Viikkoharjoitus 3

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		;

Tehtävä 1

Kasaa ja suorita esimerkkikoodi

Tehtävä 2

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".

Tehtävä 3

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.