Wikipedysta:Doles/Programy/Program nr2
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