如何在汇编器 x86 函数调用中传递参数? [英] How can I pass parameters in assembler x86 function call?

查看:85
本文介绍了如何在汇编器 x86 函数调用中传递参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

看看这个汇编代码.它是为 32 位 x86 设计的,将由 nasm 编译

Look at this assembler code. It is designed for 32 bits x86 and will be compiled by nasm

   ...
   my_function:
        pop %eax
        ...
        ret


   main:
       push 0x08
       call my_function

我很久以前就知道我们可以使用堆栈在主程序和函数之间传递参数.

I have learned a long time ago that we can use stack for passing parameters between main program and functions.

我希望 eax 包含 0x08,但这是错误的,我无法解释原因.

I would expect that eax contains 0x08, but this is false and I can not explain why.

我应该如何获取我的函数参数?

How should I do for fetching my function parameters ?

推荐答案

首先,如果您希望与平台上的其他语言或库进行交互,请务必阅读为该平台定义的接口.可以使用多种调用机制.

Firstly, if you are looking to interface with other languages or libraries on your platform, be sure to read the defined interface for that platform. There are a variety of calling mechanisms that might be used.

在您的情况下,call 指令将返回地址推入堆栈.您可以使用一些算术和 esp 来访问您的参数.我将假设 32 位代码(和 32 位堆栈宽度),因为您使用的是 eax.我正在使用英特尔语法,因为我可以在不查找任何内容的情况下编写它:

In your case, the call instruction is pushing the return address onto the stack. You can access your parameter by using some arithmetic and esp. I will assume 32 bit code (and a 32 bit stack width) since you are using eax. I'm using intel syntax since I can write that without looking anything up:

my_function:
    mov eax, [esp+4]    ; Move the contents of ESP+4 into EAX
                        ; ESP should be pointing at the 32 bit RIP.
                        ; ESP+4 should be the pushed parameter.
    ...
    ret


main:
   push 0x08
   call my_function

在您的评论中,关于此答案,您询问这是否表示内存泄漏.答案是不."原因是调用者负责清理它添加到堆栈中的任何内容.基于已编写的其他评论的更完整示例可能如下所示:

In your comments you ask, regarding this answer, if this represents a memory leak. The answer is "No." The reason is that the caller is responsible to clean up anything that it adds to the stack. A more complete example based on the other comments that have been written might look like this:

my_function:
    push ebp            ; Store the current stack frame
    mov  ebp, esp       ; Preserve ESP into EBP for argument references
    and  esp, 0xfffffff0; Align the stack to allow library calls
    mov  eax, [ebp+8]   ; Move the contents of EBP+8 into EAX
                        ; [EBP] should be the saved 32 bit EBP.
                        ; [EBP+4] should be the 32 bit EIP (return address).
                        ; [EBP+8] should be the pushed parameter.
    ...                 ; Do lots of cool stuff
    mov  esp, ebp       ; Restore the stack and ebp
    pop  ebp
    ret


main:
   push 0x08
   call my_function
   pop ebx              ; Clean up the stack

请注意,当我们将堆栈(如果您不确定为什么会发生这种情况,当您研究平台的调用标准时会很快找到)对齐到 16 字节边界时,我们甚至不会尝试找出 esp 发生了多少变化.由于 ebp 将充当我们的书签",我们可以让 esp 移动以进行对齐或局部变量分配,而无需再考虑.

Notice that when we align the stack (if you're not sure why this is happening, you will quickly find it when you research the calling standard for your platform) to a 16 byte boundary, we don't even try to figure out how much esp has changed. Since ebp will act as a "bookmark" for us, we can let esp move for alignment or perhaps local variable allocation without another thought.

在函数epilogue中,我们将ebp移回esp,当函数被调用时,它会将esp恢复到它的原始值,从而清理完成任何已发生的本地分配和对齐操作.最后,我们从堆栈中pop ebp,将返回地址指针作为函数内堆栈上的最终值.我们现在回来.

In the function epilogue we move ebp back into esp, which restores esp to its original value when the function was called, thus cleaning up any local allocations and alignment operations that have happened. Finally, we pop ebp off of the stack, leaving the return address pointer as the final value on the stack within the function. We now return.

回来后,我们用砰的一声清理干净.

After returning we clean up with a pop.

或者,可以通过返回指定要在堆栈上释放的字节数来清理堆栈(例如 ret 4).这完全取决于您的调用标准是指定调用方清理还是被调用方清理.

Alternatively, it is possible to clean up the stack with a return specifying the number of bytes to free on the stack (eg ret 4). It all depends on whether your calling standard specifies caller cleanup or callee cleanup.

这篇关于如何在汇编器 x86 函数调用中传递参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆