退出系统调用的正确常量是什么?

OMG*_*chy 7 assembly gcc x86-64

我正在尝试学习 x86_64 汇编,并使用 GCC 作为我的汇编程序。我正在使用的确切命令是:

gcc -nostdlib tapydn.S -D__ASSEMBLY__
Run Code Online (Sandbox Code Playgroud)

我主要使用 gcc 作为它的预处理器。这是tapydn.S

.global _start

#include <asm-generic/unistd.h>

syscall=0x80

.text
_start:
    movl $__NR_exit, %eax
    movl $0x00, %ebx
    int  $syscall
Run Code Online (Sandbox Code Playgroud)

这会导致分段错误。我相信问题出在以下几行:

 movl $__NR_exit, %eax
Run Code Online (Sandbox Code Playgroud)

我使用__NR_exit它是因为它比一些神奇的数字更具描述性。但是,我对它的使用似乎是不正确的。我相信情况确实如此,因为当我将有问题的行更改为以下内容时,它运行良好:

movl $0x01, %eax
Run Code Online (Sandbox Code Playgroud)

进一步支持这一思路的是以下内容usr/include/asm-generic/unistd.h

#define __NR_exit 93
__SYSCALL(__NR_exit, sys_exit)
Run Code Online (Sandbox Code Playgroud)

我预计 __NR_exit 的值为 1,而不是 93!显然我误解了它的目的,因此误解了它的用法。据我所知,我很幸运能在$0x01案例中工作(很像 C++ 中的未定义行为),所以我一直在挖掘......

接下来,我寻找sys_exit. 我找不到。我尝试使用它如下(有和没有前面的 $):

movl $sys_exit, %eax
Run Code Online (Sandbox Code Playgroud)

这不会链接:

/tmp/cc7tEUtC.o: In function `_start':
(.text+0x1): undefined reference to `sys_exit'
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

我的猜测是它是系统库之一中的一个符号,由于我传递-nostdlib给 GCC ,我没有链接它。如果可能的话,我想避免只为一个符号链接这么大的库。

为了回应 Jester 关于混合 32 位和 64 位常量的评论,我尝试0x3C按照建议使用该值:

movq $0x3C, %eax
movq $0x00, %ebx
Run Code Online (Sandbox Code Playgroud)

这也导致了分段错误。我也试过换出eax,并ebxraxrbx

movq $0x3C, %rax
movq $0x00, %rbx
Run Code Online (Sandbox Code Playgroud)

分段错误仍然存​​在。

Jester 然后评论说我应该使用syscall而不是int $0x80

.global _start

#include <asm-generic/unistd.h>

.text
_start:
    movq $0x3C, %rax
    movq $0x00, %rbx
    syscall
Run Code Online (Sandbox Code Playgroud)

这有效,但后来我被告知我应该使用rdi而不是rbx按照 System V AMD64 ABI:

movq $0x00, %rdi
Run Code Online (Sandbox Code Playgroud)

这也可以正常工作,但最终仍然使用0x3C系统调用号的幻数。

总结一下,我的问题如下:

  • 的正确用法是__NR_exit什么?
  • 我应该使用什么来代替exit系统调用的幻数?

fuz*_*fuz 4

获取系统调用号的正确头文件是sys/syscall.h. 常量的调用位置SYS_######您感兴趣的系统调用的名称。__NR_###宏是实现细节,不应使用。根据经验,如果标识符以下划线开头,则不应使用,如果以两个下划线开头,则绝对不应使用。参数分为rdirsirdxr10r8r9。下面是 Linux 的示例程序:

#include <sys/syscall.h>

    .globl _start
_start:
    mov $SYS_exit,%eax
    xor %edi,%edi
    syscall
Run Code Online (Sandbox Code Playgroud)

这些约定大多可移植到其他类 UNIX 操作系统。

  • @user2023370 尝试 `echo '#include &lt;sys/syscall.h&gt;' | 抄送-E-`。这显示了 `sys/syscall.h` 所在的位置。在使用 glibc 的 Linux 系统上,它通常不在“/usr/include”中。 (2认同)