所以我正在阅读一些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
如果不相等则会跳转。
我错过了什么吗?
答案 0 :(得分:5)
考虑以下3种说明:
jne
,jl
等等)都会根据FLAGS寄存器中一个或多个位的当前设置跳转。 cmp
指令外,还有更多指令可以修改FLAGS寄存器中的部分位(如test
,add
等等)。mov
,push
等等)。 实施例
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