【发布时间】:2016-08-07 03:26:43
【问题描述】:
我在 64 位 Linux 环境中运行我的代码,其中 Linux 内核是使用 IA32_EMULATION 和 X86_X32 禁用构建的。 p>
在书Programming from the Ground Up 中,第一个程序除了产生段错误之外什么都不做:
.section .data
.section .text
.globl _start
_start:
movl $1, %eax
movl $0, %ebx
int $0x80
我将代码转换为使用 x86-64 指令,但它也有段错误:
.section .data
.section .text
.globl _start
_start:
movq $1, %rax
movq $0, %rbx
int $0x80
我是这样组装这两个程序的:
as exit.s -o exit.o
ld exit.o -o exit
运行./exit 为两者提供Segmentation fault。我做错了什么?
附:我看过很多使用 gcc 组装代码的教程,但是我想使用 gas。
更新
结合cmets和答案,这是代码的最终版本:
.section .data
.section .text
.globl _start
_start:
movq $60, %rax
xor %rbx, %rbx
syscall
【问题讨论】:
-
int 0x80是否仍然存在于 x86_64 中?我以为它已经被syscall指令取代了 -
@Pierre 将
int 0x80替换为syscall也给了我Segmentation fault。 -
@MichaelPetch 我使用自定义内核并禁用 i386 仿真,因为我从不运行 32 位二进制文件。
-
这就是你出现段错误的原因。大多数发行版都打开 IA32 仿真。如果您将其关闭,您将无法在 64 位代码中使用
int 0x80。您需要使用 64 位syscall指令和约定。 blog.rchapman.org/post/36801038863/… 是一个很好的起点。如果您打开 IA32 仿真,您的内核可以在 64 位代码中使用int 0x80,但仅限于 32 位操作数和 32 位指针。 IA32 仿真不使用高 32 位。一个缺点是基于堆栈的指针不能传递给int 0x80 -
在编写 x86-64 代码时首选
syscall指令。调用约定和编号不同于int 0x80
标签: linux assembly x86-64 system-calls gnu-assembler