我写了一个简单的程序,它将预定义的数字带到预定义的幂并返回结果。这是针对Linux的NASM程序集。我一直试图了解如何使用堆栈将变量传递给函数,并希望确保我正确地执行此操作。它返回正确的数字,但我不知道它是否正确:
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
非常感谢任何建议!
答案 0 :(得分:1)
它在大多数情况下都很好看。但是,在电源恢复后,您应该从堆栈中删除变量。在这些情况下并不重要,因为_start不返回,但是如果你试图从一个返回但不清理的函数调用一个函数,那就很重要了。函数的返回地址存储在堆栈中并由ret
指令弹出,因此如果堆栈顶部还有其他内容,则会返回错误的位置。
_start:
push dword 3
push dword 2
call power
add esp,8 ; Removes two dwords from stack
如果编写一个调用许多其他函数的函数,最好在函数开头为堆栈参数分配空间,在每次函数调用之前写入它,并在结束时从堆栈中删除它。功能。这样,您可以花更少的时间推送和弹出,因为您可以使用mov
代替正确的地址。
_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
作为对电源功能的评论:它目前仅在功率至少为2时才有效。您可以通过以下方式将最小功率更改为0:
示例:
; 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