gpt4 book ai didi

assembly - x86 汇编 16 位与 8 位立即操作数编码

转载 作者:行者123 更新时间:2023-12-01 11:13:32 25 4
gpt4 key购买 nike

我正在编写自己的汇编程序并尝试对 ADC 指令进行编码,我对立即值有疑问,尤其是在将 8 位值添加到 AX 寄存器时。

添加 16 位值时:adc ax, 0xff33被编码为 15 33 ff哪个是正确的。
但是如果 adc ax, 0x33 是否重要?被编码为 15 33 00 ?

Nasm 将其编码为 83 d0 33这显然是正确的,但我的方法也正确吗?

最佳答案

x86 通常有超过 1 种有效的指令编码方式。例如大多数 op reg, reg 指令都可以选择通过 op r/m, regop reg, r/m 操作码进行编码。

是的,通常您希望汇编程序始终为指令选择最短的编码。 NASM 甚至将 mov rax, 1(mov r64, sign_extended_imm32 的 7 个字节)优化为 x86-64 的 mov eax, 1(5 个字节),更改操作数大小以使用写入 32 位寄存器的零扩展,而不是 32 位的显式符号扩展即时。

在可用时使用符号扩展 imm8 编码总是好的

它对于 16 位长度相等,但对于 32 位操作数大小较短,因此它简化了您的代码以始终选择 imm8

操作数大小为 32 位时,op eax, imm32 为 5 个字节,而 op r/m32, imm8 仍为 3 个字节。 (不包括设置操作数大小或其他内容所需的任何前缀;两者都是相同的。)

imm8 编码的性能优势

如果需要操作数大小前缀(例如在 adc ax, 0x33 的 32 位模式下),使用带有操作数大小前缀的 adc ax/eax/rax, imm16/32/32 编码将在 Intel CPU 上创建 LCP 停顿(长度更改前缀意味着前缀更改长度指令的其余部分。这不会发生在 imm8 编码中,因为无论操作数大小如何,它仍然是(前缀)+ 操作码 + modrm + imm8。

请参阅 Agner Fog's microarch.pdf 中的 x86 tag wiki 和其他性能链接。另请参阅 x86 instruction encoding how to choose opcode,它与此相同,除了 adc 是一个特殊情况。

adc/sbb 的特定情况下,避免 ax, imm16 编码还有另一个优势:通过 Haswell 参见 Sandybridge 上的 Which Intel microarchitecture introduced the ADC reg,0 single-uop special case?adc ax, 0 被特例视为单 uop 指令,而不是 3 输入 uop 的普通 2(斧头,旗帜,立即)。

但是这种特殊的 shell 不适用于 no-ModRM 短格式编码,因此 3 字节的 adc ax, imm16 仍然解码为 2 uops 。只有 imm8 形式的解码器在解码为单个 uop 之前检查立即数是否为零。 (它仍然不适用于 adc al, imm8 。)

所以总是尽可能选择符号扩展的 imm8 也是最佳选择, 即使在 adc ax,0 不需要操作数大小前缀的 16 位模式下也是如此,因此不会发生 LCP 停顿问题。

大多数汇编程序不提供覆盖来避免 no-ModRM 短格式。在设计它们时,除了有意延长指令以获得对齐而不在循环顶部或其他分支目标之前添加 NOP 之外,没有其他性能用例:What methods can be used to efficiently extend instruction length on modern x86?

如果您正在设计一种新的 asm 语法风格,您可能会考虑允许使用 override 关键字对编码进行更多控制。对于现有设计,查看 NASM 的 strictnosplit 关键字,以及 GAS 的 {vex2}{vex3}{disp32} 等“前缀”

  • How to force NASM to encode [1 + rax*2] as disp32 + index*2 instead of disp8 + base + index? 用于 nosplit 以强制对 LEA 进行更长更有效的编码。
  • How do GNU assembler x86 instruction suffixes like ".s" in "mov.s" work?(GAS {disp32} 等,以及 {load}{store} 以选择您喜欢的 op r/m, rop r, r/m 编码中的哪一个。)
  • Sign or Zero Extension of address in 64bit mode for MOV moffs32? 在 64 位模式下,带有 no-modrm a32 mov eax, [0x123456] 编码的 moffs 会导致 Intel CPU 上的 LCP 停顿。对于绝对寻址,它比 modrm+SIB+disp32 短,但可能更慢。
  • Why NASM on Linux changes registers in x86_64 assembly NASM mov rax,1(5 字节)与 mov rax, strict dword 1(7 字节)与 mov rax, strict qword 1(10 字节 imm64 编码)
  • 关于assembly - x86 汇编 16 位与 8 位立即操作数编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56524046/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com