我对汇编语言编程非常陌生,我目前正在尝试阅读从二进制文件生成的汇编语言。我遇到了
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
本身很好,在什么情况下我们不跳?
我是编程的初学者,所以如果有人能向我解释这一点,我会非常感激。谢谢!
答案 0 :(得分:128)
CMP
减去操作数并设置标志。也就是说,如果差值为零(操作数相等),它会设置零标志。
TEST
设置零标志ZF
。如果两个操作数相等,则当它们都为零时,它们的按位AND为零。当结果中设置了最高有效位时,TEST
还设置符号标志SF
,当设置位数为偶数时,设置奇偶校验标志PF
。
JE
[等于跳转]测试零标志,如果设置了标志则跳转。 JE
是JZ
[跳转为零]的别名,因此反汇编程序无法根据操作码选择一个。 JE
的名称是这样的,因为如果CMP
的参数相等,则设置零标志。
所以,
TEST %eax, %eax
JE 400e77 <phase_1+0x23>
如果%eax
为零,则跳转。
答案 1 :(得分:45)
某些x86指令旨在保留操作数(寄存器)的内容,只是设置/取消设置特定的内部CPU标志,如零标志(ZF)。您可以将ZF视为驻留在CPU内部的真/假布尔标志。
在这种特殊情况下,TEST指令执行按位逻辑AND,丢弃实际结果并根据逻辑结果设置/取消设置ZF,如果结果为零,则设置ZF = 1,否则设置ZF = 0。
像JE这样的条件跳转指令用于查看ZF的跳转/不跳跃,因此使用TEST和JE相当于根据特定寄存器的值执行条件跳转:
例:
测试EAX,EAX
JE some_address
当且仅当ZF = 1时,CPU将跳转到“some_address”,换句话说,当且仅当AND(EAX,EAX)= 0时,当且仅当EAX == 0时才会发生这种情况
等效的C代码是:
if(eax == 0)
{
goto some_address
}
答案 2 :(得分:11)
检查EAX
是否为零。指令test
在参数之间按位AND
,如果EAX
包含零,则结果设置ZF或ZeroFlag。
答案 3 :(得分:3)
你是对的,test
“和两个操作数。但结果被抛弃了,唯一保留的东西,也就是重要的部分,就是旗帜。它们已设置,这就是使用test
指令(并且存在)的原因。
JE
在相等时不跳转(它具有前面指令作为比较时的含义),它实际上是什么,它在设置ZF
标志时跳转。由于它是由test
设置的标志之一,因此该指令序列(test x,x; je ...)具有在x为0时跳转的含义。
对于这样的问题(以及更多细节),我可以推荐一本关于x86指令的书,例如:即使它非常大,英特尔文档也非常精确。
答案 4 :(得分:3)
test
是非破坏性的and
,它不返回操作的结果,但它相应地设置了标志寄存器。要知道它真正测试的是什么,需要检查以下说明。通常out用于检查寄存器0,可能与jz
条件跳转相结合。