Синтаксис AT&T hello world работает, но синтаксис Intel - нет

Я пишу программу hello world для linux x86_64, используя ассемблер GAS, и вот мой код в синтаксисе 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

Это работает и печатает «привет, мир». Вот синтаксис Intel:

.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

Это компилируется и работает нормально, но не выводит «привет, мир». Я предполагаю, что ошибка в mov rsi, msg? Если да, то каков правильный синтаксис?


person wingerse    schedule 26.07.2018    source источник


Ответы (2)


Попробуйте mov rsi, offset msg. gas использует синтаксис типа masm, где mov rsi, msg перемещает содержимое msg в rsi вместо перемещения адреса. Чтобы избежать этой проблемы, необходимо использовать ключевое слово offset.

Если вы хотите программировать с использованием синтаксиса Intel, я советую вам выбрать лучший ассемблер, например, nasm.

person fuz    schedule 26.07.2018
comment
@WingerSendon Обратите внимание, что вам нужно вернуться к исходному коду и исправить некоторые директивы для его сборки на nasm, но синтаксис в целом намного разумнее, чем с gcc в синтаксисе Intel. - person fuz; 26.07.2018

Вы можете использовать дизассемблер синтаксиса AT&T (например, objdump -d), чтобы увидеть, что mov rsi, msg в GAS .intel_syntax ассемблируется в mov msg, %rsi, 64-битную загрузку с 32-битного абсолютного адреса.

Или используйте objdump -d -Mintel, чтобы увидеть разборку синтаксиса Intel для вашей рабочей версии.

GDB имеет set disassembly-flavor intel или att, поэтому вы можете переключаться даже в течение одного сеанса отладки.


И, кстати, вы должны использовать LEA, относящийся к RIP, для получения 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

person Peter Cordes    schedule 26.07.2018