如果我在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是正确的常数。为什么要使用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
答案 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小节中找到。