汇编的jl/jg与jb/ja--------古魏书生

来源:互联网 发布:中国人眼睛的颜色 知乎 编辑:程序博客网 时间:2024/06/08 02:47

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则把它们视为有符号数

原创粉丝点击