可能的重复: x86汇编- ' testl ' eax对eax?

我对汇编语言编程非常非常陌生,我目前正在尝试阅读由二进制文件生成的汇编语言。我遇到过

 test   %eax,%eax

或者测试%rdi, %rdi,等等。我很困惑这是做什么的。难道%eax, %eax中的值不一样吗?它在测试什么?我在某处读到,它正在做AND操作.....但因为它们是相同的值,它不只是返回%eax吗?

以下是我发现这种用法的一个例子:

   400e6e:       85 c0                   test   %eax,%eax
   400e70:       74 05                   je     400e77 <phase_1+0x23>

我认为je跳,如果两个值进行比较是相等的......因为%eax本身,在什么情况下我们不会跳?

一般来说,我是一个编程初学者,所以如果有人能给我解释一下,我会非常感激。谢谢!


当前回答

CMP减去操作数并设置标志。也就是说,如果差值为零(操作数相等),则设置零标志。

当AND操作的结果为零时,TEST设置零标志ZF。如果两个操作数相等,当它们都为零时,它们的位与为零。TEST还设置符号标志SF(当结果中设置最高有效位时)和奇偶标志PF(当设置位的数量为偶数时)。

JE[等于则跳]测试零标志,如果设置了标志则跳。JE是JZ [Jump if Zero]的别名,因此反汇编程序不能基于操作码选择一个。JE之所以如此命名,是因为如果CMP的参数相等,则设置零标志。

So,

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

如果%eax为零则跳跃。

其他回答

CMP减去操作数并设置标志。也就是说,如果差值为零(操作数相等),则设置零标志。

当AND操作的结果为零时,TEST设置零标志ZF。如果两个操作数相等,当它们都为零时,它们的位与为零。TEST还设置符号标志SF(当结果中设置最高有效位时)和奇偶标志PF(当设置位的数量为偶数时)。

JE[等于则跳]测试零标志,如果设置了标志则跳。JE是JZ [Jump if Zero]的别名,因此反汇编程序不能基于操作码选择一个。JE之所以如此命名,是因为如果CMP的参数相等,则设置零标志。

So,

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

如果%eax为零则跳跃。

你是对的,测试and是两个操作数。但是结果被丢弃了,唯一留下来的,也是最重要的部分,是标志。它们被设置了,这就是为什么测试指令被使用(并且存在)的原因。

JE在相等时不跳(当之前的指令是比较时它有意义),它真正做的是,当设置ZF标志时它跳。由于它是test设置的标志之一,这个指令序列(test x,x;Je…)的意思是当x为0时,它会被跳转。

对于这样的问题(以及更多细节),我可以推荐一本关于x86指令的书,例如,即使它真的很大,英特尔的文档也非常好和精确。

Test是非破坏性的,它不返回操作的结果,但它相应地设置标志寄存器。要了解它真正测试的是什么,您需要检查以下说明。out通常用于检查寄存器是否为0,可能与jz条件跳转相结合。

这将检查EAX是否为零。指令测试在参数之间按位进行AND运算,如果EAX包含零,则结果设置ZF或ZeroFlag。

Some x86 instructions are designed to leave the content of the operands (registers) as they are and just set/unset specific internal CPU flags like the zero-flag (ZF). You can think at the ZF as a true/false boolean flag that resides inside the CPU. in this particular case, TEST instruction performs a bitwise logical AND, discards the actual result and sets/unsets the ZF according to the result of the logical and: if the result is zero it sets ZF = 1, otherwise it sets ZF = 0. Conditional jump instructions like JE are designed to look at the ZF for jumping/notjumping so using TEST and JE together is equivalent to perform a conditional jump based on the value of a specific register: example:

TEST EAX,EAX
JE some_address

当且仅当ZF = 1时,CPU将跳转到“some_address”,换句话说,当且仅当and (EAX,EAX) = 0,当且仅当EAX == 0时,它才会发生 等价的C代码是:

if(eax == 0)
{
    goto some_address
}