【发布时间】:2014-06-26 03:53:52
【问题描述】:
在 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
它正确打印“你好”。
如您所见,OS X(FreeBSD) 使用 push 将参数传递给 sys 调用,但参数 char* 和 int 已经被压入堆栈,它们的地址是 esp+4 和 esp+8。但是,我必须从堆栈中读取它们并将它们再次推入堆栈以使其工作。
如果我删除
push dword [esp+8] ;after push, esp-4
push dword [esp+8]
它会打印很多错误代码和Bus error: 10,像这样:
???]?̀?j????????
?hello
`44?4
__mh_execute_headerm"ain1yprint6???;??
<??
(
libSystem.B?
`%?. _syscall__mh_execute_header_main_myprintdyld_stub_binder ??z0&?z?&?z?&?z۽??۽????N?R?N?o?N???N??N?e?N?h?N?0?zR?N???N???t??N?N???N?????@?`@b?`?`?a@c aaU??]N?zBus error: 10
为什么需要再次将参数压入堆栈?如何在不再次推送的情况下将堆栈中的这些参数传递给系统调用?
【问题讨论】:
-
你怎么知道这是因为操作系统而不是因为不同的处理器或编译器?您使用的是同一台计算机和相同的编译器吗?
-
Linux 使用寄存器将参数传递给系统调用。它不同于 Mac OS X(FreeBSD)。