如何将变量传递给外部汇编函数

How to pass variables to a external assembly function

如何将变量从 C 程序传递到汇编函数。

示例:

main.c:

void main() {
  unsigned int passthis = 42
  extern asm_function();
  asm_function(passthis)
}

main.asm:

bits 32
global start
section .text
asm_function:
  ...

如何在 asm_function 内访问 passthis

编辑:可能应该提到我没有使用 OS,我正在使用 i686-elf 交叉编译器进行编译并将其用作内核。

如果您使用默认的 GCC 选项将 C 编译成 32 位代码(不像 Linux 内核使用的 -mregparm=3),那么在函数入口处第一个参数只是在堆栈上在 return 地址之上(在 [esp+4]),但是在你 push 任何东西或移动 ESP 之后那个偏移量会改变。

您可以在设置传统堆栈指针后使用 [ebp+8](即使 ESP 发生变化,该指针在函数运行期间也不会发生变化)。

例如,int asm_function(int)可以实现为:

;bits 32              ; unneeded, nasm -felf32 implies this.
global asm_function   ; include asm_function in ELF .o symbol table for linking
section .text
asm_function:
    push ebp
    mov ebp, esp
    mov eax, [ebp+8]  ; return the first argument
    mov esp, ebp
    pop ebp
    ret

对于此后的每个参数,只需简单地添加另一个 4(即对于第二个参数,使用 [ebp+12])。如您所见,将 EBP 设置为帧指针会为微型函数增加大量开销。

一些非 ELF systems/ABIs 在 C 符号名称前加上一个前导下划线,因此您应该声明 asm_function_asm_function 以使您的代码在这些 ABI 中大致相同,像这样:

global _asm_function
global asm_function  ; make both names of the function global
section .text
_asm_function:
asm_function:        ; make both symbols point to the same place
    push ebp
    mov ebp, esp
    mov eax, [ebp+8]
    mov esp, ebp
    pop ebp
    ret

x86 可能有一些不同的调用约定。这取决于许多因素,例如 windows 与 linux,以及您使用的编译器环境,32 位与 64 位等。

最好查看您正在使用的编译器的输出,了解参数是如何传递的,并采取相应的适当方式在您的程序集中接受参数。因此,如果它被压入堆栈,则期望它在那里,如果它通过寄存器传递,则期望它在那里...

您可以使用反汇编器或调试器查看输出。