1

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

#.intel_syntax noprefix

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

    movq  $60, %rax
    movq  $0, %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?如果是这样,正确的语法是什么?

4

2 回答 2

6

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

如果您想使用 Intel 语法进行编程,我建议您选择更好的汇编程序,例如 nasm。

于 2018-07-26T16:52:44.380 回答
3

您可以使用 AT&T 语法反汇编器(如objdump -d)来查看mov rsi, msg在 GAS 中的.intel_syntax汇编为mov msg, %rsi32 位绝对地址的 64 位加载。

或使用objdump -d -Mintel查看您的工作版本的英特尔语法反汇编。

GDB has set disassembly-flavor intelor 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 位的位置相关可执行文件中效率低。)

 ## 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 位的。无法将 .data 中的变量移动到 Mac x86 程序集的寄存器

于 2018-07-26T17:06:29.763 回答