天天看點

彙編的jl/jg與jb/ja--------古魏書生

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則把它們視為有符号數

繼續閱讀