Смещения между различными разделами вашего исполняемого файла являются константами времени соединения , поэтому относительная к RIP адресация может использоваться для любого раздела (включая .data
, где используются глобальные значения, отличные от const
).Обратите внимание на .data
в выходных данных asm.
Это применимо даже в исполняемой или разделяемой библиотеке PIE, где абсолютные адреса не известны до времени выполнения (ASLR).
Runtime ASLR для независимых от позиции исполняемых файлов (PIE) рандомизирует один базовый адрес для всей программы, а не начальные адреса отдельных сегментов относительно друг друга.
Весь доступ к статическим переменным использует относительную RIP-адресацию, потому что это наиболееэффективен даже в зависящем от позиции исполняемом файле, где абсолютная адресация является опцией (поскольку статические адреса являются константами времени соединения).
В 32-разрядной версии x86 существует 2 избыточных способа кодирования режима адресации безрегистры и абсолютный адрес disp32
.(С байтом SIB и без него).x86-64 переназначил более короткую на RIP+rel32
, поэтому mov foo, %eax
на 1 байт длиннее mov foo(%rip), %eax
.
64-битная абсолютная адресация займет еще больше места и доступна только для mov
в / из RAX / EAX / AX / AL, если только вы сначала не используете отдельную инструкцию для ввода адреса в регистр.
(В Linux PIE / PIC x86-64 разрешена 64-битная абсолютная адресация иобрабатываются с помощью исправлений во время загрузки, чтобы поместить правильный адрес в код или таблицу переходов или статически инициализированный указатель функции.Таким образом, технически не имеет , чтобы быть независимым от позиции, но обычно это более эффективно, чтобы быть32-разрядная абсолютная адресация не допускается, поскольку ASLR не ограничивается низкими 31 битами виртуального адресного пространства.)
Обратите внимание, что в исполняемом файле, отличном от PIE, gcc будет использовать 32-битную абсолютную адресацию для записи адреса статических данных в регистр.например, puts("hello");
обычно компилируется как
mov $.LC0, %edi # mov r32, imm32
call puts
В модели памяти по умолчанию, отличной от PIE, статический код и данные связываются с низкими 32 битами виртуального адресного пространства, поэтому 32-битные абсолютные адреса работают независимо от того,они расширены до нуля или знака до 64-битЭто удобно для индексирования статических массивов , например, mov array(%rax), %edx
;add $4, %eax
например.
См. 32-разрядные абсолютные адреса, более не разрешенные в x86-64 Linux? для получения дополнительной информации о исполняемых файлах PIE, которые используют позиционно-независимый код для всего, включая RIP-относительный LEA, такой как 7-байтовый lea .LC0(%rip), %rdi
вместо 5-байтового mov $.LC0, %edi
.
Я упоминаю Linux, потому что он выглядит из директив .cfi
, как будто вы компилируете для платформы, отличной от Windows.