![](/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.