from:http://hi.baidu.com/sxgxd/blog/item/e8ce613fe9405de955e72347.html
一直以來,我對何時用jl/jg何時用jb/ja非常迷惑,昨天試了一下午,終于讓我得到了答案。
書上說jl/jg是用于有符号數的,jb/ja用于無符号數,那jl/jg與jb/ja如何取舍呢,關鍵是要知道無符号數的表示方式.
首先看以下例子:
mov ax,100
mov bx,100
cmp ax,bx
jb @Skip ;這裡是等于,call skip不被執行
;jl @F
call skip
@Skip:
以上代碼中無論是jb還是jl都可正常運作.
稍做修改再看:
mov ax,-100
mov bx,-110
cmp ax,bx ;ax>bx
jb @Skip ;這裡是大于,call skip将被執行
;jl @Skip
call skip
@Skip:
這個例子運作後你會發現call skip執行了,也就是說條件正确,可是這個例子中兩個操作數都是負數(ja/jb是用于無符号數的),為什麼會正确?這是因為IBM-PC負數是用補碼表示的,-100與-110在寄存器内的值其實是這個寄存器的最大值減去目前值的絕對值,16位寄存器最大值是65536,那麼上述代碼中ax=65536-|ax|=65436,bx=65536-|bx|=65426,那麼cmp ax,bx就和第一個例子中cmp ax,bx相同了.(注意:ax=-100=有符号數-100的補碼=65436,但是直接提供65436則是視做無符号數65436而不是-100)
再看下面的例子:
mov ax,100
mov bx,-100
cmp ax,bx
jb @Skip ;小于跳轉(這裡是大于,應該執行call skip)
;jl @Skip
call skip
@Skip:
這個例子中,call skip這條語句将無法執行,表面看條件是對的,但是call skip總是無法執行,因為比較中兩個操作數有隻有一個是有符号數,CPU在執行這種操作時,如果發現兩個數的最高位不同,則會自動進行轉換來完成正确的操作,同時它改變的标志位與jb/ja所判斷的标志位是不同的(我忘了是哪些标志位了),是以,這裡隻能使用jl而不能使用jb.
再看下面的例子:
mov ax,65336
mov bx,-100
cmp ax,bx
jb @Skip
;jl @Skip
call skip
@Skip:
本例中,當使用jb時,将把-100視為無符号數65436,那麼上述條件成立,如果使用jl指令,将把65336視為-200,上述條件也成立.這是因為jb/ja系列指令會無條件把操作數視為無符号數,jl/jg則相反.
總結:(對應四個例子)
(有符号數超出範圍視為無符号數)
1.當操作數全部是正數(有符号數)并且沒有超出資料類型範圍時使用jl/jg和jb/ja都無所謂.優先使用jl/jg.
2.當操作數全部是負數(最高位為1的無符号數)時并且沒有超出資料類型範圍時使用jl/jg和jb/ja也無所謂.優先使用ja/jb.
3.當有任一一個操作數是負數并且沒有超出資料類型範圍時使用jl/jg做為有符号數運算對待.
4.當有任一一個操作數是無符号數(不是負數)時應當使用jb/ja做為無符号數運算對待.
5.無論是正數、負數、有符号數、無符号數,使用ja/jb系列指令都把它們視為無符号數,而使用jl/jg則把它們視為有符号數