这是在堆栈上传递变量的正确方法吗?

发布于 2024-10-30 19:10:50 字数 937 浏览 2 评论 0原文

我编写了一个简单的程序,它将预定义的数字取预定义的幂并返回结果。它位于 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 

任何建议将不胜感激!

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

↘紸啶 2024-11-06 19:10:50

大部分看起来都不错。但是,在电源恢复后,您应该从堆栈中删除变量。在这些情况下这并不重要,因为 _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:

  • 从 1 开始 eax
  • 不要在循环之前递减计数器变量
  • 检查计数器是否在循环开始时为 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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文