TEST指令和ZF标志
为什么零标志必须与零不同?
这是一个有点混乱,但零标志为一组(即其值为1),如果最后的结果IS为零:
- 结果是
0⇒ ZF不是0 - 结果不是
0⇒ ZF是0
通常,设置一个标志来表明适当的条件为真,或者适当的事件发生了。(我们也说标志是开( 1) 或关( 0))。
。顺便说一句,这可能是也有点反直觉:JNZ(Ĵ UMP如果Ñ OT Ž ERO)跳转如果ZF 是零(因为这意味着“不为零,在过去结果”,而不是“不为零的零标志”)。
最好只考虑结果,而忽略零标志- 标志主要是机器的技术工具,而不是我们人类的。
如果 2 值 (0=0) 相等,则 Z 标志设置为 1,因为比较的结果为真!这是正确的吗?
不完全的:
在
CMP比较的情况下,零的意思是“他们的差为零”,所以他们是一样的,但是在 的情况下
TEST AL,AL,零表示“AND AL,AL为零”,即AL本身为零:TEST AL,AL当且仅当 AL 本身的值也为零时,该指令的结果为零。解释,为什么:
如果值
AL是零(其所有位都为0):0 0 0 0 0 0 0 0 ← AL AND 0 0 0 0 0 0 0 0 ← AL -------------------- 0 0 0 0 0 0 0 0 ← zero (ZF is set to 1)的值
AL是不为零(即其比特中的至少一个是1):0 0 1 0 0 0 0 0 ← AL AND 0 0 1 0 0 0 0 0 ← AL -------------------- 0 0 1 0 0 0 0 0 ← nonzero (ZF is reset to 0)为什么(按位)
AND,而不是TEST?因为
TEST指令做同样的AND那样-的唯一的区别是逐位的结果AND操作对于TEST指令丢弃,所以只有零标志(ZF)被设定或复位。
您似乎认为 ZF 通常意味着操作数相等。这是错误的。显示操作数是否相等不是 ZF 的属性。相反,CMP如果操作数相等,则它设置零标志的属性。此代码片段不执行CMP。
相反,此代码片段执行TEST,其工作方式不同。在第一个和第二个操作数中都没有设置位的情况下,它完全表示 ZF。因此,如果 AL 非零,TEST AL,AL则会发现在第一个和第二个操作数中都设置了某些位(所有在 AL 中设置的位),并清除 ZF。另一方面,如果 AL 为零,则 AL 中没有位被设置,因此在第一个或第二个操作数中都没有设置位,ZF 将被设置。
可以使用TEST,AND或以相同的效果执行零测试OR,其中两个操作数是相同的寄存器。您将在实际代码中找到所有三个变体来测试寄存器是否为零。
让我们以相反的顺序进入重要说明。
JNZ ...如果不是零则跳转。你想跳过(跳过“坏男孩”),即你想在这个(上一个)指令中获得“非零”:
TEST AL,AL要获得“非零”,AL 中的值也必须是“非零”。
AL 的值在此(上一条)指令中设置:CALL ...该指令调用一个函数,该函数用其返回值填充 EAX 寄存器(与调用约定一致)。AL 寄存器是 EAX 的一部分:
所以你想从这个函数返回一些“非零”,但它顽固地返回 0(意思是“未注册”)。
你有一些自然的可能性来达到你想要的行为(跳过“坏男孩”),但首先我提醒原始指令的顺序:
CALL ...
TEST AL,AL
JNZ ...
JNZ ...用JMP ...或替换指令JZ ...。- 将
TEST AL,AL指令替换为这样的指令,该指令可为您提供“非零”结果。 - 将
CALL ...指令替换为用“非零”填充 AL 寄存器的指令。 - 深入了解
CALL ...指令中的函数并将其更改为返回“非零”值。

