Почему при переключении с синтаксиса AT&T на Intel это руководство приводит к ошибке сегментации с использованием GAS?

Я работаю над некоторыми учебниками на http://www.ibm.com/developerworks/linux/library/l-gas-nasm/index.html, чтобы ознакомиться с x86/x64. Этот обучающий код компилируется и работает без сбоев, используя предоставленный код, который использует синтаксис AT&T:

.global main
.text
main:                               # This is called by C library's startup code
    mov     $message, %rdi          # First integer (or pointer) parameter in %edi
    call    puts                    # puts("Hello, World")
    ret                             # Return to C library code
message:
    .asciz "Hello, World"           # asciz puts a 0x00 byte at the end

Однако, когда я преобразовываю этот код в синтаксис Intel, я получаю сообщение об ошибке «Ошибка сегментации».

.intel_syntax noprefix
.global main
.text
main:                               # This is called by C library's startup code
    mov     rdi, message            # First integer (or pointer) parameter in %edi
    call    puts                    # puts("Hello, World")
    ret                             # Return to C library code
message:
    .asciz "Hello, World"           # asciz puts a 0x00 byte at the end

Я не знаком с x86, поэтому, возможно, я что-то упускаю. Есть идеи?


person Alex    schedule 20.04.2013    source источник
comment
Вы бинарные выходы сравнивали?   -  person Jens Björnhager    schedule 20.04.2013
comment
@JensBjörnhager, я не сравнивал бинарные выходы. Я новичок в ассемблере, а бинарник знаю еще меньше. Есть ли что-то конкретное, что я могу получить от сравнения двоичных файлов, не будучи гуру низкого уровня?   -  person Alex    schedule 20.04.2013
comment
Вероятно, упоминался mov rdi, offset message?   -  person Egor Skriptunoff    schedule 20.04.2013
comment
@EgorSkriptunoff, изменение mov rdi, message на mov rdi, offset message работает. Не могли бы вы указать мне правильное направление, почему это работает? Я предполагаю, что это как-то связано с указанием rdi на место в памяти прямо перед запуском message? Почему смещение необходимо в синтаксисе Intel, а не AT&T?   -  person Alex    schedule 20.04.2013


Ответы (1)


В синтаксисе AT&T mov $message, %rdi, $ означает немедленно, то есть адрес сообщения.

В синтаксисе Intel GAS mov rdi, message означает абсолютную адресацию, то есть содержимое в сообщении. Чтобы получить фактический адрес сообщения, необходимо указать ключевое слово offset: mov rdi, offset message.

Разборка двух бинарников показывает разницу:

АТ&Т:

0000000000000000 <main>:
0:   48 c7 c7 00 00 00 00    mov    $0x0,%rdi

Интел:

0000000000000000 <main>:
0:   48 8b 3c 25 00 00 00 00    mov    0x0,%rdi
     
person Jens Björnhager    schedule 20.04.2013
comment
Большое спасибо, Йенс! Это просто многое для меня прояснило. - person Alex; 20.04.2013