![](/img/trans.png)
[英]GCC compile to assembly: cmp followed by call instead of conditional jump
[英]Is it possible to use a conditional jump in assembly without a `cmp` first?
所以我正在阅读一些用于学习目的的汇编源代码 ,并且遇到了一些非常奇怪的东西(或者我可能只是一个新东西):
.ver:
mov al, [redoxfs.header + Header.version + bx]
mov ah, [.version + bx]
cmp al, ah
jne .ver_err
inc bx
jl .ver
所以在这个子标签中我们有两个跳转指令。
但是,关于最后一次跳转指令jl
。 如果我错了,请纠正我,但是在跳转之前不应该有cmp
,因为它是有条件的吗?
我最初认为它是基于cmp al, ah
,但如果不相等的话jne
跳。
我错过了什么吗?
考虑以下3种说明:
jne
, jl
等等)都将根据FLAGS寄存器中一个或多个位的当前设置跳转。 cmp
指令外,还有更多指令可以修改FLAGS寄存器中的某些位(如test
, add
等等)。 mov
, push
等等)。 例子
cmp al, ah
jne .ver_err
jne .ver_err
根据最近的标志修改指令设置的jne .ver_err
跳转,这种指令在本例中是cmp al, ah
。
inc bx
jl .ver
jl .ver
.ver基于最近的标志修改指令设置的标志位跳转,在这种情况下是inc bx
。
inc bx
lea si, [si+1]
jl .ver
由于这个插入的lea
指令不修改任何标志,因此jl .ver
.ver指令仍然根据inc bx
指令设置的flagbits跳转,因为它仍然是最新的标志修改指令 。
跳转指令只检查对应于后缀的标志。 在跳转之前不需要cmp指令。 在这种情况下, inc-instruction只增加寄存器,但cmp指令设置的标志由jl指令测试。 inc指令可以设置或重置标志。 例如。 溢出时,溢出标志置位。 大多数处理器通过减去寄存器来实现cmp,但只写入标志。 因此子指令设置相同的标志,也可以用于比较。 还允许彼此之后的多个分支,其中通过跳转指令重新检查标志。
cmp eax, ecx
jl lbl_less
je lbl_equal
jg lbl_greater
您还可以显式设置标志,例如。 在被调用的函数中,稍后可以通过跳转指令来检查。
stc ;; set carry-flag
;; instructions, which not unintentionally change the carry-flag
clc ;; clear carry-flag
;; ...
jc lbl_carry_is_set ;; check and jump
在你的情况下,它没有出现,有jl指令,因为所有不等式(包括“小于”)的情况都由jne-instruction检查,所以分支永远不会从最后一行发生。 也许有遗漏的东西。 jl测试inc的操作数是否为负数。
指令的这种行为取决于您拥有的处理器,因此x86的行为与Arm和其他处理器的行为不同。 (在这种情况下,我读取了inc
指令的页面 ,其中没有关于标志的详细信息。(C编译器需要知道,哪些标志被指令修改,它可以优化int i = a - b; if(a < b) {...}
只是减法和跳转指令。)
您可以在设置标志的指令和测试它们的指令之间拥有任意数量的指令,只要它们都不会影响您要测试的标志,并详细了解指令和/或良好的参考至关重要。
cmp eax,edx
xchg eax,edx
jne label
但是你不需要专门的cmp
指令 - 任何设置标志的指令都可以跟随一个测试标志的指令。 例如
sub eax, edx
js label
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.