Нет, доступ к EIP / IP невозможен напрямую, но в позиционно-зависимом коде это постоянная времени соединения, поэтому вы можете использовать ближайший (или удаленный) символ в качестве непосредственного.
mov eax, nearby_label ; in position-dependent code
nearby_label:
Чтобы получить EIP или IP в 32-битном коде, не зависящем от позиции:
call _here
_here: pop eax
; eax now holds the PC.
На процессорах, более новых, чем Pentium Pro (или, возможно, PIII), call rel32
с rel32 = 0 имеет специальный случай, чтобы не влиять на стек предикторов обратных адресов . Так что это эффективно и компактно на современном x86, и это то, что clang использует для 32-битного позиционно-независимого кода.
На старых 32-битных процессорах Pentium Pro это приведет к дисбалансу стека предикторов вызовов / возвратов, поэтому предпочтительнее вызывать функцию, которая действительно возвращает данные, чтобы избежать ошибочных прогнозов ветвлений для примерно 15 или более будущих инструкций ret
в родительском элементе функции. (Если только вы не собираетесь возвращаться или настолько редко, что это не имеет значения.) Однако стек предикторов обратного адреса восстановится.
get_retaddr_ppro:
mov eax, [esp]
ret ; keeps the return-address predictor stack balanced
; even on CPUs where call +0 isn't a no-op.
В режиме x86-64 RIP может считываться напрямую с использованием относительного RIP lea
.
default rel ; NASM directive: use RIP-relative by default
lea rax, [_here] ; RIP + 0
_here:
MASM или GNU .intel_syntax
: lea rax, [rip]
Синтаксис AT & T: lea 0(%rip), %rax