Tällä kertaa kokeilemme assembler-ohjelmointia x86-alustalla. Alla olevan koodin voit ladata tästä.
;TIEA325 ;Jani Kurhinen ;2.4.2008 ;calc.asm ; ;Vastaa seuraavanlaista C-kielistä koodia ; ;#include <stdio.h> ;int calc(int i, int j, int k) ;{ return (i+j)*k;} ; ;int main(void) ;{ ; int a=1; ; int b=2; ; int c=3; ; int d; ; d=calc(a,b,c); ; printf("Tulos on %d\n",d); ; return 0; ;} ; ;Käännä jalavassa komennolla ;nasm -f elf calc.asm ;ja linkitä gcc:n avustuksella ;gcc -m32 -o calc calc.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. ; extern printf;Myös assemblerissa voidaan käyttää ulkoisia funtioita. ;Tämä vastaa C-kielen funktion esittelyä. SECTION .data print_string: db "Tulos on %d",10,0 ;Merkkijono, rivinvaihto ja loppunolla. SECTION .text calc: ;Hyppyviite eli label push ebp ;Vanha basepointteri talteen pinoon mov ebp,esp ;basepoitterille uusi arvo nykyisen pinon päältä mov eax,[ebp+8];1.parametri add eax,[ebp+12];2.parametri imul eax,[ebp+16];3.parametri mov esp,ebp ;Palautetaan stackpoitteri samaan arvoon kuin tullessa. pop ebp ;Palautetaan basepoitteri (stackpointer muuttuu myös) ret ;Palataan kutsupaikkaan. global main ;main komponentin entrypointti. 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,16 ;Varataan tilaa neljälle dword muuttujalle (integer) ;Tilaa on siis [ebp] -- [ebp-16] mov dword [ebp],1 ;Sijoitetaan arvot muuttujille a mov dword [ebp-4],2 ;b ja mov dword [ebp-8],3;c push dword [ebp-8] ;Valmistaudutaan aliohjelmakutsuun push dword [ebp-4] ;viemällä parametrit pinoon. push dword [ebp] ;Huomaa järjestys! call calc ;Aliohjelmakutsu add esp,12 ;Stackpointteri 3 dwordiä taaksepäin mov [ebp-12],eax ;Neljäs (d) muuttuja paikoillensa pinoon push eax ;Parametrit pinoon aliohjelmakutsua varten. push dword print_string call printf add esp,8; ;Paramertien poisto pinosta aliohjelman jälkeen mov esp,ebp ;Palautetaan stackpoitteri ja pop ebp ;basepointteri alkuperäisiin arvoihin mov eax,0 ;Lopetetaan ohjelma nollalla ret ;
Kasaa ja suorita esimerkkikoodi
Tee "aliohjelma" plus1, jota kutsutaan "calc"in ja "printf":n välissä. Aliohjelmalle annetaan parametrina muuttuja d. Aliohjelman tulee lisätä parametrinsa arvoa yhdellä ja palauttaa tulos akussa. Arvon kasvattamiseen yhdellä on käskysana "inc".
Muokkaa koodia siten, että välität neljännen muuttujen aitona viittauksena. Eli muutat arvoa suoraa sen sijaan, että palautat arvon akussa ja siirrät se sitten paikoilleen.