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 l开发者_开发知识库ocal 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 ret
instruction, so if you have something else on the top of the stack you will return to the wrong location.
_start:
push dword 3
push dword 2
call power
add esp,8 ; Removes two dwords from stack
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 mov
with the proper address instead.
_start:
sub esp,8 ; Make room for two dwords
mov dword [esp+4], 3
mov dword [esp], 2
call power
add esp,8 ; Removes two dwords from stack
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:
- Start eax at 1
- Don't decrement the counter variable before the loop
- Check to see if the counter is 0 at the beginning of the loop
Example:
; dec dword [ebp-8] ; Don't do this
mov eax, dword 1
jmp power_loop
power_loop:
cmp dword [ebp-8], 0
je end_loop
imul eax, dword [ebp-4] ;multiply current val by original num
dec dword [ebp-8] ;decrement counter
jmp power_loop
end_loop:
mov esp, ebp
精彩评论