汇编的jl、jg与jb、ja

转自:http://blog.ixpub.net/html/13/13151113-234860.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.

你可能感兴趣的:(汇编的jl、jg与jb、ja)