【问题标题】:Swap most significant byte and least significant byte in assembler在汇编程序中交换最高有效字节和最低有效字节
【发布时间】:2017-08-11 17:02:37
【问题描述】:

假设我们将数字 1 保存在 EAX-Register 中,并将最高有效字节与最低有效字节交换。新交换的号码是 256 还是 16777216?

我在汇编程序中尝试了将 AL- 的值与 AH-Register 的值交换。我的结果是 256。我认为这是不正确的,我也不理解 256 的结果。我认为 EAX-Register 是 32 位的,而不是 16 位的。

问题与交换的正确结果有关。

【问题讨论】:

  • EAX 是 32 位,AX 是 EAX 的低 16 位,AL 和 AH 是 AX 的低字节和高字节。无法直接访问 EAX 的前 16 位。见,相关:Get the upper half of the EAX register
  • 如果我可以通过 AX 寄存器获得低 16 位,我如何获得 EAX 寄存器的高位?
  • 见上......
  • 交换最低和最高有效字节时0x00000001的值自然是0x01000000。如果您在将其解释为整数时询问该值的十进制表示形式,那么,是的,该值为 16777216。

标签: assembly x86 byte cpu-registers


【解决方案1】:

为此有一个特殊的操作码,称为BSWAP,例如:

    MOV     EAX,1   ; EAX is 0x00000001  or 1 decimal  
    BSWAP   EAX     ; EAX is 0x01000000  or 16777216 decimal

它将交换任何 32 位通用寄存器的 全部 4 个字节。这会将 little-endian 32 位值转换为 big-endian,反之亦然。

FWIW,交换 16 位值的字节,例如在AX,你可以做

    MOV     AX,1    ; AX is 0x0001 or 1 decimal
    XCHG    AL,AH   ; AX is 0x0100 or 256 decimal

或者,根据@PeterCordes:

    MOV     AX,0x1234
    ROL     AX,8    ; AX is 0x3412 now

没有特殊的操作码可以交换 32 位寄存器的高字节和低字节(并保持其他两个不变)。你只能这样做:

编辑

ROR、XCHG AL,AHROLBSWAP的代码>

正如@Fifoernik 在评论中指出的那样(谢谢!),比我删除的代码容易得多:

    MOV     EAX,0x12345678
    ROL     EAX,8   ; EAX is 0x34567812  rotate left one byte: 12 34 56 78 --> 34 56 78 12
    XCHG    AL,AH   ; EAX is 0x34561278  swap 12 and 78:       34 56 78 12 --> 34 56 12 78
    ROR     EAX,8   ; EAX is 0x78345612  rotate back:          34 56 12 78 --> 78 34 56 12

编辑 2

正如@PeterCordes 指出的那样,这甚至可能会更快一些:

    MOV     EAX,0x12345678
    ROL     EAX,8   ; EAX is 0x34567812  rotate left one byte: 12 34 56 78 --> 34 56 78 12
    ROL     AX,8    ; EAX is 0x34561278  swaps 12 and 78:      34 56 78 12 --> 34 56 12 78
    ROR     EAX,8   ; EAX is 0x78345612  rotate back:          34 56 12 78 --> 78 34 56 12

但我没有计时。

【讨论】:

  • 也许向 OP 说明为什么交换 ah 和 al 会产生这个结果是有用的。
  • 为什么在最后的sn-p中坚持使用BSWAP?它只需要这 3 个步骤:ROL EAX,8XCHG AL,AH`ROR EAX,8`。
  • ROL AX,8 在大多数 CPU 上应该比 xchg al,ah 更高效,因为它是 1 uop 而不是 3。它还避免了 Intel Haswell/Skylake 上的任何部分寄存器合并 uops。它也适用于任何 reg,包括 R8W...R15W。 (在 Intel Haswell/Skylake 上,出于某些目的,high8 寄存器比 low8/low16 寄存器慢;在撰写有关此问题的问答过程中;完成后将发布链接。总结:我认为只有 AH 与 RAX 分开重命名;AL而 AX 不会。此外,读取 AH 会增加 1c 的延迟。)
  • 这很酷。我首先有一个 2 套准解决方案,然后是一个 1 套准解决方案,然后由 Fifoernik 改进以反向旋转,现在甚至 AX 也由 Peter Cordes 旋转。 尽管对于不熟悉 x86 汇编的人来说,XCHG AL,AH 可能比 ROL AX,8 更容易理解,即使两者实现的效果相同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-07
  • 2014-12-28
相关资源
最近更新 更多