在Mac OS X上编译C和nasm时,我发现它在传递参数和进行系统调用时与Linux不同。我的代码有效,但我真的很困惑
我在nasm中编写了一个函数myprint
来打印从C传递的字符串。
这是C代码main.c
#include <stdio.h>
void myprint(char* msg, int len);
int main(void){
myprint("hello\n",6);
return 0;
}
这是nasm代码myprint.asm
section .text
global _myprint
_syscall:
int 0x80
ret
_myprint:
push dword [esp+8] ;after push, esp-4
push dword [esp+8]
push dword 1
mov eax,4
call _syscall
add esp,12
ret
编译并链接它们:
nasm -f macho -o myprint.o myprint.asm
gcc -m32 -o main main.c myprint.o
它打印&#34;你好&#34;正确。
正如您所看到的,OS X(FreeBSD)使用push将参数传递给sys调用,但参数char*
和int
已经被压入堆栈,其地址为{{1} }和esp+4
。但是,我必须从堆栈中读取它们并再次将它们推入堆栈以使其工作
如果我删除
esp+8
它将打印许多错误代码和push dword [esp+8] ;after push, esp-4
push dword [esp+8]
,如下所示:
Bus error: 10
为什么需要再次将参数推入堆栈?如何在不再推送的情况下将堆栈中已有的参数传递给系统调用?
答案 0 :(得分:1)
即使是普通的C函数调用也是如此。问题是返回地址仍然在参数之前的堆栈上。如果你不再将它们推回到返回地址之下,你将在参数之前在堆栈上有2个返回地址(第一个到main
,第二个到myprint
),但是系统调用只是期望1。