Инструкция x86 "movb $ 5, var (, 1)" - PullRequest
       10

Инструкция x86 "movb $ 5, var (, 1)"

0 голосов
/ 04 февраля 2019

Я читаю учебник сборки x86 по синтаксису AT & T, и я столкнулся с этой инструкцией

movb $5, var(,1) - сохранить значение 5 в байте в местоположении var.

Что означает (,1) после var?Каков общий синтаксис для такого суффикса?

1 Ответ

0 голосов
/ 04 февраля 2019

Это нетрадиционный стиль, если не сказать больше;Я никогда раньше не видел, чтобы кто-то писал это для адресации статической метки без регистров.


Это может быть попытка указать байт SIB (без базы или индекса), вместо этогоразрешить ассемблеру использовать более короткое кодирование только с байтом ModRM.

(Да, это возможно. 32-разрядные режимы адресации имеют 2 избыточных способа кодирования [disp32] абсолютных адресов. x86-64 переопределяет более короткиеодин для относительной RIP-адресации. См. также rbp не разрешен в качестве базы SIB? )

Но текущий GAS игнорирует его и кодирует его так же, как и var.

Так что, возможно, это попытка напомнить вам, что это операнд памяти, как всегда с использованием [var] в синтаксисе Intel вместо mov var, al (который действителен в MASM-стили синтаксиса Intel, такие как GNU .intel_syntax, но не NASM).

Каков общий синтаксис для такого суффикса?

Или, может быть, они простоделать это для согласованности всегда использовать disp(basereg, idxreg, scale)синтаксис для операндов памяти, пропуская неиспользуемые части.


Источник теста:

var:                  # this won't be in writeable memory, it will assemble but not run
movb  $5, var
movb  $5, var(,1)
movb  $5, (var)      # turns out this is valid, too!

#movb $5, var(%rip)  # RIP-relative is x86-64 only, but it's recommended when available.

# movb  $5, var()     # Error: junk `()' after expression
# movb  $5, (var,,1)  # also invalid
# movb  $5, (var,%ecx,1)       # also invalid.
# movb  $5, (var+%eax,%ecx,1)  # also invalid.

as --version печатает GNU assembler (GNU Binutils) 2.31.1 в моей системе.

$ gcc -m32 -no-pie -nostdlib foo.s
/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000008049000
 # I just wanted a linked binary with real addresses filled in, not to run it.
 # entry = start of the .text section is fine.

$ objdump -drwC -Mintel a.out

08049000 <var>:
 8049000:       c6 05 00 90 04 08 05    mov    BYTE PTR ds:0x8049000,0x5
 8049007:       c6 05 00 90 04 08 05    mov    BYTE PTR ds:0x8049000,0x5
 804900e:       c6 05 00 90 04 08 05    mov    BYTE PTR ds:0x8049000,0x5

Встроенный ассемблер Clang 7.0 также принимает все 3 варианта, которые делает GAS, создавая идентичный двоичный файл.(По крайней мере, раздел .text, который я разбираю; возможно, какая-то разница где-то в другом разделе.)


Так, возможно, cmp $1, (var) - это хороший способ сделать операнды памяти явными? Но это не так здорово, потому что, в отличие от синтаксиса Intel, вы не можете просто добавить регистров к этому, вам придется переместить var за пределы паренсов.

...