x86 汇编语言位运算

核心位运算指令

1. 逻辑位运算指令

这些指令按位操作,CF 和 OF 标志位总被清零(0),SF 和 ZF 根据结果设置。

指令 格式 真值表/操作 核心用途与典型场景
AND AND dest, src 按位与:1&1=1, 其他=0 ① 位清零(屏蔽):将特定位设为0。
AND AL, 11110111b ; 清零第3位
② 测试奇偶:AND AL, 1 测试最低位。
OR OR dest, src 按位或:`0 0=0`, 其他=1 ① 位置1(设置):将特定位设为1。
OR AL, 00001000b ; 设置第3位为1
② 合并位域。
XOR XOR dest, src 按位异或:相同=0, 不同=1 ① 位取反(翻转):与1异或翻转该位。
XOR AL, 00001000b ; 翻转第3位
② 寄存器清零:XOR EAX, EAX 比 MOV EAX, 0 更快。
③ 简单加密/交换值(无需临时变量)。
NOT NOT op 按位取反:0→1, 1→0 求反码。不影响任何标志位。

应用示例:

MOV  AL, 10101100b
AND  AL, 11110111b    ; AL = 10100100b (清零第3位)
OR   AL, 00001000b    ; AL = 10101100b (设置第3位)
XOR  AL, 00001111b    ; AL = 10100011b (低4位翻转)
NOT  AL               ; AL = 01011100b (按位取反)

2. 移位指令

通过移位,可以高效地进行乘除运算和位提取。

flowchart LR subgraph A[逻辑/算术移位] direction LR A1[SHL/SAL] --> A2[左移: 高位出<br>进CF, 低位补0] A3[SHR] --> A4[逻辑右移: 低位出<br>进CF, 高位补0] A5[SAR] --> A6[算术右移: 低位出<br>进CF, 高位补符号位] end subgraph B[循环移位] direction LR B1[ROL] --> B2[循环左移: 高位出<br>同时进CF和低位] B3[ROR] --> B4[循环右移: 低位出<br>同时进CF和高位] end subgraph C[带进位的循环移位] C1[RCL] --> C2[通过CF循环左移] C3[RCR] --> C4[通过CF循环右移] end

移位指令详解:

指令 格式 对标志位的影响 典型用途
SHL/SAL SHL dest, count CF = 移出的最后一位;OF(count=1时)表示符号位是否改变;SF、ZF 根据结果设置 无符号数 × \(2^n\);提取高位
SHR SHR dest, count 同上 无符号数 ÷ \(2^n\);提取低位
SAR SAR dest, count 同上,但 OF=0(符号位不变) 有符号数 ÷ \(2^n\)(向负无穷舍入)
ROL ROL dest, count CF = 移出的最后一位;OF(count=1时)表示符号位是否改变 位重组,高位循环至低位
ROR ROR dest, count 同上 位重组,低位循环至高位
RCL RCL dest, count 将 CF 作为扩展位融入循环 多精度移位(操作大于64位的数据)
RCR RCR dest, count 同上 多精度移位

移位示例:

; 算术运算
MOV  CL, 3
MOV  EAX, 5          ; 5d = 00000101b
SHL  EAX, CL         ; EAX = 00101000b = 40d (5*2^3)

; 位提取与重组
MOV  AL, 11001011b
SHR  AL, 4           ; AL = 00001100b (提取高4位至低4位)
ROL  AL, 2           ; AL = 00110000b (将低4位循环至高4位)

; 有符号除法
MOV  BL, -16         ; BL = 11110000b (-16)
SAR  BL, 2           ; BL = 11111100b (-4) (有符号除以4)

3. 位测试与扫描指令

这些指令专为位操作设计,能高效地测试和定位特定位。

指令 格式 操作与标志位影响 核心用途
TEST TEST op1, op2 对两操作数做逻辑 AND,根据结果设置 SF、ZF、PF,并清零 CF、OF 测试特定位是否置1:不破坏原值。
TEST AL, 00100000b ; 测试第5位
BT BT op1, op2 将 op1 的第 op2 位的值复制到 CF 测试特定位,支持位索引变量。
BTS BTS op1, op2 同 BT,然后将该位置1(Set) 测试并设置(原子操作,用于锁机制)。
BTR BTR op1, op2 同 BT,然后将该位清零(Reset) 测试并清零。
BTC BTC op1, op2 同 BT,然后将该位取反(Complement) 测试并翻转。
BSF BSF dest, src 从低位向高位扫描,找到第一个置1的位,将其索引存入 dest,若 src=0 则 ZF=1 寻找最低有效位1。
BSR BSR dest, src 从高位向低位扫描,找到第一个置1的位,将其索引存入 dest,若 src=0 则 ZF=1 寻找最高有效位1。

位测试与扫描示例:

; 使用TEST检查标志
TEST  DX, 00000001b
JNZ   BitIsSet        ; 如果最低位为1则跳转

; 使用BT系列指令(操作位索引)
MOV   EAX, 0F0h       ; 位模式: 11110000b
MOV   EBX, 5
BT    EAX, EBX        ; 测试第5位(从0计数), CF=1 (第5位是1)
BTR   EAX, 6          ; 测试并清零第6位, 之后CF=1, EAX=10110000b

; 使用BSF寻找位
MOV   EDX, 00000100b
BSF   ECX, EDX        ; ECX = 2 (找到第2位为1)
BSR   ECX, EDX        ; ECX = 2 (此时与BSF结果相同)

关键编程提示与常见陷阱

  1. 明确操作数大小:使用 BYTE PTR、WORD PTR 等修饰符避免歧义,尤其是在操作内存时。
  2. 利用 XOR 清零:XOR EAX, EAX 是清零寄存器的最优指令(代码尺寸小,执行快)。
  3. 移位计数的特殊性:count 通常放在 CL 寄存器中,或直接使用立即数。在 32/64 位模式下,count 会被隐式掩码(8086 为 & 0x1F,即只取低5位),因此移 32 位等于移 0 位,移 33 位等于移 1 位。
  4. 注意 NOT 与 NEG:NOT 是位取反(求反码),NEG 是算术取负(求补码:NEG a = 0 - a)。NOT a 等于 -a - 1(有符号视角)。
  5. 位测试的灵活性:TEST 指令非常高效,常用于判断奇偶、检查标志位或对齐检查(如 TEST ESP, 0FFFh 检查栈是否 4KB 对齐)。
  6. BSF/BSR 的零值处理:使用 BSF 或 BSR 前,最好先用 TEST 判断源操作数是否为 0,因为当源为 0 时,目标寄存器的值是未定义的(不同 CPU 可能结果不同)。
  7. 原子性操作:BTS、BTR、BTC 指令在多线程环境下对内存操作时,可以加 LOCK 前缀保证原子性,用于实现自旋锁或位图分配器。
posted @ 2025-12-20 13:25  ffff5  阅读(119)  评论(0)    收藏  举报