x86汇编中如何单独旋转字节的高4位与低4位?
解决x86汇编中单独旋转字节高低四位的问题
这个需求其实可以通过拆分字节、利用旋转指令+位操作轻松实现,核心思路是把高4位和低4位分开处理,各自完成旋转后再合并结果。针对你给出的0xB4 → 0x72的例子,我给你两种可行的实现方案:
方案一:用rol/ror旋转指令(简洁高效)
rol(循环左移)和ror(循环右移)指令天生适合这种“把移出的位循环补到另一端”的需求,我们只需要先把目标4位移到寄存器的低4位(或高4位),就能直接用旋转指令完成操作。
假设待处理的字节存在AL寄存器中,最终结果也会保存在AL里:
; 输入:AL = 0xB4(二进制 1011 0100) ; 输出:AL = 0x72(二进制 0111 0010) mov bl, al ; 先把原始字节备份到BL,避免后续操作覆盖 ; 处理高4位:左旋转1位 mov ah, al shr ah, 4 ; 把高4位移到低4位,此时AH = 0xB(二进制 1011) rol ah, 1 ; 对低4位左旋转1位,1011 → 0111,AH = 0x7 shl ah, 4 ; 把旋转后的高4位移回原位置,AH = 0x70(二进制 0111 0000) ; 处理低4位:右旋转1位 mov al, bl and al, 0Fh ; 提取低4位,此时AL = 0x4(二进制 0100) ror al, 1 ; 对低4位右旋转1位,0100 → 0010,AL = 0x2 ; 合并高低四位的结果 or al, ah ; AL = 0x70 | 0x2 = 0x72
步骤解释:
- 备份原始字节到
BL是为了后续分别处理高低位时,都能拿到原始值。 - 处理高4位时,我们先把它移到寄存器的低4位,这样
rol ah,1就会把原高4位的最高位(1)循环补到低4位的最低位,完美实现4位左旋转。 - 处理低4位时,直接提取后用
ror al,1,把低4位的最低位(0)循环补到最高位,完成4位右旋转。 - 最后用
or指令把两个处理后的部分合并成最终字节。
方案二:纯位运算实现(无需旋转指令)
如果不想用旋转指令,也可以通过移位、与、或运算手动实现循环移位的逻辑:
; 输入:AL = 0xB4 ; 输出:AL = 0x72 mov bl, al ; 备份原始字节 ; 计算高4位左旋转1位后的结果 mov ah, bl and ah, 0F0h ; 提取高4位:0xB0 shl ah, 1 ; 左移1位:0x60 mov dl, bl and dl, 80h ; 提取原高4位的最高位:0x80 shr dl, 3 ; 把这个位移到高4位的最低位位置:0x10 or ah, dl ; 合并得到高4位旋转后的部分:0x70 ; 计算低4位右旋转1位后的结果 mov al, bl and al, 0Fh ; 提取低4位:0x4 shr al, 1 ; 右移1位:0x2 mov cl, bl and cl, 01h ; 提取原低4位的最低位:0x0 shl cl, 3 ; 把这个位移到低4位的最高位位置:0x0 or al, cl ; 合并得到低4位旋转后的部分:0x2 ; 合并最终结果 or al, ah ; AL = 0x72
逻辑说明:
- 高4位左旋转1位 =
(高4位左移1位) | (原高4位最高位移到高4位的最低位) - 低4位右旋转1位 =
(低4位右移1位) | (原低4位最低位移到低4位的最高位)
验证例子
对于输入0xB4(二进制1011 0100):
- 高4位
1011左旋转1位 →0111(对应0x70) - 低4位
0100右旋转1位 →0010(对应0x2) - 合并后就是
0111 0010,即0x72,完全符合你的需求。
这个思路可以扩展到其他4位旋转的场景,比如旋转2位、3位,只需要调整旋转指令的次数或者位运算的移位位数就可以了。
内容的提问来源于stack exchange,提问作者agentosage
相关产品推荐
相关产品推荐

