可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am trying to understand some assembly.
The assembly as follows, I am interested in the testl
line:
000319df 8b4508 movl 0x08(%ebp), %eax
000319e2 8b4004 movl 0x04(%eax), %eax
000319e5 85c0 testl %eax, %eax
000319e7 7407 je 0x000319f0
I am trying to understand that point of testl
between %eax
and %eax
? I think the specifics of what this code isn\'t important, I am just trying to understand the test with itself - wouldn\'t the value always be true?
回答1:
It tests whether eax
is 0, or above, or below. In this case, the jump is taken if eax
is 0.
回答2:
The meaning of test
is to AND the arguments together, and check the result for zero. So this code tests if EAX is zero or not. je
will jump if zero.
BTW, this generates a smaller instruction than cmp eax, 0
which is the reason that compilers will generally do it this way.
回答3:
The test instruction does a logical AND-operation between the operands but does not write the result back into a register. Only the flags are updated.
In your example the test eax, eax will set the zero flag if eax is zero, the sign-flag if the highest bit set and some other flags as well.
The Jump if Equal (je) instruction jumps if the zero flag is set.
You can translate the code to a more readable code like this:
cmp eax, 0
je somewhere
That has the same functionality but requires some bytes more code-space. That\'s the reason why the compiler emitted a test instead of a compare.
回答4:
test
is like and
, except it only writes FLAGS, leaving both its inputs unmodified. With two different inputs, it\'s useful for testing if some bits are all zero, or if at least one is set. (e.g. test al, 3
sets ZF if EAX is a multiple of 4 (and thus has both of its low 2 bits zeroed).
test eax,eax
sets all flags exactly the same way that cmp eax, 0
would:
- CF and OF cleared (AND/TEST always does that; and subtracting zero never produces a carry)
- ZF, SF and PF according to the value in EAX. (
a = a&a = a-0
)
(Except for the obsolete AF (auxiliary-carry flag, used by ASCII/BCD instructions). TEST leaves it undefined, but CMP sets it \"according to the result\". Since subtracting zero can\'t produce a carry from the 4th to 5th bit, CMP should always clear AF).
TEST is smaller (no immediate) and sometimes faster (can macro-fuse into a compare-and-branch uop on more CPUs in more cases than CMP). That makes test
the preferred idiom for testing a register for zero or not.
The only common reason for using CMP with an immediate 0 is when you want to compare against a memory operand (for example, cmpb $0, (%esi)
to check for a terminating zero byte at the end of an implicit-length C-style string).
AVX512F adds kortestw k1, k2
and AVX512DQ/BW (Skylake but not KNL) add ktestb/w/d/q k1, k2
, which operate on AVX512 mask registers (k0..k7) but still set regular FLAGS like test
does, the same way that integer OR
or AND
instructions do.
kortestw k1,k1
is the idiomatic way to branch / cmovcc / setcc based on an AVX512 compare result, replacing SSE/AVX2 (v)pmovmskb/ps/pd
+ test
or cmp
.
Use of jz
vs. je
can be confusing.
jz
and je
are literally the same instruction, i.e. the same opcode in the machine code. They do the same thing, but have different semantic meaning for humans. Disassemblers (and typically asm output from compilers) will only ever use one, so the semantic distinction is lost.
cmp
and sub
set ZF when their two inputs are equal (i.e. the subtraction result is 0). je
(jump if equal) is the semantically relevant synonym.
test %eax,%eax
/ and %eax,%eax
again sets ZF when the result is zero, but there\'s no \"equality\" test. ZF after test doesn\'t tell you whether the two operands were equal. So jz
(jump if zero) is the semantically relevant synonym.
回答5:
This snippet of code is from a subroutine that was given a pointer to something, probably some struct or object. The 2nd line dereferences that pointer, fetching a value from that thing - possibly itself a pointer or maybe just an int, stored as its 2nd member (offset +4). The 3rd and 4th lines test this value for zero (NULL if it\'s a pointer) and skip the following few operations (not shown) if it is zero.
The test for zero sometimes is coded as a compare to an immediate literal zero value, but the compiler (or human?) who wrote this might have thought a testl op would run faster - taking into consideration all the modern CPU stuff like pipelining and register renaming. It\'s from the same bag of tricks that holds the idea of clearing a register with XOR EAX,EAX (which i saw on someone\'s license plate in Colorado!) rather than the obvious but maybe slower MOV EAX, #0 (i use an older notation).
In asm, like perl, TMTOWTDI.
回答6:
If eax is zero it will perform the conditional jump, otherwise it will continue execution at 319e9
回答7:
In some programs they can be used to check for a buffer overflow.
At the very top of the allocated space a 0 is placed. After inputting data into the stack, it looks for the 0 at the very beginning of the allocated space to make sure the allocated space is not overflowed.
It was used in the stack0 exercise of exploits-exercises to check if it was overflowed and if there wasnt and there was a zero there, it would display \"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
回答8:
we could see the jg,jle
If testl %edx,%edx. jle .L3
we could easy find jleis suit (SF^OF)|ZF
,if %edx is zero ,ZF=1,but if %edx is not zero and is -1,after the testl ,the OF=0,and the SF =1,so the flag =true,that implement jump
.sorry ,my English is poor