这个问题在这里已经有了答案:9 年前关闭。
可能重复:x86 程序集 - 针对 eax 的“testl”eax?
我对汇编语言编程非常陌生,我目前正在尝试读取从二进制文件生成的汇编语言。我跑过
test %eax,%eax
或test %rdi, %rdi
等。我对它的作用感到非常困惑。 %eax, %eax
中的值不一样吗?它在测试什么?我在某处读到它正在执行 AND
操作.....但由于它们的值相同,它不会只返回 %eax
吗?
以下只是我发现这种用法的一个实例:
400e6e: 85 c0 test %eax,%eax
400e70: 74 05 je 400e77 <phase_1+0x23>
我认为如果要比较的两个值相等,je
会跳转......好吧,因为 %eax
本身很好,在什么情况下我们不会跳转?
我是一般编程的初学者,所以如果有人可以向我解释这一点,我将非常感激。谢谢!
TEST
还会更新除 ZF
之外的其他标志。请参阅指令集参考。
test
instruction do?
CMP
减去操作数并设置标志。即,如果差为零(操作数相等),则设置零标志。
当 AND 运算的结果为零时,TEST
设置零标志 ZF
。如果两个操作数相等,则当两者都为零时,它们的按位与为零。当在结果中设置最高有效位时,TEST
还设置符号标志 SF
,当设置的位数为偶数时,还设置奇偶校验标志 PF
。
JE
[Jump if Equals] 测试零标志,如果设置了标志则跳转。 JE
是 JZ
[Jump if Zero] 的别名,因此反汇编程序无法根据操作码选择一个。 JE
之所以如此命名,是因为如果 CMP
的参数相等,则设置零标志。
所以,
TEST %eax, %eax
JE 400e77 <phase_1+0x23>
如果 %eax
为零,则跳转。
一些 x86 指令旨在保持操作数(寄存器)的内容不变,而只是设置/取消设置特定的内部 CPU 标志,如零标志 (ZF)。您可以将 ZF 视为驻留在 CPU 内部的真/假布尔标志。在这种特殊情况下,TEST 指令执行按位逻辑与,丢弃实际结果并根据逻辑结果设置/取消设置 ZF,如果结果为零,则设置 ZF = 1,否则设置 ZF = 0。像 JE 这样的条件跳转指令旨在查看 ZF 的跳转/不跳转,因此同时使用 TEST 和 JE 相当于根据特定寄存器的值执行条件跳转:示例:
TEST EAX,EAX
JE some_address
当且仅当 ZF = 1 时,CPU 才会跳转到“some_address”,换句话说,当且仅当 AND(EAX,EAX) = 0 时,当且仅当 EAX == 0 时,它才会发生,等效的 C 代码是:
if(eax == 0)
{
goto some_address
}
这将检查 EAX
是否为零。指令 test
在参数之间按位执行 AND
,如果 EAX
包含零,则结果设置 ZF 或 ZeroFlag。
test
是非破坏性的 and
,它不返回操作结果,但会相应地设置标志寄存器。要了解它真正测试的内容,您需要查看以下说明。 out 通常用于检查寄存器是否为 0,可能与 jz
条件跳转结合使用。
你是对的,那 test
“和”是两个操作数。但是结果被丢弃了,唯一留下来的,也是最重要的部分,就是旗帜。它们已设置,这就是使用(并存在)test
指令的原因。
JE
在相等时不跳转(它在之前的指令是比较时具有含义),它真正的作用是在设置 ZF
标志时跳转。由于它是test
设置的标志之一,这个指令序列(test x,x; je...)具有当x为0时跳转的含义。
对于这样的问题(以及更多细节),我可以推荐一本关于 x86 指令的书,例如,即使它真的很大,英特尔文档也非常好和精确。
不定期副业成功案例分享
%eax
为零,则跳转,这就是我想要的。