unistd.h常量linux x86_64

时间:2014-07-24 23:13:25

标签: c linux

如果我在64位linux上的一个简单程序中printf __NR_exit,则值为<asm/unistd_64.h>中定义的60。但是,此代码(使用-nostdlib编译)段错误:

void _start(){
 asm("movl $60,%eax;"
     "xorl %ebx,%ebx;"
     "int $0x80");
}

但是,这按预期运行:

void _start(){
 asm("movl $1,%eax;"
     "xorl %ebx,%ebx;"
     "int $0x80");
}

其中__NR_exit在32位版本的<unistd.h>

中定义为1

显然1是正确的常数。为什么要使用32位系统调用值?

$ uname -a                                         
Linux galois 3.14.6-1-ARCH #1 SMP PREEMPT Sun Jun 8 10:08:38 CEST 2014 x86_64 GNU/Linux

1 个答案:

答案 0 :(得分:2)

x86-64系统上的调用约定是不同的。 Linux采用了System V ABI,其中包括其调用约定。

系统调用号存储在%rax中,参数后跟%rdi%rsi%rdx%r10%r8和按此顺序%r9,并使用syscall指令代替int $0x80。只能传递归类为属于MEMORY类的整数和项目,并且只能使用那些寄存器。类MEMORY的项目通过堆栈传递。您只能将6个或更少的参数传递给系统调用。

使用相同的寄存器调用用户模式函数,第一个函数参数存储在%rdi中,但使用%rcx代替%r10%rax除外用于表示传递的SSE参数的数量,而不是系统调用号。

有关详细信息,请参阅System V AMD64 Calling Convention,但有关某些Linux特定信息的更明确指南可在the actual specification的附录A第2.1小节中找到。