К сожалению, компилятор NASM не имеет опции -fPIC.
Конечно, нет;это опция генерации кода для компилятора .NASM - это ассемблер, а не компилятор;инструкции, которые он собирает, задаются исходным файлом, а не параметрами командной строки.(Сообщение об ошибке предполагает, что люди используют ld
на выходе компилятора, а не рукописный asm.)
Recompile = повторить генерацию asm-инструкций, а не пересобрать тот же asm с разными опциями.Компилятор - ваш мозг.
- Все ли инструкции mov необходимо переписать с ключевым словом rel
Нет, вы можете просто использовать default rel
вверху файла, как обычный человек, вместо того, чтобы изменять каждый режим адресации, чтобы явно использовать [rel foo]
.
и 3. Существуют ли другие типы команд, требующие специальной обработки?
Это не имеет ничего общего с инструкцией mov
, все связано с режимом адресации.Все инструкции (включая LEA) используют одну и ту же кодировку ModR / M + SIB + disp0 / 8/32 для режимов адресации.(За исключением одной формы mov
, которая может использовать 64-битный абсолютный адрес при загрузке / хранении AL / AX / EAX / RAX. Но вы этого тоже не хотите.)
Вам также необходимо избегать любого использования адресов в качестве 32-битных абсолютных непосредственных операндов .Поэтому, если вы помещаете адрес в регистр, вам нужен REA-относительный LEA вместо более эффективного 5-байтового mov-немедленного, который вы могли бы использовать в позиционно-зависимом коде.
;; putting a label address into a register
default rel
mov edi, my_string ; optimal in position-dependent executables on Linux
lea rdi, [my_string] ; optimal otherwise, best you can do for PIC/PIE
mov rdi, my_string ; Never use: 64-bit absolute is inefficient
только раз вы должны использовать 64-битные абсолютные адреса в .data
или .rodata
для содержимого таблицы переходов или других указателей на статические адреса.Не в коде;вместо этого используйте RIP-относительный.
Очевидно, что вам следует избегать [disp32 + reg]
режимов адресации, таких как [array + rdi]
или [array + rdx*4]
. Единственный относительный режим RIP-адресации - [RIP + rel32]
;другие режимы по-прежнему используют 32-разрядное смещение в качестве 32-разрядного абсолютного значения с расширенным знаком (так что это может быть постоянное смещение, например 1024, а не адрес).
Mach-O 64-битный формат не поддерживает 32-битные абсолютные адреса.NASM Accessing Array (MachO64 никогда не допускает 32-битный абсолют, поэтому он имеет те же ограничения, что и объект PIC Linux / ELF)
Я знаю, что R_X86_64_32S указывает на 32-битную адресацию, но я нев моем коде нет 32-битной адресации.
[abs foo]
- это знак disp32, расширенный до 64. Вот почему тип перемещения равен 32 S .В отличие от этого, mov edi, foo
использует R_X86_64_32
.
Это не 32-разрядный размер адреса, но абсолютный адрес все еще должен быть закодирован как 32-разрядное целое число со знаком.Что не допускается в объекте PIE / PIC, который должен быть перемещен в любое место в 64-битном адресном пространстве.
Связанный:
Предполагается, что библиотеки PIC будут поддерживать вставку символов.Подробнее см. Извините за состояние динамических библиотек в Linux .
Если вам нужен эффективный внутренний доступ к вашим собственным global
символам (без прохождения GOT) , вывозможно, потребуется определить слабые псевдонимы для них, которые имеют «скрытую» видимость ELF.Или просто поместите 2 ярлыка в одно место, один глобальный скрытый.См. 7.9.5 elf Расширения к директиве GLOBAL в руководстве NASM:
global hashlookup:function hidden
Кроме того, примечания к руководству NASM:
Объявление типа и размера глобальных символов необходимо при написании кода совместно используемой библиотеки.Для получения дополнительной информации см. Раздел 9.2.4.