我想了解一些装配。
汇编如下,我对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
点?我认为这段代码的具体内容并不重要,我只是试图用自己来理解测试 - 这个值总是不正确吗?
答案 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)
test
与and
类似,只是它只会写入FLAGS,而且两个输入都不会被修改。使用两个不同的输入,它可用于测试某些位是否全为零,或者是否设置了至少一个位。 (例如,test al, 3
设置ZF,如果EAX是4的倍数(因此它的两个低位都被置零)。
test eax,eax
设置所有标记的方式与cmp eax, 0
完全相同:
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
这样的标记就像整数OR
或AND
指令一样。
kortestw k1,k1
是基于AVX512比较结果分支/ cmovcc / setcc的惯用方法,取代了SSE / AVX2 (v)pmovmskb/ps/pd
+ test
或cmp
。
jz
与je
的使用可能令人困惑。
jz
and je
are literally the same instruction,即机器代码中的相同操作码。 他们做同样的事情,但对人类有不同的语义含义。反汇编程序(通常是编译器的asm输出)只能使用一个,因此语义上的区别就会丢失。
cmp
和sub
在两个输入相等时设置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,我的英语很差