Jatkamme edellisen viikon linjoillai eli x86-assemblyllä. Nouda alla oleva koodirunko tästä.
;TIEA325
;Jani Kurhinen
;9.4.2008
;fibocalc.asm
;
;Valmiin koodin on tarkoitus vastata seuraavanlaista C-kielistä koodia
;
;int fibonacci(int i)
;{
; if (i==1 || i==2)
; return 1
; return finonacci(i-1) + fibonacci(i-2);
;}
;
;
;Käännä jalavassa komennolla
;nasm -f elf calcfibo.asm
;Lisäksi tarvitset myös pääohjelman, joka kutsuu tätä modulia.
;Linkitys gcc:n avustuksella esim.
;gcc -m32 -o calc calcfibo.o mainmodule.o
;
;ebp on ohjelmalohkon pinomuistialueen alkuosoitin
;esp on pino-osoitin
;*push ja pop-käskyt muokkaavat esp:tä, mutta sitä voi myös itse käpistellä
;*HUOM! x86:ssa pino kasvaa "alaspäin"
;eax on akkurekisteri, johon aritmeettiset operaatiot tallentavat tuloksensa.
;Myös aliohjelmat palauttavat arvonsa akussa.
;
;Yleiskäyttöisiä rekistereitä käytettäessä on syytä huomioida, että
;aliohjelmilla on lupa muuttaa rekistereiden EAX,ECX ja EDX sisältöä. Sen
;sijaan rekistereiden EBX, EDI sekä ESI arvojen voidaan olettaa säilyvät
;aliohjelmakutsun yli!
;
;
;Koodirunko palauttaa pinossa välitetyn parametrin mukaisen fibonaccin
;luvun, ja siinä on valmis toteutus 1. ja 2. luvulle.
;
;Alla tarvittavia komentoja
;
;cmp vertaa Esim. cmp eax,1
;je hyppää, jos samat Esim. je R1
;jmp pakotettu hyppy Esim. jmp R1
;sub Vähennyslasku Esim. sub eax,2
;dec Vähennä yhdellä Esim. dec eax
;add Yhteenlasku Esim. add esp,4
;mov Siirrä sisältö Esim. mov ebx,eax
; Siirrä osoittesta Esim. mov eax,[ebp+12]
;push Lisää pinoon Esim. push eax
;pop Poista pinosta Esim. pop ebx
;call Aliohjelmakutsu Esim. call fibonacci
;ret Aliohjelmasta paluu Esim. ret
;
;Keosta varattavat muistilohkot. Kukin label on osoite.
SECTION .data
;Varsinainen koodi tulee tähän.
SECTION .text
R1: ;Hyppyviite eli label
mov eax,1 ;Akkuun arvo 1
RETURN: ;Hyppyviite eli label
mov esp,ebp ;Palautetaan pino-osoitin,
pop ebx ;EBX, sekä
pop ebp ;kantaosoitin alkuperäisiin arvoihin
ret
global fibonacci ;komponentin entrypointti.
fibonacci: ;Hyppyviite eli label
push ebp ;Vanha basepointteri talteen pinoon
push ebx ;BX:n arvo talteen
mov ebp,esp ;basepoitterille uusi arvo nykyisen pinon päältä
sub esp,8 ;Varataan tilaa kahdelle dword-muuttujalle (integer)
mov eax, [ebp+12] ;parametri akkuun
cmp eax,1 ;verrataan akussa olevaa tulosta lukuun 1
je R1 ;Hypätään, jos sama.
mov eax, [ebp+12] ;parametri akkuun
cmp eax,2 ;verrataan akussa olevaa tulosta lukuun 2
je R1 ;Hypätään, jos sama.
;
;Jos tänne päädytää, on parametri siis suurempi kuin 2
;Täydennä siten, että koodi kutsuu rekursiivisesti
;itseään.
;
jmp RETURN ;ehdoton hyppy poistumisrutiiniin
Alla olevaa koodi kutsuu fibocalc:ia arvolla 6
extern printf;Myös assemblerissa voidaan käyttää ulkoisia funtioita.
;Tämä vastaa C-kielen funktion esittelyä.
extern fibonacci
SECTION .data
print_string: db "Tulos on %d",10,0 ;Merkkijono, rivinvaihto ja loppunolla.
SECTION .text
global main
main: ;Tässä on main-label, ei siis tuo ylempi direktiivi.
push ebp ;Vanha basepointteri talteen pinoon
mov ebp,esp ;basepoitterille uusi arvo nykyisen pinon päältä
sub esp,8 ;Varataan tilaa parille dwordille
mov eax,6 ;Vakio 6 akkuun
push eax ;Parametri pinoon
call fibonacci
add esp,4 ;Parametrin poisto pinosta
mov [ebp-4],eax;Tallennetaan tulos paikalliseen muuttujaan.
;TULOSTUS#################
push dword [ebp-4] ;Parametrit pinoon aliohjelmakutsua varten.
push dword print_string
call printf
add esp,8; ;Parametrien poisto pinosta aliohjelman jälkeen
;END###############
mov esp,ebp ;Palautetaan stackpoitteri ja
pop ebp ;basepointteri alkuperäisiin arvoihin
mov eax,0 ;Lopetetaan ohjelma nollalla
ret
Täydennä fibocalc.asm siten, että sillä voidaan laskea enemmän kuin kaksi ensimmäistä lukua.
Oppikirjojen mukaan parametrit välitetään pinossa. Käytännössä näin ei kuitenkaan ole, vaan kääntäjät käyttävät rekistereitä mahdollisimman paljon hyväkseen. Muuta koodia siten, että käytät parametrin välitykseen rekisteriä EDI. Huomaa, että kokonaan ilman pinoa et selviä, sillä EDI:n arvo ei saa muuttua aliohjelmakutsun aikana. Joudut siis käyttämään paikallista muuttujaa apuna.