`testl` eax对抗eax?

时间:2008-09-29 01:22:57

标签: assembly x86 instructions

我想了解一些装配。

汇编如下,我对testl行感兴趣:

000319df  8b4508        movl   0x08(%ebp), %eax  
000319e2  8b4004        movl   0x04(%eax), %eax  
000319e5  85c0          testl  %eax, %eax  
000319e7  7407          je     0x000319f0  

我想了解testl%eax之间的%eax点?我认为这段代码的具体内容并不重要,我只是试图用自己来理解测试 - 这个值总是不正确吗?

8 个答案:

答案 0 :(得分:86)

test的含义是将参数组合在一起,并将结果检查为零。因此,此代码测试EAX是否为零。如果为零,je将跳转。

顺便说一下,这会生成比cmp eax, 0更小的指令,这就是编译器通常会这样做的原因。

答案 1 :(得分:84)

它测试eax是0,或更高,或更低。在这种情况下,如果eax为0,则进行跳转。

答案 2 :(得分:32)

测试指令在操作数之间执行逻辑AND操作,但不将结果写回寄存器。只更新标志。

在你的例子中,测试eax,如果eax为零,eax将设置零标志,如果最高位设置则设置符号标志,以及其他一些标志。

如果设置了零标志,则跳转如果等于(je)指令跳转。

您可以将代码翻译成更易读的代码,如下所示:

cmp eax, 0
je  somewhere

它具有相同的功能,但需要一些字节更多的代码空间。这就是编译器发出测试而不是比较的原因。

答案 3 :(得分:19)

testand类似,只是它只会写入FLAGS,而且两个输入都不会被修改。使用两个不同的输入,它可用于测试某些位是否全为零,或者是否设置了至少一个位。 (例如,test al, 3设置ZF,如果EAX是4的倍数(因此它的两个低位都被置零)。

test eax,eax设置所有标记的方式与cmp eax, 0 完全相同:

  • CF和OF清除(AND / TEST总是这样做;减去零从不产生进位)
  • ZF,SF和PF根据EAX中的值。 (a = a&a = a-0

(除了过时的AF(辅助进位标志,由ASCII / BCD指令使用)。TEST leaves it undefined,但CMP sets it "according to the result"。由于减零不能产生从第4到第5的进位位,CMP应始终清除AF)。

TEST更小(没有立即),有时更快(在比CMP更多的情况下,可以在更多CPU上宏 - 融合到比较和分支uop)。 That makes test the preferred idiom for testing a register for zero or not

使用具有立即数0的CMP的唯一常见原因是当您想要与内存操作数进行比较时(例如,cmpb $0, (%esi)以检查隐式长度C-末尾的终止零字节样式字符串)。

AVX512F添加kortestw k1, k2 和AVX512DQ / BW(Skylake但不是KNL)添加ktestb/w/d/q k1, k2,它们在AVX512掩码寄存器(k0..k7)上运行,但仍设置为常规像test这样的标记就像整数ORAND指令一样。

kortestw k1,k1是基于AVX512比较结果分支/ cmovcc / setcc的惯用方法,取代了SSE / AVX2 (v)pmovmskb/ps/pd + testcmp

jzje的使用可能令人困惑。

jz and je are literally the same instruction,即机器代码中的相同操作码。 他们做同样的事情,但对人类有不同的语义含义。反汇编程序(通常是编译器的asm输出)只能使用一个,因此语义上的区别就会丢失。

cmpsub在两个输入相等时设置ZF(即减法结果为0)。 je(如果相等则跳转)是语义相关的同义词。

当结果为零时,

test %eax,%eax / and %eax,%eax再次设置ZF,但是没有“相等”测试。测试后的ZF没有告诉你两个操作数是否相等。所以jz(如果为零则跳转)是语义相关的同义词。

答案 4 :(得分:5)

这段代码来自一个子程序,它被赋予一个指向某事物的指针,可能是一些结构或对象。第二行取消引用指针,从该东西获取一个值 - 可能本身就是一个指针,或者只是一个int,存储为第二个成员(偏移+4)。第3行和第4行将此值测试为零(如果它是指针,则为NULL),如果为零,则跳过以下几个操作(未显示)。

对零的测试有时被编码为与直接的文字零值进行比较,但编写此文件的编译器(或人?)可能认为测试操作会运行得更快 - 考虑所有现代CPU的东西,如流水线和注册重命名。它来自同一个技巧包含清除XOR EAX,EAX(我在科罗拉多州某人的车牌上看到的)登记册的想法,而不是明显但可能更慢的MOV EAX,#0(我使用较旧的表示法) )。

在asm中,像perl,TMTOWTDI。

答案 5 :(得分:3)

如果eax为零,它将执行条件跳转,否则它将继续执行319e9

答案 6 :(得分:0)

在某些程序中,它们可用于检查缓冲区溢出。 在分配空间的最顶部放置0。在将数据输入堆栈后,它会在分配的空间的最开头查找0,以确保分配的空间不会溢出。

它在stack0练习中用于检查它是否溢出,如果没有并且那里有零,它会显示"再试一次"

0x080483f4 <main+0>:    push   ebp
0x080483f5 <main+1>:    mov    ebp,esp
0x080483f7 <main+3>:    and    esp,0xfffffff0
0x080483fa <main+6>:    sub    esp,0x60                     
0x080483fd <main+9>:    mov    DWORD PTR [esp+0x5c],0x0 ;puts a zero on stack
0x08048405 <main+17>:   lea    eax,[esp+0x1c]
0x08048409 <main+21>:   mov    DWORD PTR [esp],eax
0x0804840c <main+24>:   call   0x804830c <gets@plt>
0x08048411 <main+29>:   mov    eax,DWORD PTR [esp+0x5c] 
0x08048415 <main+33>:   test   eax,eax                  ; checks if its zero
0x08048417 <main+35>:   je     0x8048427 <main+51>
0x08048419 <main+37>:   mov    DWORD PTR [esp],0x8048500 
0x08048420 <main+44>:   call   0x804832c <puts@plt>
0x08048425 <main+49>:   jmp    0x8048433 <main+63>
0x08048427 <main+51>:   mov    DWORD PTR [esp],0x8048529
0x0804842e <main+58>:   call   0x804832c <puts@plt>
0x08048433 <main+63>:   leave
0x08048434 <main+64>:   ret

答案 7 :(得分:-2)

我们可以看到 jg jle 如果<Grid> <customButton:Button DefaultColor="set your default color" NewColor="Set your onClick color".../> 我们很容易找到 jle testl %edx,%edx. jle .L3,如果%edx为零,则ZF = 1,但如果%edx不为零且为-1,则在testl,OF = 0,SF = 1,所以flag = true,实现跳转 .sorry,我的英语很差