с 64-битным абсолютным адресом вместо режима адресации ModR / M. Но опять же, не делайте этого, потому что режим RIP-относительной адресации более компактен и столь же эффективен.

тите этот код с моего компьютера Mac, используя команду:

nasm -f macho64 -o max.a maximum.asm

Это код, который я пытаюсь запустить на своем компьютере, который находит наибольшее число в массиве.

section .data

data_items:
    dd 3,67,34,222,45,75,54,34,44,33,22,11,66,0

    section .text

global _start

_start:
    mov edi, 0
    mov eax, [data_items + edi*4]
    mov ebx, eax

start_loop:
    cmp eax, 0
    je loop_exit
    inc edi
    mov eax, [data_items + edi*4]
    cmp eax, ebx
    jle start_loop

mov ebx, eax
jmp start_loop

loop_exit:

mov eax, 1
int 0x80

Ошибка:

maximum.asm:14: error: Mach-O 64-bit format does not support 32-bit absolute addresses
maximum.asm:21: error: Mach-O 64-bit format does not support 32-bit absolute addresses
 Michael Petch15 нояб. 2017 г., 08:31
Первый вопрос, который вы должны задать себе. Пытаюсь ли я создать 32-битную или 64-битную программу?

Ответы на вопрос(1)

остерегайтесь ошибок NASM с выходным форматом macho64 с участием64-битная абсолютная адресация (NASM 2.13.02+) и сRIP-родственник в NASM 2.11.08, 64-битная абсолютная адресация не рекомендуется, поэтому этот ответ должен работать даже для глючного NASM 2.13.02 и выше. (Ошибки не вызывают эту ошибку, они приводят к неправильным адресам, используемым во время выполнения.)

[data_items + edi*4] 32-битный режим адресации Четный[data_items + rdi*4] можно использовать только 32-битное абсолютное смещение, поэтому оно тоже не будет работать. Обратите внимание, что использование адреса в качестве 32-разрядного (расширенного знака) немедленного типаcmp rdi, data_items тоже проблема: толькоmov позволяет 64-битный немедленный.

64-разрядный код в OS X вообще не может использовать 32-разрядную абсолютную адресацию, Исполняемые файлы загружаются с базовым адресом выше 4 ГБ, поэтому адреса меток просто не помещаются в 32-разрядные целые числа с расширением нуля или знака. RIP-относительная адресация является лучшим / наиболее эффективным решением, независимо от того, нужна ли вам независимость от позиции или нет1.

В НАСМdefault rel в верхней части вашего файла сделаю все[] Операнды памяти предпочитают RIP-относительную адресацию. Смотрите такжеРаздел 3.3 Эффективные адреса в руководстве NASM.

default rel                     ; near the top of file; affects later instructions

my_func:
    ...
    mov   ecx, [data_items]         ; uses the default: RIP-relative

    ;mov  ecx, [abs data_items]     ; override to absolute [disp32], unusuable
    mov   ecx, [rel data_items]     ; explicitly RIP-relative

Но RIP-относительныйвозможно только тогда, когда другие регистры не задействованы, такдля индексации статического массива сначала нужно получить адрес в регистре, Используйте RIP-родственникlea rsi, [rel data_items].

 lea   rsi, [data_items]    ; can be outside the loop
 ...
 mov   eax, [rsi + rdi*4]

Или ты могadd rsi, 4 внутри цикла и использовать более простой режим адресации, какmov eax, [rsi].

Обратите внимание, чтоmov rsi, data_items будет работать для получения адреса в реестре, но вы не хотите этого, потому что это менее эффективно.

Технически, любой адрес в пределах + -2 ГБ вашего массива будет работать, поэтому, если у вас есть несколько массивов, вы можете адресовать другие относительно одного общего базового адреса, только связывая один регистр с указателем. напримерlea rbx, [arr1] / ... /mov eax, [rbx + rdi*4 + arr2-arr1]. Относительные ошибки адресации - Mac 10.10 упоминает, что в руководстве «Оптимизирующая сборка» Агнера Фога есть несколько примеров адресации массива, в том числе с использованием__mh_execute_header в качестве ориентира. (Код в этом вопросе выглядит как очередная попытка перенести этот 32-битный пример Linux с книги PGU на 64-битную OS X, в то же время, в первую очередь, при изучении asm.)

Обратите внимание, что в Linux зависимые от позиции исполняемые файлы загружаются в нижние 32 бита виртуального адресного пространства, поэтому вы увидите такой кодmov eax, [array + rdi*4] или жеmov edi, symbol_name в примерах Linux или на выходе компилятораhttp://gcc.godbolt.org/. gcc -pie -fPIE создаст независимые от позиции исполняемые файлы в Linux, ипо умолчанию во многих последних дистрибутивах, но не Годболт.

Это не поможет вам на MacOS, но я упомяну об этом на тот случай, если кто-нибудь запутается в коде, который они видели для других ОС, или почему архитекторы AMD64 стараются разрешить[disp32] Режимы адресации у всех на x86-64.

И кстати,предпочитаю использовать 64-битные режимы адресации в 64-битном коде, например использование[rsi + rdi*4]не[esi + edi*4], Обычно вы не хотите усекать указатели до 32-разрядных, и для кодирования требуется дополнительный префикс размера адреса.

Точно так же вы должны использоватьsyscall делать 64-битные системные вызовы, а неint 0x80. Каковы соглашения о вызовах для системных вызовов UNIX и Linux на i386 и x86-64 для различий, в которых регистры для передачи аргументов.

Сноска 1: 64-разрядная абсолютная адресация поддерживается в OS X, но только в позиционно-зависимых исполняемых файлах (не PIE). Этот связанный вопросx64 nasm: вставка адресов памяти в стек и вызов функции включает в себяld предупреждение от использованияgcc main.o связывать:

ld: warning: PIE disabled. Absolute addressing (perhaps -mdynamic-no-pic) not
allowed in code signed PIE, but used in _main from main.o. To fix this warning,
don't compile with -mdynamic-no-pic or link with -Wl,-no_pie

Таким образом, компоновщик проверяет, используются ли какие-либо абсолютные 64-разрядные перемещения, и если это так, отключает создание независимого от позиции исполняемого файла. Пирог может извлечь выгоду изASLR для безопасности. Я думаю, что код разделяемой библиотеки всегда должен быть независимым от позиции в OS X; Я не знаю, разрешены ли таблицы переходов или другие случаи указателей как данных (т.е. исправлены динамическим компоновщиком), или их нужно инициализировать во время выполнения, если вы не делаете зависимый от позиции исполняемый файл.

mov r64, imm64 больше (10 байт) и не быстрее чемlea r64, [RIP_rel32] (7 байт).

Так что вымог использованиеmov rsi, qword data_items вместо REA-относительного LEA, который работает примерно так же быстро и занимает меньше места в кеше кода и кэше uop. 64-битные немедленные также имеют штраф за выборку uop-кэша для семейства Sandybridge (http://agner.org/optimize/): для чтения из строки кэша UOP требуется 2 цикла вместо 1.

x86 также имеет формуmov который загружает / сохраняет с / на 64-битный абсолютный адрес, но только для AL / AX / EAX / RAX. Видетьhttp://felixcloutier.com/x86/MOV.html, Вы тоже этого не хотите, потому что он больше и не быстрееmov eax, [rel foo].

(Связанный:синтаксическая версия AT & T того же вопроса)

 Peter Cordes13 дек. 2017 г., 14:45
Обновление, по-видимому, OS X не требует PIE (независимые от позиции исполняемые файлы), оно просто использует базу изображений выше 32 бит. Так что вымог использованиеmov r64, imm64 помещать адреса в регистры, но не потому, что REA-относительный LEA лучше.
 Peter Cordes07 мая 2018 г., 03:54
Или для неиндексированных нагрузок, вы можете использоватьmovabs eax, [foo] (мнемоника AT & T дляmov al/ax/eax/rax, moffs формаmov с 64-битным абсолютным адресом вместо режима адресации ModR / M. Но опять же, не делайте этого, потому что режим RIP-относительной адресации более компактен и столь же эффективен.

Ваш ответ на вопрос