在8086汇编中,TEST指令用于在不改变原始数据的情况下 测试指定位是0还是1,然后通常用JZ或JNZ指令根据测试结果进行跳转。
核心逻辑很简单:TEST对两个操作数执行"按位与"(AND)操作,结果不保存,但会影响ZF(零标志位)。
-
如果结果为零 ,则ZF = 1 (
JZ会跳转,意味着被测试的位都是0)。 -
如果结果非零 ,则ZF = 0 (
JNZ会跳转,意味着至少有一位是1)。
基础用法:测试单个位
最常用的场景是测试寄存器或内存中某一位的值。
语法示例:
assembly
TEST AL, 80h ; 测试AL寄存器的最高位(第7位)
JZ Target ; 如果最高位是0,则跳转到Target
原理解析:
-
80h的二进制是1000 0000,只有最高位是1。 -
TEST之后,只有AL的最高位是1时,结果才不为零,ZF才会被置0。 -
反之,如果最高位是0,结果为0,
ZF被置1。
TEST本身无法直接 通过单个标志位判断"是否所有被测试位都为1",因为结果非零时ZF都是0。解决思路有二:
多次检测(最稳健):依次测试每一位。
TEST AL, 16 ; 测试第4位 (16 = 00010000b)
JZ not_both ; 如果为0,失败
TEST AL, 1 ; 测试第0位 (1 = 00000001b)
JZ not_both ; 如果为0,失败
; 能执行到这里,说明两位都为1
both_set:
; ... 你的代码 ...
not_both:
; ... 其他代码 ...
对比法 :修改数据后配合CMP。
AND AL, 17 ; 保留第0、4位,其余位清零
CMP AL, 17 ; 对比是否保留的两位都是1
JE both_set ; 如果等于17,说明两位都为1
常见误区
-
TEST不保存结果 :它只改标志位,AX或AL等操作数的值不会改变 。如果想改变,要用AND指令。 -
JE和JZ是等价的 :它们都检查ZF标志,机器码完全相同,只是别名,方便在不同语义下阅读。 -
避免错误的"全为1"判断 :记住
JNZ跳转时,只代表"至少有一位是1",不保证所有测试位都是1。
速查表
| 你的需求 | 指令组合 | 说明 |
|---|---|---|
| 测试某一位是否为1 | TEST 后跟 JNZ |
若该位为1,结果非零,ZF=0,跳转 |
| 测试某一位是否为0 | TEST 后跟 JZ |
若该位为0,结果为零,ZF=1,跳转 |
| 测试是否任意位为1 | TEST 后跟 JNZ |
只要有一个掩码位是1就跳转 |
| 测试是否所有位为0 | TEST 后跟 JZ |
只有所有掩码位都是0才跳转 |
| 测试是否所有位为1 | TEST + 多个JZ 或 AND + CMP + JE |
无法用单个TEST+JZ/JNZ完成 |
希望这份指南能帮你理清思路。关于位操作,你还想了解BT(位测试)或BSF(位向前扫描)这些指令的用法吗?
