簡體   English   中英

是否可以在沒有'cmp`的情況下在匯編中使用條件跳轉?

[英]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種說明:

  • 所有條件跳轉(如jnejl等等)都將根據FLAGS寄存器中一個或多個位的當前設置跳轉。
  • 除了cmp指令外,還有更多指令可以修改FLAGS寄存器中的某些位(如testadd等等)。
  • 然后有很多指令不會修改任何標志(如movpush等等)。

例子

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM