编译C和nasm时传递参数

时间:2014-05-08 16:15:33

标签: c macos assembly nasm

在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

为什么需要再次将参数推入堆栈?如何在不再推送的情况下将堆栈中已有的参数传递给系统调用?

1 个答案:

答案 0 :(得分:1)

即使是普通的C函数调用也是如此。问题是返回地址仍然在参数之前的堆栈上。如果你不再将它们推回到返回地址之下,你将在参数之前在堆栈上有2个返回地址(第一个到main,第二个到myprint),但是系统调用只是期望1。