`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
和 之间的
testl
点%eax ? 我认为这段代码的细节并不重要,我只是想理解测试本身 - 该值不总是正确的吗?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
我们可以看到jg,jle
如果
testl %edx,%edx。 jle .L3
我们很容易发现jle适合(SF^OF)|ZF
,如果%edx为零,ZF=1,但如果%edx不为零,为-1,testl后,OF=0,SF=1,所以flag=true,实现跳转.抱歉,我的英语很差
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
test
就像and
,但它只写入 FLAGS,而其两个输入均未修改。 对于两个不同输入,它对于测试某些位是否全为零或是否至少设置了一个非常有用。 (例如,如果 EAX 是 4 的倍数,则test al, 3
设置 ZF(因此其低 2 位均为零)。test eax,eax
设置所有标志的方式与cmp eax, 0
会:a = a&a = a-0
)。(PF照常只是根据低8位设置)
已过时的 AF(辅助进位标志,由 ASCII/BCD 指令使用)除外。 TEST 未定义,但是CMP“根据结果”设置它。 由于减零不能产生第 4 到第 5 位的进位,因此 CMP 应始终清除 AF。
TEST 更小(不是立即执行),有时更快(与 CMP 相比,在更多情况下可以在更多 CPU 上宏融合到比较和分支微指令中)。 这使得
test< /code> 将寄存器与零进行比较的首选习惯用法
。 这是
cmp reg,0
的窥孔优化,无论语义如何,您都可以使用它。使用带有立即数 0 的 CMP 的唯一常见原因是当您想要与内存操作数进行比较时。 例如,
cmpb $0, (%esi)
用于检查隐式长度 C 样式字符串末尾是否有终止零字节。AVX512F 添加
kortestw k1, k2
< /strong> 和 AVX512DQ/BW(Skylake-X 但不是 KNL)添加ktestb/ w/d/q k1, k2
,它们在 AVX512 掩码寄存器 (k0..k7) 上运行,但仍然像test
一样设置常规标志,与整数相同OR
或AND
指令即可。 (有点像 SSE4ptest
或 SSEucommiss
:SIMD 域中的输入并产生整数 FLAGS。)kortestw k1,k1
是惯用的基于 AVX512 比较结果分支 / cmovcc / setcc 的方式,替换 SSE/AVX2(v)pmovmskb/ps/pd
+test
或cmp
。使用
jz
与je
可能会造成混淆。jz
和je
实际上是相同的指令,即机器代码中的相同操作码。 它们做同样的事情,但对人类来说具有不同的语义。 反汇编器(通常是编译器的 asm 输出)只会使用一个,因此语义区别就会丢失。cmp
和sub
当它们的两个输入相等(即减法结果为0)时设置ZF。je
(如果相等则跳转)是语义相关的同义词。test %eax,%eax
/和 %eax,%eax
当结果为零时再次设置 ZF,但没有“相等”测试。 测试后的 ZF 不会告诉您两个操作数是否相等。 所以jz
(如果为零则跳转)是语义相关的同义词。test
is likeand
, 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 thatcmp eax, 0
would:a = a&a = a-0
).(PF as usual is only set according to the low 8 bits)
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 comparing a register against zero. It's a peephole optimization forcmp reg,0
that you can use regardless of the semantic meaning.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-X but not KNL) addktestb/w/d/q k1, k2
, which operate on AVX512 mask registers (k0..k7) but still set regular FLAGS liketest
does, the same way that integerOR
orAND
instructions do. (Sort of like SSE4ptest
or SSEucomiss
: inputs in the SIMD domain and result in integer FLAGS.)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
orcmp
.Use of
jz
vs.je
can be confusing.jz
andje
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
andsub
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. Sojz
(jump if zero) is the semantically relevant synonym.这段代码来自一个子例程,该子例程被赋予了一个指向某个东西的指针,可能是某个结构或对象。 第二行取消引用该指针,从该指针获取一个值 - 可能本身是一个指针,也可能只是一个 int,存储为其第二个成员(偏移量 +4)。 第 3 行和第 4 行测试该值是否为零(如果它是指针,则为 NULL),如果它为零,则跳过以下几个操作(未显示)。
对零的测试有时被编码为与立即文字零值的比较,但编写此代码的编译器(或人类?)可能认为 testl 操作会运行得更快 - 考虑到所有现代 CPU 的东西,如管道和寄存器重命名。 它来自同一个技巧,它包含使用 XOR EAX,EAX(我在科罗拉多州某人的车牌上看到的!)清除寄存器的想法,而不是明显但可能较慢的 MOV EAX, #0(我使用旧的符号) )。
在asm中,像perl一样,TMTOWTDI。
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.
在某些程序中,它们可用于检查缓冲区溢出。
在分配空间的最顶部放置一个 0。 将数据输入到堆栈后,它会在分配的空间的最开头查找0,以确保分配的空间不会溢出。
它被用在exploits-exercises的stack0练习中,检查是否溢出,如果没有溢出并且那里有一个零,它会显示“再试一次”
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"
如果eax为零,则执行条件跳转,否则将在319e9处继续执行
If eax is zero it will perform the conditional jump, otherwise it will continue execution at 319e9
测试指令在操作数之间执行逻辑与运算,但不会将结果写回到寄存器中。 仅更新标志。
在您的示例中,测试 eax,如果 eax 为零,则 eax 将设置零标志,如果设置了最高位,则 eax 将设置符号标志以及其他一些标志。
如果设置了零标志,则跳转(je)指令将跳转。
您可以将代码转换为更具可读性的代码,如下所示:
具有相同的功能,但需要更多字节的代码空间。 这就是编译器发出测试而不是比较的原因。
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:
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.
它测试
eax
是否为 0、或大于或小于 0。 在这种情况下,如果eax
为0,则进行跳转。It tests whether
eax
is 0, or above, or below. In this case, the jump is taken ifeax
is 0.test
的含义是将参数与在一起,并检查结果是否为零。 所以这段代码测试 EAX 是否为零。 如果为零,je
将跳转。顺便说一句,这会生成比 cmp eax, 0 更小的指令,这就是编译器通常会这样做的原因。
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.