Для x86 характерно иметь более 1 допустимого способа кодирования инструкции.Например, большинство op reg, reg
инструкций могут выбирать кодировку с помощью операционного кода op r/m, reg
или op reg, r/m
.
И да, обычно вы хотите, чтобы ассемблер всегда выбирал для инструкции самую короткую кодировку.NASM даже оптимизирует mov rax, 1
(7 байт для mov r64, sign_extended_imm32
) в mov eax, 1
(5 байт) для x86-64, изменяя размер операнда, чтобы использовать нулевое расширение вместо записи 32-битного регистра вместо явного знака-расширение 32-битного немедленного.
Использование кодировки sign-extended-imm8, когда доступно, всегда хорошо
Это равная длина для 16-битного, но короче для 32-битного размера операндаТаким образом, это упрощает ваш код, чтобы он всегда выбирал imm8
.
. Размер операнда 32-битный, op eax, imm32
равен 5 байтам, тогда как op r/m32, imm8
все еще равен 3 байтам.(Не считая префиксов, необходимых для установки размера операнда или других вещей; они будут одинаковыми для обоих.)
Преимущества производительности кодировки imm8
Если требуется префикс размера операнда, требуется(например, в 32-битном режиме для adc ax, 0x33
), использование кодировки adc ax/eax/rax, imm16/32/32
с префиксом размера операнда создаст стойку LCP на процессорах Intel (префикс изменения длины означает, что префикс изменяет длину rest инструкции. Этого не происходит для кодировки imm8, потому что она все еще (префикс) + код операции + modrm + imm8 независимо от размера операнда.
См. Agner Fog's microarch.pdf и другие ссылки на производительность в теге x86 вики . См. Также x86 инструкция, кодирующая, как выбрать код операции , который является его дубликатом, крометот факт, что adc
является особым случаем.
В конкретном случае adc
/ sbb
есть еще одно преимущество, позволяющее избежать кодировки ax, imm16
: См. Какой Intelмикроархитектура яне представил ADC reg, 0 особый случай с одним мопом? На Sandybridge через Haswell, adc ax, 0
имеет специальный регистр как инструкция с одним мопом, вместо обычного 2 для мопов с 3 входами (ax, flags,Немедленно).
Но этот специальный регистр не работает для кодировок коротких форм без ModRM, поэтому 3-байтовый adc ax, imm16
все еще декодирует до 2 моп .Только декодер для формы imm8
проверяет, является ли непосредственный ноль перед декодированием в один моп.(И это все еще не работает для adc al, imm8
.)
Так что всегда лучше выбирать вариант sign-extended-imm8, когда это возможно, для этого тоже даже в 16-битном режимегде префикс размера операнда не потребуется для adc ax,0
, и, следовательно, проблема с остановкой LCP не возникнет.
Большинство ассемблеров не предоставляют переопределения, чтобы избежать краткой формы no-ModRM,Когда они были спроектированы, не было ни одного варианта использования производительности, кроме намеренного удлинения инструкций для получения выравнивания без добавления NOP перед вершиной цикла или другой целью ветвления: Какие методы можно использовать для эффективного увеличения длины инструкции насовременный x86?
Если вы разрабатываете новый вариант синтаксиса asm, вы можете подумать о предоставлении большего контроля над кодированием с помощью переопределенных ключевых слов.Для существующих конструкций проверьте ключевые слова strict
и nosplit
NASM, а также префиксы GAS {vex2}
, {vex3}
, {disp32}
и т. Д.
- Как заставитьNASM для кодирования [1 + rax * 2] в виде disp32 + index * 2 вместо disp8 + base + index? для
nosplit
для принудительного более длительного и эффективного кодирования для LEA. Как работают суффиксы инструкций GNU на ассемблере x86, такие как ".s" в "mov.s"? (GAS {disp32}
и т. Д., И {load}
или {store}
, чтобы выбрать, какой из op r/m, r
против op r, r/m
кодировка, которую вы предпочитаете.)
Знак или нулевое расширение адреса в 64-битном режиме для MOV moffs32? В 64-битном режиме a32 mov eax, [0x123456]
с кодировкой no-modrm moffs
вызывает остановку LCP на процессорах Intel.Для абсолютной адресации он короче, чем modrm + SIB + disp32, но потенциально медленнее.
- Почему NASM в Linux меняет регистры в сборке x86_64 NASM
mov rax,1
(5 байт) против mov rax, strict dword 1
(7 байт) против mov rax, strict qword 1
(10 байт imm64
кодировка)