我正在尝试学习 x86_64 汇编,并使用 GCC 作为我的汇编程序。我正在使用的确切命令是:
gcc -nostdlib tapydn.S -D__ASSEMBLY__
我主要使用 gcc 作为它的预处理器。这里是
tapydn.S
:.global _start
#include <asm-generic/unistd.h>
syscall=0x80
.text
_start:
movl $__NR_exit, %eax
movl $0x00, %ebx
int $syscall
这会导致段错误。我认为问题出在以下行:
movl $__NR_exit, %eax
我用了
__NR_exit
因为它比一些神奇的数字更具描述性。但是,看来我对它的使用是不正确的。我相信是这样的,因为当我将有问题的行更改为以下内容时,它运行良好:movl $0x01, %eax
usr/include/asm-generic/unistd.h
的内容进一步支持了这一思路。 :#define __NR_exit 93
__SYSCALL(__NR_exit, sys_exit)
我预计 __NR_exit 的值为 1,而不是 93!显然,我误解了它的目的,因此误解了它的用法。据我所知,
$0x01
让我很幸运案例工作(很像 C++ 中的未定义行为),所以我一直在挖掘......接下来,我查找了
sys_exit
的定义。 .我找不到它。我尝试按如下方式使用它(有和没有前面的$):movl $sys_exit, %eax
这不会链接:
/tmp/cc7tEUtC.o: In function `_start':
(.text+0x1): undefined reference to `sys_exit'
collect2: error: ld returned 1 exit status
我的猜测是它是其中一个系统库中的一个符号,由于我传递了
-nostdlib
,我没有链接它。到海湾合作委员会。如果可能的话,我想避免为一个符号链接(symbolic link)这么大的库。为了回应 Jester 关于混合 32 位和 64 位常量的评论,我尝试使用值
0x3C
按照建议:movq $0x3C, %eax
movq $0x00, %ebx
这也导致了段错误。我也试过换掉
eax
和 ebx
对于 rax
和 rbx
:movq $0x3C, %rax
movq $0x00, %rbx
段错误仍然存在。
Jester 然后评论说我应该使用
syscall
而不是 int $0x80
:.global _start
#include <asm-generic/unistd.h>
.text
_start:
movq $0x3C, %rax
movq $0x00, %rbx
syscall
这行得通,但后来我被告知我应该使用
rdi
而不是 rbx
根据 System V AMD64 ABI:movq $0x00, %rdi
这也可以正常工作,但最终仍然使用魔数(Magic Number)
0x3C
为系统调用号。总结一下,我的问题如下:
__NR_exit
的正确用法是什么? exit
的魔数(Magic Number)系统调用? 最佳答案
获取系统调用号的正确头文件是sys/syscall.h
.这些常量称为 SYS_###
在哪里 ###
是您感兴趣的系统调用的名称。__NR_###
宏是实现细节,不应使用。根据经验,如果标识符以下划线开头,则不应使用,如果以 2 开头,则绝对不应使用。参数进入 rdi
, rsi
, rdx
, r10
, r8
, 和 r9
.这是 Linux 的示例程序:
#include <sys/syscall.h>
.globl _start
_start:
mov $SYS_exit,%eax
xor %edi,%edi
syscall
这些约定大多可移植到其他类 UNIX 操作系统。
关于gcc - 退出系统调用的正确常量是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41915010/