`testl` eax反对eax?
我想了解一些程序集。
大会如下,我对testl
行感兴趣:
000319df 8b4508 movl 0x08(%ebp), %eax 000319e2 8b4004 movl 0x04(%eax), %eax 000319e5 85c0 testl %eax, %eax 000319e7 7407 je 0x000319f0
我想了解%eax
和%eax
之间的testl
点吗? 我认为这个代码的重要性并不重要,我只是试图用自己来理解testing – 这个价值永远不会是真的吗?
它testingeax
是否为0或更高或更低。 在这种情况下,如果eax
为0,则跳转。
test
的意义是将参数与参数一起,并检查结果为零。 所以这个代码testingEAX是否为零。 如果零, je
会跳。
顺便说一下,这会产生一个比cmp eax, 0
更小的指令cmp eax, 0
这就是编译器通常这样做的原因。
testing指令在操作数之间进行逻辑与操作,但不将结果写回寄存器。 只有标志被更新。
在你的例子中,testingeax,如果eax为零,eax将设置零标志,如果设置了最高位,则标志标志也会置位。
如果等于(je)指令跳转,如果零标志被设置。
您可以将代码翻译成更可读的代码,如下所示:
cmp eax, 0 je somewhere
这有相同的function,但需要一些字节更多的代码空间。 这就是为什么编译器发出testing而不是比较的原因。
test eax,eax
设置所有标志完全一样cmp eax, 0
会:
- CF和OF清零(AND / TEST总是这样做,而减零不会产生进位)
- ZF,SF和PF根据EAX中的值。 (
a = a&a = a-0
)
(除了过时AF(辅助进位标志,由ASCII / BCD指令使用)之外, TEST不定义 ,但CMP根据结果设置它 。由于减零不能产生从第4个到第5个进位CMP应该始终清除AF)。
TEST更小(不立即),有时更快(可以在比CMP更多的情况下在更多的CPU上将macros观融入到比较分支的uop中)。 这使得test
成为testing寄存器为零或不是零的首选成语 。
使用立即为0的CMP的唯一常见原因是当你想要比较一个内存操作数(例如, cmpb $0, (%esi)
来检查一个隐式长度的C风格末尾的终止零字节串)。
jz
与je
可能会jz
困惑。
jz
和je
字面上是相同的指令 ,即机器码中的相同操作码。 他们做同样的事情,但对人类有不同的语义 。 反汇编程序(通常是编译器的输出)只会使用一个,所以语义上的差别就会丢失。
当它们的两个input相等时(即,相减结果是0), cmp
和sub
集ZF。 je
(如果相等则跳转)是语义上相关的同义词。
test %eax,%eax
/ and %eax,%eax
在结果为零时再次设置ZF,但是没有“相等”testing。 ZF经过testing并没有告诉你这两个操作数是否相等。 所以jz
(跳转,如果是零)是语义相关的同义词。
这段代码来自一个被指定了某个东西的子程序,可能是一些结构或对象。 第二行取消引用这个指针,从它的第二个成员(偏移+4)中获取一个值 – 可能是一个指针或者可能只是一个int值。 第三行和第四行testing这个值为零(如果它是一个指针,则为NULL),如果它为零,则跳过下面的几个操作(未示出)。
有时零的testing被编码为立即文字零值的比较,但编译器(或人类)写这个可能会认为testl运行速度会更快 – 考虑到所有现代CPU的东西,如stream水线和注册重命名。 这是从同一个包装的技巧,拥有与XOR EAX,EAX(我在科罗拉多州的人的车牌上看到)清除registry的想法,而不是显而易见的,但也许更慢的MOV EAX,#0(我使用一个更旧的表示法)。
在asm中,像perl,TMTOWTDI。
如果eax为零,它将执行条件跳转,否则它将在319e9继续执行
在某些程序中,它们可以用来检查缓冲区溢出。 在分配空间的最顶端放置一个0。 将数据input到堆栈后,会在分配空间的最开始处查找0,以确保分配的空间不会溢出。
它被用在stack0的exploit-exercise练习中,以检查它是否溢出,如果没有,那里有一个零,它会显示“Try again”
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
我们可以看到jg , jle如果testl testl %edx,%edx. jle .L3
如果%edx为零,则ZF = 1,但是如果%edx不为零并且为-1,则在testl之后,OF = 0,并且SF = 1,所以flag = true,实现跳跃。不过,我的英文很差