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.