核心位运算指令
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 LRsubgraph A[逻辑/算术移位]direction LRA1[SHL/SAL] --> A2[左移: 高位出<br>进CF, 低位补0]A3[SHR] --> A4[逻辑右移: 低位出<br>进CF, 高位补0]A5[SAR] --> A6[算术右移: 低位出<br>进CF, 高位补符号位]endsubgraph B[循环移位]direction LRB1[ROL] --> B2[循环左移: 高位出<br>同时进CF和低位]B3[ROR] --> B4[循环右移: 低位出<br>同时进CF和高位]endsubgraph 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结果相同)
关键编程提示与常见陷阱
- 明确操作数大小:使用
BYTE PTR、WORD PTR等修饰符避免歧义,尤其是在操作内存时。 - 利用 XOR 清零:
XOR EAX, EAX是清零寄存器的最优指令(代码尺寸小,执行快)。 - 移位计数的特殊性:
count通常放在CL寄存器中,或直接使用立即数。在 32/64 位模式下,count会被隐式掩码(8086 为& 0x1F,即只取低5位),因此移 32 位等于移 0 位,移 33 位等于移 1 位。 - 注意 NOT 与 NEG:
NOT是位取反(求反码),NEG是算术取负(求补码:NEG a = 0 - a)。NOT a等于-a - 1(有符号视角)。 - 位测试的灵活性:
TEST指令非常高效,常用于判断奇偶、检查标志位或对齐检查(如TEST ESP, 0FFFh检查栈是否 4KB 对齐)。 - BSF/BSR 的零值处理:使用
BSF或BSR前,最好先用TEST判断源操作数是否为 0,因为当源为 0 时,目标寄存器的值是未定义的(不同 CPU 可能结果不同)。 - 原子性操作:
BTS、BTR、BTC指令在多线程环境下对内存操作时,可以加LOCK前缀保证原子性,用于实现自旋锁或位图分配器。