y86-64 Arkkitehtuuri¶
Osaamistavoitteet: y86-64 prosessorin assembly-kieltä käytetään kurssilla havainnollistamaan käskyn suoritusta prosessorissa. Lisäksi sitä käytetään simulaattorin avulla harjoitustehtävien ja -työn ohjelmoinnissa. Tämän materiaalin luettuaan opiskelija tuntee y86-64-prosessorin ohjelmoijalle näkyvän arkkitehtuurin ja sen assembly-kielen syntaksin sekä osaa laatia pienimuotoisia assembly-kielisiä ohjelmia.
y86-64 prosessoriarkkitehtuuri on siis 64-bittinen, josta seuraa että muistipaikat ja rekisterit ovat 64-bittisiä. Näin ollen sanan pituus on 8 tavua. Lukuesitys on 2-komplementti ja bittijärjestys on big endian, eli MSB-bitti on merkkibitti. Tavujärjestys taas on little endian, eli vähiten merkitsevä tavu tulee ensin.
Rekisterit¶
Prosessorissa on useita rekistereitä, joista osalle on määritelty käyttötarkoitus:
- Yleiskäyttöisiä:
%rax
,%rcx
,%rdx
,%rbx
,%rsi
,%rdi
,%r8
-%r14
- Pinon alkupään osoite:
%rbp
- Pinon osoitinrekisteri:
%rsp
- Suorittimen tilarekisteri
- Ohjelmalaskuri (Program counter, PC) sisältää seuraavan suoritettavan käskyn muistiosoitteen.
Assembly-kielessä
%
-merkki ilmaisee, että kyse on ohjelmallisesti käytettävästä rekisteristä.Prosessorin tila¶
Prosessorin tila on oleellinen asia ohjelmien suoritusta, koska konekielen käskyt muuttavat ja reagoivat prosessorin tilaan. Tila esitetään tilabittejä, joita varten on varattu erillinen tilarekisteri. Suoritin asettaa tilabitin kun se saa keskeytyksen, Käsky voi asettaa tilabitin huomattuaan virheellinen toiminnon, joihin kontrolliyksikkö reagoi. Myös konekielisen ohjelman ehdollinen toiminta (vertailuoperaattorit jne) perustuvat tilarekisterin arvoon.
y86:sessa on kolme tilabittiä (lippua, Condition codes, CC):
ZF
(zero flag): Ilmaisee oliko edellisen ALUn suorittaman operaation tulos 0- ZF=0, tulos erisuuri kuin 0
- ZF=1, kun tulos on 0
Esimerkiksi positiivisen ja positiivisen luvun vähennyslasku 01111111 - 01111111 -------- 00000000 ZF=1, koska tulos on 0
SF
(Sign flag): Edellinen ALUn operaation tulos negatiivinen?- SF=0, tulos > 0
- SF=1, tulos < 0
Esimerkiksi positiivisen ja negatiivisen luvun yhteenlasku 00001111 10000001 -------- 10010000 Nyt MSB on 1, tulos on negatiivinen -> SF=1
OF
(Overflow flag): Ilmaisee tapahtuiko operaatiossa ylivuoto. Ylivuoto tarkoittaa sitä, että laskutoimitus ei mahdu tulosrekisterin lukualueeseen.- OF=0, ei ylivuotoa
- OF=1, ylivuoto tapahtui
Lasketaan yhteen kaksi positiivista lukua ja tulos on negatiivinen: 01111111 01111111 -------- 11111110 Tulos ei mahdu positiiviseen lukualueeseen, vaan on negatiivinen luku -> OF=1 Lisäksi -> SF=1 Lasketaan yhteen kaksi negatiivistiä lukua ja tulos on positiivinen: 10000001 + 10000001 -------- 100000010 MSB leikkautuu pois 00000010 Tulos on positiivinen luku -> OF=1
Oikeissa prosessoreissa tilabittejä on useita, esimerkkinä 8086:n 16-bittinen tilarekisteri.
Osana tilarekisteria on y86:n ohjelman suorituksen tila (status code,
STAT
), joka voi olla:AOK
: Kaikki okHLT
: Prosessori pysähdyksissäADR
: Osoitettiin väärään muistiosoitteeseenINS
: Käskyssä virhe / väärä käsky
Osoitusmuodot¶
Assembly-kielessä voidaan käskyn operandeilla osoittaa muistia eri tavoin. Käskyn suorituksen yhteydessä prosessori tulkitsee osoitusmuodosta mistä sen tarvitsema data löytyy.
y86:sessa on kolme osoitusmuotoa:
- Suora osoitus (Immediate) vakioarvoille:
$numero
. Esimerkiksi$-577
tai$0x1F
. - Rekisteriosoitus (Register) jossa operandi on rekisterin sisältö:
%rekisteri
. Esimerkiksi%rax
käyttäisi käskyn suorituksessa tämän rekistern arvoa. - Epäsuora osoitus (Memory) jossa operandi haetaan rekisterin osoittamasta muistipaikasta:
(%rekisteri)
. Epäsuora osoitus merkitään sulkeilla, esimerkiksi(%rax)
. - Sulkeiden edessä voi vielä olla numero
n(%rekisteri)
(base + displacement), jossa tapauksessa osoitetaan muistipaikkaarekisterin arvo + n
. Tätä käytetään tyypillisesti pinomuistin lukemisessa. Esimerkiksi4(%rbp)
lukisi tiedon muistipaikasta %rbp+4. - Tätä osoitusmuotoa vastaa C-kielen osoitin, eli (%rax) voisi olla C-kielessä *rax
Pino-muisti¶
Pino (engl. stack) on keskusyksikölle käyttömuistista varattu muistialue, johon varastoidaan tietoa LIFO-periaatteella (Last in -> First out). Pinoon
push
-käskyllä viedyt arvot päätyvät aina sen päällimäisiksi, josta nimitys pino. Pinosta luetaan pop
-käskyllä arvoja aina päällimmäinen arvo edellä, jolloin se häviää pinosta. Toisinsanoen pinoon viedyt arvot luetaan sieltä käänteisessä järjestyksessä. Nyt, muistissa pino kasvaa alaspäin, eli päällimmäisellä arvolla on aina pienin muistiosoite.Ohjelmoija voi päättää assembly-kielisen ohjelman pinon koon. Pino-muistia käytetään yleisesti tiedon varastointipaikkana, esimerkiksi aliohjelmia suorittaessa tai taulukkomuuttujia käsitellessä (ja joskun rekisterit loppuvat..).
Pino-muistin osoittamiseen on varattu ylläkuvatut kaksi rekisteriä
%rbp
ja %rsp
. Ohjelman alussa asetetaan pinomuistin alkupään osoite. Pino-muistin nykyisen muistipaikan osoittimen arvo muuttuu käskyn suoritusten mukaan. Hox! Koska pino sijaitsee samassa muistissa kuin koodi ja data, pitää olla tarkkana ettei se sotkeudu niiden kanssa päällekäin!
Muisti¶
Lisäksi prosessorissa on muistia 8-tavun muistipaikkoina. Simulaattorissa muistia on käytössä pari kiloa.
y86-64 Assembly-kieli¶
y86-64:sen sybtaksi ja käskykanta ovat perusteiltaan hyvin samankaltaisia kuin x86. Pienillä muutoksilla ohjelmia voi käyttää molemmissa suorittimissa! Toki on huomattava ettei läheskään kaikkia x86-perheen assembly-käskyjä ole toteutettu y86-64:sessa.
y86-assemblyn käskyt päättyvät usedin kirjaimeen
q
, joka tarkoittaa sitä että käskyn käsittelemä luku on 64-bittinen (quad). 32-bittistä lukua voisi merkitä kirjain l, jossain toisessa arkkitehtuurissa (lue x86).Pino¶
Jokaisessa ohjelmassa meidän tulee ensin määrittää pinon paikka. Ok, kirjaimellisesti ihan välttämätön se ei ole, pystymme toteuttamaan pieniä ohjelmia ilmankin. Kurssilla opettelemme pinon käytön, koska ilman sitä aliohjelmat eivät toimisi.
Pinon hallintaan tarvitaan avuksi rekistereitä, jotka osoittavat mistä pino muistissa alkaa
%rbp
, sekä osoitinrekisteri %rsp
, johon tallennetaan pinon päällimäisen arvon osoite. Pinon alustus ohjelmamme alussa tapahtuu seuraavasti:
.pos 0
irmovq Pino,%rbp # Pinon alkuosoite rekistereihin
irmovq Pino,%rsp # Pinon nykyisen muistipaikan osoite
.pos 0x100
Pino:
Ohjelman tarkempi toiminta selviää materiaalista alla, mutta ohjelmassa olemme nimenneet muistiosoitteen
0x100
nimellä Pino
. Ikäänkuin siis C-kielen #define-esikääntäjäkäsky. Ohjelman ensimmäisissä käskyissä sitten viemme tämän muistiosoitteen pinon rekistereihin. Nyt siis pinomuistin ensimmäinen osoite on 0x100. Muistetaan että pino kasvaa alaspäin, jolloin sen muistiosoite siis pienenee. Pinoa käsitellään kahdella käskyllä:
- Pinoon viemme tavaraa
pushq
käskyllä, joka ottaa operandikseen sen rekisterin arvon, mistä arvo haetaan. Pino-osoittimen osoittamasta kohtaan muistia tallennetaan rekisterin arvo ja päivitetään pino-osoitinta vastaavasti. - Pinosta haetaan tavaraa
popq
-käskyllä, joka tallentaa pino-osoittimen osoittamasta kohdasta arvon operandina annettuun rekisteriin.
Esimerkki. Haemme pinomuistista pino-osoittimen (
%rsp
-rekisteri) osoittamasta paikasta arvon rekisteriin %rsi
ja viemme arvon takaisin pinoon. irmovq $0xab,%rsi
pushq %rsi
...
popq %rsi
Pinon käsittelykäskyt päivittävät itse pino-osoitinta, joten sitä ei tarvitse koodissa tehdä.
Aritmeettiset operaatiot¶
Aritmeettisiä operaatiota on vain! neljä erilaista.. Nämä käskyt ottavat kaksi operandia, joiden tulee olla rekistereitä. Prosessorin tilabitit asettuvat operaation tuloksen mukaan.
addq %r1,%r2
: yhteenlaskur2 = r2 + r1
subq %r1,%r2
: vähennyslaskur2 = r2 - r1
andq %r1,%r2
: JA-operaatior2 = r2 & r1
xorq %r1,%r2
: ERI-operaatior2 = r2 ^ r1
Esimerkkejä.
addq %r10,%rsi # %rsi = %rsi + %r10
subq %r9,%rsi # %rsi = %rsi - %r9
andq %rax,%rbx # %rbx = %rax & %rbx
xorq %rsp,%rbp # %rbp = %rsp ^ %rbp
Siirtokäskyt¶
Sijoitusoperaatiota, esimerkiksi C-kielessä arvon sijoittamista muuttujaan, assembly:ssä vastaa siirto-operaatio.
Dataa voidaan siirtää kahdella tavalla: siirtokäskyillä ja ehdollisilla siirtokäskyillä. Siirtokäskyjen operandien tyyppi riippuu käskystä, kaikki osoitusmuodot ovat käytössä. Huomioitavaa on, ettei siirtoja voi tehdä muistiosoitteesta toiseen tai vakioarvoa ei voi viedä suoraan muistiin. Aina mennään jonkin rekisterin kautta.
Siirtokäskyjä on neljä erilaista. Käskyn
xxmovq
nimessä edessä olevat kaksi kirjainta xx
ilmaisevat käskyn operandin tyypin. irmovq
: vakioarvo (i=immediate) rekisteriin (r=register):i->r
rrmovq
: rekisteristä rekisteriinr->r
mrmovq
muistista (m=memory) rekisteriinm->r
rmmovq
: rekisteristä muistiinr->m
Nämä käskyt ottavat kaksi operandia, eli mistä siirretään (source) ja minne siirretään (destination).
Esimerkkejä.
Esimerkkejä.
irmovq $4 , %rsi # Sijoitetaan numeroarvo 4 rekisteriin %rsi
rrmovq %rax , %rsp # Sijoitetaan %rax:n arvo %rsp:hen
mrmovq (%rdi), %r10 # Haetaan arvo rekisterin %rdi osoittamasta paikasta ja sijoitetaan %r10:n
rmmovq %rcx , 8(%rdx) # Sijoitetaan %rcx:n arvo osoitteeseen %rdx:n arvo + 8
Ehdollisia siirtokäskyjen toiminta riippuu prosessorin tilabittien arvoista, siitä siis ehdollisuus. Eli, edellisen käskyn suorituksen jälkeisestä tilasta päätellään tehdäänkö siirot vai ei. Käskyt ottavat operandeikseen rekistereitä. Käskyt ensin lukevat operandista arvon ja siirtävät sen toiseen operandiin (rekisteriin) vain jos haluttu ehto on totta tilabittien mukaan.
Ehdollisia siirtokäskyjä ovat.
cmove
(equal): toteutuu kunZF=1
cmovne
(not equal): toteutuu kun~ZF
, eli ZF=0cmovl
(less): toteutuu kunSF^OF
cmovle
(less or equal): toteutuu kun(SF^OF) | ZF
cmovge
(greater or equal): toteutuu kun~(SF^OF)
cmovg
(greater): toteutuu kun~(SF^OF) & ~ZF
Kuten huomataan, ehdollisten siirtokäskyjen logiikka on mielenkiintoinen. Esimerkiksi, yhtäsuuruus todetaan aritmeettisellä operaatiolla, jonka lopputulos on 0. Takana tässä on ajatus, että näin suorittimen kombinaatiologiikan toteutus olisi mahdollinen yksinkertainen. Seurauksena sitten assembly-ohjelmoijan täytyykin miettiä esim. vertailuoperaatiot suorittimen näkökulmasta eikä omastaan..
Esimerkki.
.pos 0
main:
irmovq $3,%rax # a=3
irmovq $2,%rbx # b=2
# Testataan a == b ?
subq %rax,%rbx # Vähennyslaskulla rbx = rbx - rax
# Jos rbx > rax, tilaliput eivät muutu
# Jos rbx < rax, SF=1 ja OF=1
# Jos rbx = rax, ZF=1
cmove %rax,%rcx # Nyt jos ZF=1, sijoitetaan rcx = rax
# Muutoin ei sijoitusta
Tämä toteutus voidaan tehdä myös pinoa käyttäen niin, että a:n arvo pistetään talteen pinoon.
Ehdolliset siirtokäskyt voivat optimoida prosessorin toimintaa, josta lisää myöhemmin..
Hyppykäskyt¶
Hyppykäskyjä on seitsemän erilaista. Hyppykäskyssä ei itsessään vertailla mitään, vaan ne tekevät hyppypäätöksen edellisen käskyn asettamien tilabittien perusteella. Operandiksi hyppykäskylle annetaan muistiosoitteen nimi, mihin se ehdon toteutuessa hyppää.
jmp
: Hyppää ehdoittaje
yhtäsuuri (equal) toteutuu kunZF=1
jne
erisuuri (not equal) toteutuu kun~ZF eli ZF=0
jle
pienempi tai yhtäsuuri (less or equal) toteutuu kun(SF^OF) | ZF
jl
pienempi (less) toteutuu kunSF^OF
jge
suurempi tai yhtäsuuri (greater or equal) toteutuu kun~(SF^OF)
jg
suurempi (greater) toteutuu kun~(SF^OF) & ~ZF
Esimerkki. C-kielen silmukkarakenne:
int64_t rcx = 10; // Silmukkamuuttuja
int64_t rdx = 1; // apumuuttuja (jolla vähennetään 1)
while (rcx !=0) { // Testaus rcx != 0
tee_jotain(); // Aliohjelmakutsu
rcx = rcx - rdx; // Vähennyslasku rcx = rcx - rdx
}
Ja sama y86-assemblyllä:
irmovq $0x10,%rcx # Silmukkamuuttuja
irmovq $0x1,%rdx # apumuuttuja (jolla vähennetään 1)
loop:
call tee_jotain # Aliohjelmakutsu, kts alla.
subq %rdx,%rcx # Vähennyslasku rcx = rcx - rdx: jos rcx = 0 -> ZF=1
jne loop # Testaus rcx != 0: Jos erisuuri, eli ZF=0, hyppää loop
halt # Muutoin lopeta ohjelma
(Tietenkään C-kielessä ei tarvita apumuuttujaa
rdx
, vaan silmukkamuuttujan koodi voisi olla rcx--
, mutta y86-assembly-kielessä ei ole vastavaa aritmeettistä operaattoria.)Aliohjelmat¶
Assembly-kielessä voidaan toki kutsua ohjelmasta myös aliohjelmia (ts. funktioita). Voimme sijoittaa aliohjelman koodin haluamaamme paikkaan muistissa, mutta meidän pitää lisäksi huomioida seuraavat asiat.
- Aliohjelman suoritus tehdään hyppykäskyllä sen muistiosoitteeseen, josta paluu takaisin kutsuvaan koodiin
- Muuttujien (ts. parametrien) välitys aliohjelmalle ja aliohjelman paluuarvo
- Muistin varaaminen aliohjelman paikallisille muuttujille
Nyt, assembly-kielessä rekistereitä ja/tai pinomuistia käytetään näiden kolmen asian toteutuksessa.
Yleensä on sovittu mihin rekistereihin kutsuparametrit talletetaan. Tällöin ei joka ohjelmassa tarvitse miettiä asiaa uudelleen ja lisäksi koodin uudelleenkäytettävyys paranee. x86:ssä (kyllä, x86) on sovittu, että parametrit tallennetaan rekistereihin seuraavassa järjestyksessä:
%rdi, %rsi, %rdx, %rcx, %r8, %r9
. Eli maksimissaan kuusi parametriä voidaan välittää rekisterien kautta. Aliohjelman suoritus¶
Aliohjelman suoritus assembly- (ja kone)kielessä menee seuraavasti:
- Ensiksi, ennen hyppyä aliohjelmaan tallennetaan nykyinen ohjelman tila (rekisterit + PC) pinoon. Tämä siksi, että voimme palata aliohjelmasta samaan tilaan mistä sitä lähdettiin suorittamaan. Jos esimerkiksi käytämme samoja rekistereitä pää- ja aliohjelmassa, niin aliohjelma muuttaisi niiden arvoja eikä kutsuvan suoritus aliohjelman jälkeen enää jatkuisi samasta tilasta mihin jäätiin!
- Osa rekistereistä on myös määritelty siten, että niissä olevan arvon ylläpitämisestä on vastuussa joko aliohjelman kutsuja tai aliohjelma. Jonka tulee tällöin huolehtia tilan säilymisestä.
- Aliohjelman hyppykutsu tallentaa pinoon paluuosoitteen, ts. osoitteen josta kutsuvan ohjelman suoritus jatkuu kun aliohjelman suoritus on loppunut.
- Aliohjelman parametrit voidaan välittää joko rekisterien tai pinon kautta. Jos käytetään rekistereitä, niille on sovittu järjestys jota tulisi käyttää. Eli ensimmäinen parametri menee rekisteriin x1 ja toinen parametri rekisteriin x2, jne. Koska rekistereitä on rajallinen määrä, on mahdollista välittää vain muutamia arvoja. Tähän tarjoaa pino apua, eli viemme parametrit pinoon alkaen ensimmäisestä parametristä.
- Funktion paikallisille muuttujille voidaan ennen funktion kutsua varata muistia siirtämällä pino-osoitinta eteenpäin tarvittava tavumäärä. Luemme arvot sitten pinosta käyttäen epäsuoraa osoitusta.
- Aliohjelmassa ja sitä kutsuvassa pitää huolehtia, että pinosta haetaan täsmälleen sama joukko tietoa kun sinne tallennettiin. Aliohjelmakutsussa pino on siis tilapäinen tietovarasto.
- Aliohjelmasta poistumiskäsky sitten hakee pinosta kutsuneen ohjelman seuraavan koodirivin osoitteen ja palaa suorittamaan sitä. Tässä yhteydessä prosessorin tila tulee palauttaa entiselleen.
Aliohjelmiin assembly-kielessä hypätään käskyllä
call
, jolloin operandiksi annetaan aliohjelman nimi, kts. alla. Paluuosoite, mihin aliohjelman suorituksen jälkeen palataan, tallentuu automaattisesti pinoon. Aliohjelmista palataan
ret
-käskyllä, joka kaivaa paluuosoitteen pinosta.Esimerkki yksinkertaisesta aliohjelmasta
laske
:.pos 0
init:
irmovq pino,%rsp # Pinon alustus (muistiosoitteeseen 0x100)
irmovq pino,%rbp
main: # Pääohjelma
irmovq $0x11,%rdi # Argumentit rekistereihin
irmovq $0x11,%rsi
call laske
halt
.pos 0x40
laske:
addq %rsi,%rdi # Argumentit aliohjelmassa
ret
.pos 0x100
pino:
Pinon käyttäminen parametrien välitykseen on hieman monimutkaisempaa..
Pinomuistin käyttöjärjestys aliohjelmakutsun yhteydessä, josta alla koodiesimerkki. (Kuvassa pino kasvaa alaspäin.)
Esimerkki. Tässä ei ole huomioitu aliohjelman paluuosoitetta pinossa.
.pos 0
irmovq Pino,%rsp # Alustetaan pino
irmovq Pino,%rbp
main:
irmovq $0x11,%rax
pushq %rax # vie 1. argumentti pinoon
irmovq $0x22,%rax
pushq %rax # vie 2. argumentti pinoon
pushq %rax # varataan tilaa funktion paluuarvolle
call laske # aliohjelmakutsu
popq %rax # haetaan paluuarvo
popq %rax # tyhjennetään pino
popq %rax
halt
.pos 0x40
laske:
mrmovq 24(%rsp),%rdx # haetaan 1. argumentti pinosta
mrmovq 16(%rsp),%rcx # haetaan 2. argumentti pinosta
addq %rcx,%rdx
rmmovq %rdx,8(%rsp) # paluuarvo pinoon
ret
.pos 0x400
Pino:
Kutsuva ohjelma on sitten vastuussa argumenttien ja funktion paluaarvon käsittelystä, eli sen pitää poistaa ne pinosta.
Muistin varaaminen Pinosta menee yksinkertaisesti siten, että siirrämme pino-osoitina tarvittavan tavumäärän eteenpäin.
subq $32, %rsp # Pino-osoitin siirtyy 4 sanaa x 8 tavua = 32 tavua
# Eli varattiin tilaa neljälle sanalle
Muita käskyjä¶
nop
-käsky ei tee mitään, paitsi kasvattaa PC-rekisteriä. Oikeissa prosessoreissa käskyllä on silti useita käyttötarkoituksia, mm. ajan mittaaminen ja koodin ryhmitys muistiin. halt
-käsky pysäyttää prosessorin toiminnan tähän käskyyn. Ohjelma tila STAT
asettuu tilaan HLT.Kääntämistä ohjaavat käskyt¶
Kääntämistä ohjaavat käskyt ovat seuraavat:
nimi:
Symbolinen nimi tätä seuraavalle koodilohkolle. Esimerkiksi aliohjelmalle voidaan antaa symbolinen nimi. Nimi häviää koodista käännösvaiheessa ja korvautuu varsinaisella muistiosoitteella.
Nimet eivät ole millään tavoin pakollisia, niitä voidaan käyttää auttamaan koodin jäsentämisessä. Ohjelmoijalla on tässä vapaat kädet. Yhtähyvin alla voisi lukea
oa_aasi
eikä main
. main:
...
funktio1:
...
funktio2:
...
.pos
Asettaa tätä seuraavan koodin / koodilohkon alkavan mistä tahansa annetusta muistiosoitteesta.
Ohjelman muistiosoitteiden ei tarvitse olla peräkkäin, välissä voi olla tyhjää tilaa..
.pos 0 # Koodi (tässä itse nimetty main-funktio) alkaa muistiosoitteesta 0
main:
...
.pos 0x100 # funktio1:sen koodi alkaa muistiosoitteesta 0x100
funktio1:
...
.align
tasaa muistiosoitteen annettuun sanan pituuteen.
Jos muistiin asetattavan arvon koko on pienempi kuin sana, täytetään sen perään nollia niin kauan että se vastaa sanan pituutta. Tämä on hyödyllinen ominaisuus esimerkiksi taulukkojen yhteydessä.
.align 8 # ryhmitellään muisti 8:n tavun mittaisiin osoitteisiin
.quad
-käskyllä voidaan muistiin asettaa tietoa. Asetus tapahtuu ennen koodin ajamista, eli tämä toimii ikäänkuin massamuistina, josta voimme lukea dataa.
Ensin
.pos
-käskyllä voidaan asettaa haluttu muistipaikka ja .align
käskyllä haluttu tasaus. .pos 0x80
.align 8 # ryhmitellään muisti 8:n tavun mittaisiin osoitteisiin
.quad 0x1234 # 2-tavuinen luku
.quad 0x5678 # 2-tavuinen luku
Muisti näyttää seuraavalta, koska luku tasataan sanan pituuteen.
... 0x80: 0x3412000000000000 0x88: 0x7856000000000000 ...
Lopuksi¶
Nyt kun assembly-kielen syntaksi on jo tuttua, voisi olla hyvä idea palata aiemmassa materiaalissa esitettyyn x86-assembly-ohjelmaan ja käydä se uudelleen läpi.
y86-64:selle löytyy netistä vapaasti käytettävä simulaattori (Vasemmalta menusta Student site ja Chapter 4: Processor Architecture), jolle kurssilla laadimme pieniä assembly-kielisiä ohjelmia. Tämän simulaattorin voitte asentaa omalle koneella ja se onkin jo asennettu työasemaluokissa kurssin virtuaalikoneeseen TKJ_harjoitukset. Tulemme seuraavilla luennoilla käyttämään simulaattoria esimerkeissä.
Myös 32-bittinen verkkoversio on olemassa täällä, mutta siitä on tietenkin eroja 64-bittiseen versioon. Rekisterit ovat 32-bittisiä, nimeltään: %eax, %ebx, jne ja käskyt hieman eri nimisiä: addq -> addl. Tämä johtuu siitä, että tietotyyppi vaihtuu quad:stä long:iin.
Anna palautetta
Kommentteja materiaalista?