退出系统调用的正确常量是多少?

时间:2017-01-28 21:27:25

标签: gcc assembly x86-64

我正在尝试学习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传递给GCC,我没有将其链接起来。如果可能的话,我想避免将这么大的图书馆链接到一个符号。

在回应Jester关于混合32位和64位常量的评论时,我尝试使用值0x3C,如下所示:

movq $0x3C, %eax
movq $0x00, %ebx

这也导致了分段错误。我还尝试为eaxebx换取raxrbx

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

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

movq $0x00, %rdi

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

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

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

1 个答案:

答案 0 :(得分:1)

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

#include <sys/syscall.h>

    .globl _start
_start:
    mov $SYS_exit,%eax
    xor %edi,%edi
    syscall

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