开发者

Is this the proper method for passing variables on the stack?

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜