我一直在努力解决这个问题,这对我来说毫无意义......
为什么这个程序会进入死循环?!
我想你可以用它来比较两个值是否相等,如此处test
所示......为什么它不起作用?
int main()
{
__asm
{
mov EAX, 1;
mov EDX, EAX;
test EAX, EDX;
L: jne L;
}
}
你对TEST
指令的期望是不正确的。
该指令用于执行位测试。如果某些位设置为给定掩码,您通常会使用它来“测试”。它将与JZ
(jump if zero) 或JNZ
(jump if not zero) 指令结合使用。
该测试涉及对两个操作数执行按位与并设置适当的标志(丢弃结果)。如果没有设置掩码中的相应位,则 ZF(零标志)将为1
(所有位为零)。如果您想测试是否设置了任何设置,您将使用该JNZ
指令。如果你想测试是否没有设置,你会使用JZ
指令。
JE
和JNE
不适用于该指令,因为它们对标志的解释不同。
您正在尝试对某些变量执行相等性检查。您应该使用该CMP
说明。您通常会使用它来相互比较值。
比较有效地减去操作数并仅设置标志(丢弃结果)。当相等时,两个值之差为0
(ZF = 1)。当不相等时,两个值的差值非零(ZF = 0)。如果您想测试它们是否相等,您将使用JE
(jump if equal) 指令。如果您想测试它们是否不相等,您将使用JNE
(jump if not equal) 指令。
在这种情况下,由于您使用TEST
了 ,因此生成的标志将产生ZF = 0
(0x1 & 0x1 = 0x1,非零)。由于ZF = 0
,该JNE
指令将采用您在此处看到的分支。
CMP
如果要检查是否相等,则需要使用指令比较值,而不是TEST
它们。
int main()
{
__asm
{
mov EAX, 1
mov EDX, EAX
cmp EAX, EDX
L: jne L ; no more infinite loop
}
}
这很简单。您显然需要知道指令的作用,它们读取和写入的处理器状态。如有疑问,请获取参考手册。Intel x86 手册很容易在网上找到。
您的具体程序:
mov EAX, 1;
将常数 1 移动到 EAX。不会发生其他状态更改。
mov EDX, EAX;
将 EAX 的上下文复制到 EDX 中,因此它也包含值 1。
test EAX, EDX;
test 计算两个寄存器的按位与(你检查过参考手册吗?),扔掉答案,并根据答案设置条件代码位。在您的情况下,每个寄存器的高 31 位为零,并且会产生零。两个寄存器中的最低有效位均为 1;and'd 产生一个 1。最终结果是生成了 32 个二进制值“一”,并在设置条件代码位后丢弃。我们关心这个程序的一个条件代码位,那就是“Z”(ero)位,如果最后一个条件代码设置操作产生一个全零值,则设置该位。该测试产生“一”,因此 Z 位被复位。我会让你查找其他条件代码位。
L: jne L;
这是一个“Jmp on Not Equal”,例如,如果 Z 位被复位,它会 jmps。对于您的程序,Z 被重置,jmp 发生。执行后,处理器处于相同的指令,并看到另一个(相同的 jmp)。jmp 指令不会更改条件代码位。
所以......它进入了一个无限循环。
汇编器支持的各种操作码有很多同义词。例如,“JZ”和“JE”是同一指令的同义词。不要让同义词混淆。