是否可以在没有'cmp`的情况下在汇编中使用条件跳转?

时间:2018-01-07 16:50:33

标签: assembly x86

所以我正在阅读一些assembly source code用于学习目的,并且遇到了一些非常奇怪的东西(或者我可能只是一个新手):

.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 个答案:

答案 0 :(得分:5)

考虑以下3种说明:

  • 所有条件跳转(如jnejl等等)都会根据FLAGS寄存器中一个或多个位的当前设置跳转。
  • cmp指令外,还有更多指令可以修改FLAGS寄存器中的部分位(如testadd等等)。
  • 然后有很多指令不会修改任何标志(例如movpush等等)。

实施例

cmp al, ah
jne .ver_err

jne .ver_err根据最新标志修改指令设置的标志位跳转,在这种情况下为cmp al, ah

inc bx
jl .ver

jl .ver根据最新标志修改指令设置的标志位跳转,在这种情况下为inc bx

inc bx
lea si, [si+1]
jl .ver

由于这个插入的lea指令不会修改任何标志,jl .ver指令仍会根据inc bx指令设置的标志位跳转,因为它仍然是最近的标志修改指令

答案 1 :(得分:2)

跳转指令只检查对应于后缀的标志。在跳转之前不需要cmp指令。在这种情况下, inc指令只增加寄存器,但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 int i = a - b; if(a < b) {...}指令,其中没有关于标志的详细信息。(C编译器需要知道,哪些标志被指令修改,它可以将ggplot(effectdat) + geom_line(aes(x = varL,y = fit,linetype=varP)) + theme_bw() + geom_point(aes(x = varL,y = fit, shape = varP))优化为减法和跳转指令。)

答案 2 :(得分:2)

您可以在设置标志的指令和测试它们的指令之间拥有任意数量的指令,只要它们都不会影响您要测试的标志,并详细了解指令和/或一个很好的参考是必不可少的。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="Up">Up Vote</button>
<div id="Rate">0</div>
<button id="Down">Down Vote</button>

但是你并不需要专门的cmp eax,edx xchg eax,edx jne label 指令 - 任何设置标志的指令都可以跟随一个测试标志的指令。例如

cmp