测试指令 %eax %eax 的作用是什么?

215

可能是重复问题:
x86汇编 - 使用'testl'检查eax是否等于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值本身就相等,那么在什么情况下我们才不会进行跳转呢?

作为一个编程新手,我非常希望有人能够解释一下。谢谢!


6
因为一些回答似乎对此不太清楚,所以让我指出TEST指令除了更新ZF标志位外,还会更新其他标志位。请参考指令集手册。 - Jester
@Jester 已经修正了(在我的回答中),抱歉。 - John Dvorak
另一个可能的重复问题:test指令是做什么用的? - jww
5个回答

245

CMP做减法并设置标志位。如果差为零(即操作数相等),它将设置零标志位。

TEST进行AND运算并设置零标志位ZF,当结果为零时。如果两个操作数相等,则当它们都为零时,它们的按位AND是零。 TEST还在结果中最高位设置时设置符号标志位SF,并在设置位数为偶数时设置奇偶标志位PF

JE [Jump if Equals]测试零标志位,并在标志位被设置时跳转。由于JEJZ [Jump if Zero]的别名,因此反汇编程序无法根据操作码选择其中一个。 JE的命名是因为如果CMP的参数相等,则设置零标志位。

因此,

TEST %eax, %eax
JE   400e77 <phase_1+0x23>

如果%eax为零,则跳转。


8
我可以在哪里找到类似这样的信息? - Thorsten Staerk
17
即?X86指令列表可在维基百科上找到,该页面还链接了英特尔公司的规格说明书以及网络存档机器上(非常易读的)另一份参考资料。维基教程也提供有关X86汇编的教程。 - John Dvorak
是的,这就是我在寻找的信息。 - Thorsten Staerk
6
如果 %eax 寄存器的值为零,就会跳转,这正是我想要的。 - dud3
1
https://en.wikibooks.org/wiki/X86_Assembly/Control_Flow - Peter Chaula
如果两个操作数相等,则当它们都为零时,它们的按位与为零。因此,当两个数字都为0时,AND运算才是有用的,在1:100000的情况下,这是非常无用的。或者说我漏掉了什么? - metablaster

65

一些x86指令旨在保留操作数(寄存器)的内容,只设置/取消特定的内部CPU标志,如零标志(ZF)。您可以将ZF视为驻留在CPU内部的真/假布尔标志。

在这种特定情况下,TEST指令执行按位逻辑AND,丢弃实际结果,并根据逻辑与的结果设置/取消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
}

18

这段代码检查EAX是否为零。指令test对参数进行按位AND操作,如果EAX包含零,则结果设置ZF标志位。


3
这是标准的做法。为了“对初学者更加清晰”,也可以执行cmp %eax, 0(立即数),但这会编码成一条更长的指令(意味着效率更低)。 - Aki Suihkonen

5

test是一种非破坏性的and,它不返回操作结果,但会相应地设置标志寄存器。要了解它真正测试的内容,您需要检查以下指令。通常使用此命令来检查寄存器是否为0,可能与jz条件跳转配合使用。


4
您说得对,test操作符会对两个操作数进行“and”运算。但是结果会被丢弃,唯一留下的重要部分是标志位。这些标志位被设置,这也是使用test指令(以及存在的原因)。 JE不是在相等时跳转(它的意思是在前一条指令是比较指令时),它真正的作用是在ZF标志位被设置时跳转。由于它是由test设置的标志之一,所以这个指令序列(test x,x; je...)的意思是当x为0时跳转。
对于这样的问题(以及更多细节),我建议阅读一本关于x86指令的书籍,例如即使它真的很大,英特尔文档非常好而且精确。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接