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.