I wrote a simple program which takes a predefined number to a predefined power and returns the result. It’s in NASM assembly, for Linux. I’ve been trying to get my head around how to use the stack to pass variables to functions, and wanted to make sure I did this correctly. It returns the correct number, but I have no idea if it’s correct:
section .text
global _start
_start:
push dword 3 ;(power)
push dword 2 ;(num)
call power
mov ebx, eax
mov eax, 1
int 0x80
power:
push ebp
mov ebp, esp
sub esp, 8 ;reserve space for two local vars
push dword [ebp+8]
pop dword [ebp-4] ;store original num as a local var
push dword [ebp+12]
pop dword [ebp-8] ;store power in a local counter var
dec dword [ebp-8]
mov eax, [ebp-4] ;store original num in eax (current val)
jmp power_loop
power_loop:
imul eax, dword [ebp-4] ;multiply current val by original num
dec dword [ebp-8] ;decrement counter
cmp dword [ebp-8], 0
jne power_loop
mov esp, ebp ;restore stack pointer
pop ebp
ret
Any advice would be much appreciated!
It looks good for the most part. However, after the power returns, you should remove the variables from the stack. It doesn’t matter in these circumstances since _start doesn’t return, but it will matter if you try to call a function from a function that returns and doesn’t clean up. The return address of a function is stored on the stack and popped off by the
retinstruction, so if you have something else on the top of the stack you will return to the wrong location.If you write a function that calls a lot of other functions, it is better to allocate space for stack arguments at the beginning of the function, write to it before each function call, and remove it from the stack at the end of the function. That way, you spend less time pushing and popping because you can use
movwith the proper address instead.As a comment on your power function: It currently only works if the power is at least 2. You could change the minimum power to 0 by:
Example: