【问题标题】:The point of test %eax %eax [duplicate]测试点 %eax %eax [重复]
【发布时间】:2012-10-15 09:55:34
【问题描述】:

可能重复:
x86 Assembly - ‘testl’ eax against 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 之外的其他标志。请参阅指令集参考。
  • @Jester 已修复(在我的回答中),抱歉。
  • 另一个可能的重复:What does the test instruction do?

标签: assembly x86 att


【解决方案1】:

一些 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
}

【讨论】:

    【解决方案2】:

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

    TEST 在 AND 运算的结果为零时设置零标志 ZF。如果两个操作数相等,则当两者都为零时,它们的按位与为零。 TEST 还设置符号标志SF,当在结果中设置最高有效位时,以及奇偶校验标志,PF,当设置的位数为偶数时。

    JE [Jump if Equals] 测试零标志,如果标志被设置则跳转。 JEJZ [Jump if Zero] 的别名,因此反汇编程序无法根据操作码选择一个。 JE 之所以这样命名,是因为如果 CMP 的参数相等,则会设置零标志。

    所以,

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

    如果%eax 为零则跳转。

    【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

      JE 相等时不跳转(它在前面的指令是比较时具有含义),它真正的作用是在设置ZF 标志时跳转。而且由于它是test设置的标志之一,所以这个指令序列(test x,x;je...)的意思是当x为0时跳转。

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

      【讨论】:

        【解决方案5】:

        这会检查EAX 是否为零。指令test 在参数之间按位执行AND,如果EAX 包含零,则结果设置ZF 或ZeroFlag。

        【讨论】:

        • 这是执行此操作的标准方法。也可以为“初学者清晰”执行 cmp %eax, 0 (立即),但这会编码为更长的指令(也就是效率较低)。
        猜你喜欢
        • 2010-09-13
        • 2022-01-15
        • 2023-03-25
        • 2011-02-11
        • 2013-01-31
        • 2017-01-26
        • 2013-09-10
        • 1970-01-01
        相关资源
        最近更新 更多