如何将变量传递给外部汇编函数
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 位等。
最好查看您正在使用的编译器的输出,了解参数是如何传递的,并采取相应的适当方式在您的程序集中接受参数。因此,如果它被压入堆栈,则期望它在那里,如果它通过寄存器传递,则期望它在那里...
您可以使用反汇编器或调试器查看输出。
如何将变量从 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 位等。
最好查看您正在使用的编译器的输出,了解参数是如何传递的,并采取相应的适当方式在您的程序集中接受参数。因此,如果它被压入堆栈,则期望它在那里,如果它通过寄存器传递,则期望它在那里...
您可以使用反汇编器或调试器查看输出。