Синтаксис GAS для относительной RIP-адресации выглядит как symbol + RIP
, но на самом деле это означает symbol
относительно RIP
.
несовместимость с числовыми литералами:
[rip + 10]
или AT & T 10(%rip)
означает 10 байтов после конца этой инструкции [rip + a]
или AT & T a(%rip)
означает вычисление rel32
смещение для достижения a
, не RIP + значение символа. [a]
или AT & T a
- абсолютный адрес, использующий режим адресации disp32.Это не поддерживается в OS X, где базовый адрес образа всегда находится за пределами младших 32 бит.(Или для mov
в al / ax / eax / rax, возможно 64-битное абсолютное кодирование moffs
, но вы этого не хотите). Невозможно переместить переменные в .data в регистры с помощью сборки Mac x86 .
Позиционно-зависимые исполняемые файлы Linux do поместить статический код / данные в младшие 31 бит виртуальной памяти.адресное пространство, поэтому вы можете / должны использовать mov edi, sym
там, но в OS X ваш лучший вариант - lea rdi, [sym+RIP]
, если вам нужен адрес в реестре.
(в OS Xсоглашение гласит, что в именах переменных / функций языка C в asm добавляется _
. В написанном от руки asm у вас нет , чтобы сделать это для символов, к которым вы не хотите обращаться из C.)
NASM гораздо менее запутан в этом отношении:
[rel a]
означает относительную RIP-адресацию для [a]
[abs a]
означает[disp32]
. default rel
или default abs
устанавливает, что используется для [a]
.По умолчанию (к сожалению) default abs
, поэтому вам почти всегда нужен default rel
.
Пример с .set
значениями символов и меткой
.intel_syntax noprefix
mov dword ptr [sym + rip], 0x11111111
sym:
.equ x, 8
inc byte ptr [x + rip]
.set y, 32
inc byte ptr [y + rip]
.set z, sym
inc byte ptr [z + rip]
gcc -nostdlib foo.s && objdump -drwC -Mintel a.out
(в Linux; у меня нет OS X):
0000000000001000 <sym-0xa>:
1000: c7 05 00 00 00 00 11 11 11 11 mov DWORD PTR [rip+0x0],0x11111111 # 100a <sym> # rel32 = 0; it's from the end of the instruction not the end of the rel32 or anywhere else.
000000000000100a <sym>:
100a: fe 05 08 00 00 00 inc BYTE PTR [rip+0x8] # 1018 <sym+0xe>
1010: fe 05 20 00 00 00 inc BYTE PTR [rip+0x20] # 1036 <sym+0x2c>
1016: fe 05 ee ff ff ff inc BYTE PTR [rip+0xffffffffffffffee] # 100a <sym>
(Разборка .o
с objdump -dr
покажет вам, что нет никаких перемещений для компоновщикачтобы заполнить, все они были сделаны во время сборки.)
Обратите внимание, что только .set z, sym
привело к вычислению по отношению к.x
и y
были оригинальными из простых числовых литералов, а не меток, поэтому, хотя сама инструкция использовала [x + RIP]
, мы все равно получили [RIP + 8]
.
(только для Linux без PIE)): По адресу абсолютный 8
относительноRIP, вам понадобится AT & T синтаксис incb 8-.(%rip)
.Я не знаю, как написать это в ГАЗ intel_syntax
;[8 - . + RIP]
отклоняется с Error: invalid operands (*ABS* and .text sections) for '-'
.
Конечно, вы все равно не можете сделать это в OS X, за исключением, может быть, абсолютных адресов, которые находятся в диапазоне базы изображений.Но, вероятно, нет перемещения, которое могло бы содержать 64-битный абсолютный адрес для расчета для 32-битного rel32.