Почему эта инструкция MOVSS использует RIP-относительную адресацию?
Я нашел следующий ассемблерный код в дизассемблере (логика с плавающей точкой C++).
842: movss 0x21a(%rip),%xmm0
Я понимаю, что когда процесс RIP всегда будет 842, и этот 0x21a(% RIP) будет постоянным. Кажется немного странным использовать этот регистр.
Я хочу знать, есть ли преимущество использования относительного адреса RIP вместо другой адресации.
1 ответ
RIP
регистр указателя инструкций, что означает, что он содержит адрес инструкции, следующей сразу за текущей инструкцией.
Например, рассмотрим следующий код:
mov rax, [rip]
nop
В первой строке кода есть RIP
указывает на следующую инструкцию, поэтому он указывает на NOP
, Таким образом, этот код загружает адрес NOP
инструкция в RAX
регистр.
Таким образом, дело не в том, что RIP
это просто константа. Ваше понимание того, что RIP
в этом процессе "всегда будет 842" не правильно. Значение RIP
будет меняться в зависимости от того, где код был загружен в память. 842 - это просто номер строки, взятый из ваших символов отладки; как только код скомпилирован в двоичный файл, у него больше нет номеров строк.:-)
В вашей разборке константа это смещение (0x21A
). Это смещение от текущего значения в RIP
, Еще один способ написать это: %rip + 0x21A
,
RIP
-относительная адресация - это новая форма эффективной адресации, представленная в 64-битном длинном режиме. Дело в том, что это облегчает написание независимого от позиции кода, потому что вы можете сделать любую ссылку на память RIP
-родственник. По факту, RIP
-относительная адресация является режимом адресации по умолчанию в 64-битных приложениях. Практически все инструкции, которые обращаются к памяти в 64-битном режиме, RIP
-родственник. Я приведу цитату из блога Кена Джонсона (он же Скайвинг), потому что я не мог сказать это лучше себя:
Одно из самых больших (но часто упускаемых из виду) изменений в x64 относительно x86 состоит в том, что большинство инструкций, которые ранее ссылались только на данные через абсолютную адресацию, теперь могут ссылаться на данные через RIP-относительную адресацию.
Относительная RIP-адресация - это режим, в котором ссылка на адрес предоставляется в виде (подписанного) 32-битного смещения от текущего указателя команды. Хотя это обычно использовалось только в x86 для команд передачи управления (call, jmp и soforth), x64 расширяет использование относительной адресации указателя инструкций, чтобы охватить гораздо больший набор инструкций.
В чем преимущество использования RIP-относительной адресации? Ну, главное преимущество в том, что становится намного проще генерировать независимый от позиции код или код, который не зависит от того, где он загружен в память. Это особенно полезно в современном мире (относительно) автономных модулей (таких как DLL или EXE), которые содержат как данные (глобальные переменные), так и код, который сопровождает их. Если в x86 используется плоская адресация, то ссылки на глобальные переменные обычно требуют жесткого кодирования абсолютного адреса рассматриваемого глобала, предполагая, что модуль загружается по своему предпочтительному базовому адресу. Если тогда модуль не мог быть загружен по предпочтительному базовому адресу во время выполнения, загрузчик должен был выполнить набор базовых перемещений, которые по существу переписывают все инструкции, которые имели компонент операнда абсолютного адреса, чтобы ссылаться, чтобы принять во внимание новый адрес модуля,
[ .,, ]
Однако инструкция, которая использует относительную адресацию RIP, обычно не требует каких-либо базовых перемещений (иначе называемых "исправлениями") во время загрузки, если модуль, содержащий его, перемещен. Это связано с тем, что до тех пор, пока части модуля внутренне не переставлены в памяти (что не поддерживается форматом PE), любые адреса обращаются как к указателю текущей инструкции, так и к расположению в пределах границ текущее изображение будет продолжать ссылаться на правильное местоположение, независимо от того, где находится изображение во время загрузки.
В результате многие x64-изображения имеют значительно меньшее количество исправлений из-за того факта, что большинство операций можно выполнять в режиме RIP.
Он говорит в контексте Windows, но что-то концептуально подобное относится и к другим операционным системам.
У вас есть код загружает постоянное значение, хранящееся где-то в двоичном изображении, в XMM0
зарегистрироваться, и он делает это с помощью RIP-относительной адресации из-за своих многочисленных преимуществ.