我一直在撞墙撞墙,这对我来说毫无意义......
我认为您可以使用test
来比较两个值的相等性,如here所示......为什么不起作用?
int main()
{
__asm
{
mov EAX, 1;
mov EDX, EAX;
test EAX, EDX;
L: jne L;
}
}
答案 0 :(得分:7)
您对TEST
指令执行操作的期望不正确。
该指令用于执行位测试。您通常会使用它来“测试”是否在给定掩码的情况下设置某些位。它将与JZ
(如果为零则跳转)或JNZ
(如果不为零则跳转)指令一起使用。
测试涉及对两个操作数执行按位AND,并设置适当的标志(丢弃结果)。如果掩码中没有相应的位被置位,那么ZF(零标志)将是1
(所有位都为零)。如果您想测试是否已设置,则使用JNZ
指令。如果您想测试是否未设置,则使用JZ
指令。
JE
和JNE
不适合此指令,因为它们会以不同方式解释标记。
您正尝试对某些变量执行相等检查。您应该使用CMP
指令。您通常会使用它来相互比较值。
比较有效地减去操作数并仅设置标志(丢弃结果)。当相等时,两个值的差值为0
(ZF = 1)。当不相等时,两个值的差值为非零(ZF = 0)。如果你想测试它们是否相等,你可以使用JE
(如果相等则跳转)指令。如果你想测试它们是否不相等,你可以使用JNE
(如果不相等则跳转)指令。
在这种情况下,由于您使用了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
}
}
答案 1 :(得分:3)
JNE跳转到ZF(零标志)= 0
TEST设置ZF = 0 如果按位EAX AND EDX导致1 ,如果按位AND则导致0
如果AND的结果为0,则ZF设置为1,否则设置为 0
因此它跳转为1和1在ZF中导致0。
似乎逻辑但反直觉。
我认为@ A.Webb是对的 - 如果您使用TEST指令,它可能应该是JNZ,因为您依靠bitwuse操作的行为来设置零标志,而SUB指令将设置Zero标志如你所知。
答案 2 :(得分:1)
这很简单。您显然需要知道指令的作用,读取的处理器状态以及写入。如有疑问,请参阅参考手册。英特尔x86手册很容易在网上找到。
您的具体计划:
mov EAX, 1;
将常量1移动到EAX。没有其他状态发生变化。
mov EDX, EAX;
将EAX的上下文复制到EDX中,因此它也包含值1。
test EAX, EDX;
test计算两个寄存器的按位AND(你检查参考手册吗?),抛出答案,并根据答案设置条件代码位。在您的情况下,每个寄存器的高31位为零,并生成零。最低有效位是两个寄存器中的一个;并且产生1.净效果是生成32二进制值“1”,并在设置条件代码位后丢弃。我们关心这个程序有一个条件代码位,那就是“Z”(ero)位,如果最后一个条件代码设置操作产生一个完整的零值,则设置该位。该测试产生“1”,因此Z位被复位。我会让你查看其他条件代码位。
L: jne L;
这是“Jmp on Not Equal”,例如,如果Z位复位则jmps。对于您的程序,Z被重置,jmp发生。执行后,处理器处于相同的状态,并看到另一个(相同的jmp)。条件代码位不会被jmp指令改变。
所以......它进入了一个无限循环。
汇编程序支持的各种操作码有很多同义词。例如,“JZ”和“JE”是同一指令的同义词。不要让同义词混淆。