Да, переместитесь в регистр, а затем в память для немедленных действий, которые не подходят для 32-разрядной версии с расширенным знаком, в отличие от -1
aka 0xFFFFFFFFFFFFFFFF
. Тем не менее, часть почему представляет собой интересный вопрос:
Помните, что asm позволяет делать только то, что возможно в машинном коде. Таким образом, это действительно вопрос о дизайне ISA. Такие решения часто связаны с тем, что оборудование легко декодирует, а также с соображениями эффективности кодирования. (Использовать коды операций в редко используемых инструкциях было бы плохо.)
Он не предназначен для того, чтобы усложнять задачу, он предназначен для того, чтобы не требовать никаких новых кодов операций для mov
. А также для ограничения 64-битных непосредственных команд одним специальным форматом инструкций. mov
- единственная инструкция, которая может когда-либо использовать 64-битный немедленный вообще (или 64-битный абсолютный адрес для загрузки / сохранения AL / AX / EAX / RAX).
Ознакомьтесь с руководством Intel для форм mov
(обратите внимание, что он использует синтаксис Intel, сначала назначение, и мой ответ.) Я также резюмировал формы (и длину их инструкций) в Разница между movq и movabsq в x86-64, как и @MargaretBloom в ответ на В чем разница между командами x86-64 AT&T movq и movabsq?.
Разрешение imm64 вместе с режимом адресации ModR / M также позволило бы довольно легко достичь 15-байтового верхнего предела длины инструкции, например Код операции REX + + imm64 составляет 10 байтов, а ModRM + SIB + disp32 - 6. Таким образом, mov [rdi + rax*8 + 1234], imm64
не будет кодироваться, даже если был код операции для mov r/m64, imm64
.
И это при условии, что они перепрофилировали один из однобайтовых кодов операций, которые были освобождены, сделав некоторые инструкции недействительными в 64-битном режиме (например, aaa
), что может быть неудобно для декодеров (и предварительных декодеров длины инструкций), потому что в других режимы, в которых эти коды операций не принимают байт ModRM или немедленное выполнение.
movq
предназначен для форм mov
с обычным байтом ModRM, чтобы разрешить произвольный режим адресации в качестве пункта назначения. (или в качестве источника для movq r64, r/m64
). AMD решила оставить для них 32-разрядную версию сразу же, как и при 32-разрядном размере операнда 1.
Эти формы mov
имеют тот же формат инструкций, что и другие инструкции, такие как add
. Для простоты декодирования это означает, что префикс REX не изменяет длину инструкции для этих кодов операций. Декодирование длины инструкции уже достаточно сложно, когда режим адресации имеет переменную длину.
Итак, movq
имеет 64-битный размер операнда, но в остальном тот же формат инструкции mov r/m64, imm32
(становится формой с расширенным знаком, такой же, как и любая другая инструкция, которая имеет только одну непосредственную форму), и mov r/m64, r64
или mov r64, r/m64
.
movabs
- это 64-разрядная форма существующей краткой формы no-ModRM mov reg, imm32
. Это уже особый случай (из-за кодирования no-modrm, с номером регистра из младших 3 бит байта кода операции). Небольшие положительные константы могут просто использовать 32-битный размер операнда для неявного нулевого расширения до 64-битного без потери эффективности (например, 5-байтовый mov eax, 123
/ AT&T mov $123, %eax
в 32-битном или 64-битном режиме). И наличие 64-битного абсолютного mov
полезно, так что это логично, что AMD сделала это.
Поскольку байта ModRM нет, он может кодировать только адресат регистра. Чтобы добавить форму, которая могла бы принимать операнд памяти, потребовался бы совершенно другой код операции.
Из одного POV, будьте благодарны, вы получаете mov
с 64-битными немедленно вообще; RISC ISA, такие как AArch64 (с 32-разрядными инструкциями фиксированной ширины), нуждаются в более чем 4 инструкции только для того, чтобы получить 64-разрядное значение в регистре. (Если это не повторяющийся битовый шаблон; AArch64 на самом деле довольно крутой. В отличие от более ранних RISC, таких как MIPS64 или PowerPC64)
Если AMD64 собиралась ввести новый код операции для mov
, mov r/m, sign_extended_imm8
было бы гораздо более полезным для экономии размера кода. Компиляторы нередко могут выдавать несколько mov qword ptr [rsp+8], 0
инструкций для обнуления локального массива или структуры. , каждый из которых содержит 4-байтовый 0
немедленный. Помещение ненулевого малого числа в регистр довольно распространено и сделает mov eax, 123
3-байтовую инструкцию (меньше 5), а mov rax, -123
4-байтовую инструкцию (меньше 7). Это также сделало бы обнуление регистра без затирания FLAGS 3 байта.
Разрешение mov
imm64 в память было бы полезным достаточно редко, поэтому AMD решила, что не стоит усложнять декодеры. В этом случае я согласен с ними, но AMD была очень консервативна при добавлении новых кодов операций. Так много упущенных возможностей убрать бородавки x86, вроде расширения setcc
было бы неплохо. Но я думаю, что AMD не была уверена, что AMD64 завоюет популярность, и не хотела зависать, нуждаясь в большом количестве дополнительных транзисторов / мощности для поддержки функции, если люди ее не используют.
Сноска 1:
В общем, 32-битное немедленное преобразование - довольно хорошее решение для размера кода. Очень редко нужно add
немедленно обратиться к чему-то, что выходит за пределы диапазона + -2 ГиБ. Это может быть полезно для побитовых вещей, таких как AND
, но для установки / очистки / переворота одного бита хороши инструкции bts
/ btr
/ btc
(принятие битовой позиции как 8-битное немедленно, вместо необходимости маски). Вы не хотите, чтобы sub rsp, 1024
была 11-байтовой инструкцией; 7 уже достаточно плохо.
Гигантские инструкции? Не очень эффективно
В то время, когда разрабатывалась AMD64 (начало 2000-х), процессоры с кэшем uop не использовались. (Intel P4 с кешем трассировки действительно существовал, но в ретроспективе это было расценено как ошибка.) Выборка / декодирование инструкций происходит фрагментами размером до 16 байт, поэтому наличие одной инструкции размером почти 16 байт не намного лучше для интерфейс, чем movabs $imm64, %reg
.
Конечно, если серверная часть не успевает за клиентской частью, то пузырек, состоящий только из 1 инструкции, декодированной в этом цикле, может быть скрыт путем буферизации между этапами.
Отслеживание такого количества данных для одной инструкции также может стать проблемой. ЦП должен куда-то поместить эти данные, и если есть 64-битное немедленное и 32-битное смещение в режиме адресации, это много бит. Обычно инструкции требуется максимум 64 бита для imm32 + disp32.
Кстати, есть специальные коды операций no-modrm для большинства операций с RAX и немедленным. (x86-64 развился из 8086, где AX / AL был более особенным, см. this для получения дополнительной истории и объяснения). Для тех add/sub/cmp/and/or/xor/... rax, sign_extended_imm32
форм без ModRM было бы вполне правдоподобно использовать вместо этого полный imm64. Самый распространенный случай для RAX, немедленное использование 8-битного расширенного знака (-128..127), во всяком случае не этой формы, и он сохраняет только 1 байт для инструкций, которым требуется 4-байтовый немедленный. Однако, если вам нужна 8-байтовая константа, лучше поместить ее в регистр или память для повторного использования, чем выполнять 10-байтовую и-imm64 в цикле.
person
Peter Cordes
schedule
07.07.2020
movq $0xFFFFFFFFFFFFFFFF, (%rax)
кодируется, потому что старшие 32 бита соответствуют биту №32. All-F = все-единицы, что совпадает с-1
в дополнении до 2. Что-то вроде0x12345678abcd
, которое имеет более 32 значащих битов, будет работать в качестве примера. (И легче грокнуть, чем просто отказаться от одного из F). - person Peter Cordes   schedule 07.07.2020movq $0x123456789abcdef, %rbp
в тот же машинный код, что иmovabsq
. Он сразу же замечает, что число не помещается в 32-битное, и автоматически выбирает 64-битный, потому что это возможно для адресата регистра. (Он не делает этого автоматически для констант времени ассемблера, которые еще не были определены, или для адресов, потому что адреса иногда могут быть 32-битными. Поэтому явная записьmovabs
по-прежнему иногда необходима.) Все это не связано с однако актуальный вопрос, почему у вас не может быть места назначения в памяти. - person Peter Cordes   schedule 07.07.2020