Przejdź do zawartości

Wikipedysta:Doles/Programy/Program nr2

Z Wikibooks, biblioteki wolnych podręczników.

Do poprawienia komentarze i może jakieś rysunki jak wygląda stos po wszystkich kombinacjach. I powiedzieć, że sam program ma konwencję przekazywania argumentów wg języka C

;PRZEZNACZENIE: program oblicza wartosc wyrażenia 2^3 + 5^2 przy użyciu napisanej funkcji "power"
;WEJSCIE: wszystko będzie zaszyte na sztywno w programie a także umieszczone w rejestrach zatem
;	  nie będzie potrzebny w ogóle segment danych
;WYJŚCIE: w postaci kodu błędu w rejestrze EBX zwrócona zostanie wartość podanego wyżej wyrażenia.
;	  Będzie można ją odczytać po wykonaniu programu poleceniem echo $?
format ELF executable
entry _start

segment readable executable
_start:
	push 3
	push 4
	call power
	add esp, 8
	
	push eax ;wynik funkcji call jest w rejestrze EAX, my chcemy go zachowac
		;zatem musimy odlożyć go na stos zanim wywolamy funkcje call ponownie
		;poniewaz ona zamarze nam jego wartosc
	
	;drugie wywołanie funkcji call
	push 5
	push 6
	call power
	add esp, 8
	
	pop ebx; w rejestrze EAX jest już wynik drugiego wywołania, a do rejestru EBX ładujemy wartość starego 
	      ; EAX która była wcześniej odłożona na stosie, teraz pozostało nam tylko dodać je do siebie
	add ebx,eax ;dodajemy
	mov eax,1
	int 80h; i zwracamy jako kod błędu
;END OF _START
;************************************************************
;PRZEZNACZENIE: ta funkcja oblicza wartość liczby podanej w pierwszym arguemencie do potęgi o wartości z drugiego
;		argumentu
;WEJŚCIE:
;	pierwszy argument - podstawa potęgi
;	drugi argument -wykładnik potęgi
;WYJŚCIE: 
;	wartosc liczby podniesionej do potegi
;ZMIENNE:
;	EBX - podstawa potegi
;	ECX - potega
;	[EBP -4] - miejsce na stosie gdzie bedzie wynik
;	EAX - tymczasowe przechowanie wartosci
power:
	push ebp ;utworzenie ramki stosu, wszystko ponizej jest lokalne dla funkcji
	mov ebp, esp ;niech oba rejestry beda sobie rowne
	sub esp,4 ;zrobienia miejsca na stosie dla jedneo DD, czyli naszej zmiennej lokalnej
	mov ebx, [ebp+8] ;innymi slowy "zaladuj EBX na wartosc podstawy"
	mov ecx, [ebp+12] ;zaladuj ECX na wartosc potęgi
	mov [ebp-4], ebx ;na początek umieść podstawę potęgi w naszym zarezerwowanym miejscu
	;mov eax,ecx
power_start:
	cmp ecx,1 ;sprawdż czy licznik == 0
	je end_power ; jeśli tak to koniec
	mov eax,[ebp-4] ;przenieś tymczasową wartość z mnożenia do EAX
	imul eax,ebx ;rozkaz mnożenia liczb całkowitych ze znakiem ma inne operandy niż zwykłe mull
	mov [ebp-4],eax ;wynik mnożenia przenieś do specjalnego miejsca na stosie
	dec ecx ;zmniejsz ECX o 1
	jmp power_start ;bezwarunkowo skocz do początku pętli

end_power:
	mov eax,[ebp-4] ;wynik naszego mnożenia (de facto potęgowania) zapamiętujemy w EAX
	mov esp,ebp ;wyrównaj ESP do wartość EBP czyli "zwiń stos"
	pop ebp ;zdejmij ze stosu odłożoną wcześniej wartość EBP, innymi słowy zlikwiduj nasz "słupek graniczny"
	ret ;powrót z funkcji, RET zdejmuje wartość adresu powrotu