На x86 позиционно-независимый код в принципе выглядит так:
call 1f
1: popl %ebx
с последующим использованием ebx
в качестве базового указателя со смещением, равным расстоянию между данными, к которым осуществляется доступ, и адресом инструкции popl
.
В действительности это часто более сложно, и обычно для загрузки регистра PIC может использоваться функция крошечного thunk:
load_ebx:
movl 4(%esp),%ebx
addl $some_offset,%ebx
ret
, где смещение выбрано таким образом, чтобы при возврате thunk ebx
содержал указатель на обозначенную специальную точку в программе / библиотеке (обычно начало глобальной таблицы смещений), а затем все последующие ebx
-относительные доступы могут просто использовать расстояние между требуемыми данными и назначенной специальной точкой в качестве смещения.
В других арках в принципе все аналогично, но могут быть более простые способы загрузки счетчика программы. Многие просто позволяют использовать регистр pc
или ip
в качестве обычного регистра в режимах относительной адресации.