如何在汇编中以字节数的2位进行交换

Gil*_*lad 3 x86 assembly bit-manipulation

*我正在使用程序集8086(x86-32)

交易非常简单,我在寄存器AL(8位)中有一个字节大小的数字,现在,我需要在寄存器中的第1位(右起第二位)和第4位(右起第五位)之间进行交换AL.

例如:如果Al有这个数字:00010000B现在它将有00000010B.

谢谢!

小智 5

你可以试试这个:

mov BL, AL
mov BH, AL

and BL, 2h   //empty all bits except first
and BH, 10h  //empty all bits except fourth

shl BL, 3    //move bit 1 to position of bit 4
shr BH, 3    //move bit 4 to position of bit 1

and AL, edh  //empty first and fourth bits
or AL, BL    //set bit 4
or AL, BH    //set bit 1
Run Code Online (Sandbox Code Playgroud)

AL 寄存器包含结果。您还可能需要存储在寄存器 BX 中的数据。如果您这样做,则在解决方案前添加

push BX
Run Code Online (Sandbox Code Playgroud)

end 追加到末尾

pop BX
Run Code Online (Sandbox Code Playgroud)


Aki*_*nen 5

一对二指令回答:

and eax, $255; // mask off extra bits  -- perhaps not needed, if upper bits are 
mov al, look_up_table[eax] // guaranteed to be zero
Run Code Online (Sandbox Code Playgroud)

单独使用al的三条指令.

test al, $0x12
jpe skip       ;; parity was even (aka the bits are the same)
xor al, $0x12  ;; toggle both bits
skip:
Run Code Online (Sandbox Code Playgroud)

操作原理:只有当它们不同时才需要交换位.0更改为1和1通过将它们与1进行相关来更改为0.两个位同时受到影响.

如果有条件cmovpo或cmovpe,则可以避免跳转.但在这种情况下,序列需要至少4条指令(取决于是否已知某些寄存器包含零或位掩码).

或者,如果&mask只设置了一个位,则可以选择测试.这是用表达式完成的(a ==(a&-a))

  • 哇!在使用了近 20 年的 asm 编码之后,这是我第一次看到使用奇偶校验位。 (2认同)
  • 我编辑修复了 Intel 和 AT&T 语法的混合,现在使用纯 Intel 语法。我最终注意到还有更多需要改进的地方,例如“movzx”而不是“and eax, 255”。您还建议“cmov”需要*至少* 4 条指令,但如果您有可以使用的临时寄存器,则无需任何其他先决条件即可使用 4 条指令。(添加了一个代码块)。另外,你的“single_bit_set(a & mask)”想法很有趣,但你需要排除“a & mask”,我认为你没有这样做。如果要交换的两个位中的任何一个在低 8 位之外,这就是正确的方法。 (2认同)