AT&T 语法 hello world 有效,但 intel 语法无效

AT&T syntax hello world works but intel syntax does not

我正在使用 GAS 汇编器为 linux x86_64 编写一个 hello world 程序,这里是我的 AT&T 语法代码。

#.intel_syntax noprefix

.section .data
    msg:
        .ascii "hello world\n"
.section .text
.globl _start
_start:
    movq  , %rax
    movq  , %rdi
    movq  $msg, %rsi
    movq  , %rdx
    syscall

    movq  , %rax
    movq  [=10=], %rdi
    syscall

这有效并打印 "hello world"。这是英特尔语法:

.intel_syntax noprefix

.section .data
    msg:
        .ascii "hello world\n"
.section .text
.globl _start
_start:
    mov rax, 1
    mov rdi, 1
    mov rsi, msg
    mov rdx, 12
    syscall

    mov rax, 60
    mov rdi, 0
    syscall

编译和运行正常但不打印 "hello world"。我假设错误在 mov rsi, msg?如果是这样,正确的语法是什么?

尝试mov rsi, offset msg。 gas 使用类似 masm 的语法,其中 mov rsi, msgmsg 的内容移动到 rsi 而不是移动地址。必须使用 offset 关键字来避免此问题。

如果你想用 Intel 语法编程,我建议你选择一个更好的汇编器,比如 nasm。

您可以使用 AT&T 语法反汇编程序(如 objdump -d)来查看 GAS .intel_syntax 中的 mov rsi, msg 汇编为 mov msg, %rsi,从32 位绝对地址。

或使用 objdump -d -Mintel 查看适用于您的工作版本的 Intel 语法反汇编。

GDB 有 set disassembly-flavor intel 或 att,所以你甚至可以在一个调试会话中翻转。


顺便说一句,您应该使用 RIP 相关的 LEA 将 64 位静态地址获取到寄存器中。它比 mov r64, imm64

更有效
lea   msg(%rip), %rsi    # AT&T

lea   rsi, [msg + rip]  # GAS .intel_syntax

lea   rsi, [rel msg]     ; NASM

(但在位置相关的可执行文件中效率低于 mov r32, imm32,其中静态标签位于虚拟地址的低 31 位 space。)

 ## In x86-64 position-dependent executables on Linux

 mov  $msg, %esi            # AT&T

 mov   esi, OFFSET msg      # GAS .intel_syntax

 mov   esi, msg          ; NASM

注意 OS X 将静态地址放在低位 32 之外,因此即使在可执行文件中,您的地址也是 64 位的。