В ассемблере ATT при использовании инструкции leaq должен ли ее первый операнд быть адресом памяти, а не регистром или константой (с префиксом $
)? Должен ли его второй операнд быть регистром? У меня сложилось такое впечатление, когда я прочитал «Компьютерные системы: взгляд программиста», и я никогда не видел примера, отличного от моего предположения. Спасибо.
Спасибо. Я искал справочный документ в Интернете, но не уверен, где он находится.
@Jester Спасибо. Какие виды умственной работы?
Перевод с intel на at & t. Например. С [base+index*scale+displacement]
на displacement(base, index, scale)
@fuz, вы можете удалить этот комментарий и попробовать еще раз.
Также меняем порядок операндов (Intel - dest, src, а AT&T - src, dest).
Да, это правильно. Хотя lea
с двумя операндами регистров технически может быть закодирован, такое кодирование недопустимо и приводит к исключению #UD
. Подробнее см. эта ссылка или Вот этот.
Даже если бы он был кодируемым, вы бы никогда не захотели его использовать.
Если вы хотите поместить константу в регистр, никогда не используйте lea
. mov $1234, %eax
короче и эффективнее lea 1234, %eax
(абсолютный адрес в режиме адресации disp32).
Единственный вариант использования LEA для статических адресов - это 64-битный код с режимами относительной адресации RIP, например lea symbol(%rip), %rax
(7 байтов), в случаях, когда mov $symbol, %eax
(5 байтов) не может использоваться, потому что вам нужен независимый от позиции код, и / или адрес не вписывается в 32-битное немедленное расширение с нулевым расширением.
См. Разница между movq и movabsq в x86-64, чтобы узнать, почему mov $symbol, %rdi
не лучший выбор.
В 32-битном коде lea symbol, %edi
занимает 6 байтов (код операции + modrm + disp32) и запускает только один порт 1 или порт 5 на процессорах семейства Intel Sandybridge. (https://agner.org/optimize/)
mov $symbol, %edi
занимает 5 байтов (код операции + короткая форма imm32 без байта ModRM) и работает на любом порту ALU.
То же самое для 16-битного кода: mov $symbol, %di
составляет 3 байта, а lea symbol, %di
- 4 байта, с теми же различиями в портах выполнения. (Или в синтаксисе NASM, lea di, [symbol]
против mov di, symbol
, или mov di, OFFSET symbol
в GAS .intel_syntax
или MASM.)
Однако LEA полезен с режимами адресации base = register. Подобно lea symbol(%rdi), %rax
, если адрес соответствует 32-битному расширенному знаку disp32.
Или для произвольного использования сдвига и добавления, например lea 123(%rdi, %rdi, 2), %eax
для eax = 3*edi + 123
. Используете LEA для значений, которые не являются адресами / указателями?
Да, это правильно. В случае сомнений обратитесь к официальному справочнику по набору инструкций. Обратите внимание, что адрес памяти, конечно, может использовать регистр или смещение (без
$
, поскольку это было бы немедленно).