AT&T 汇编-7: 跳转标志

EFLAGS 寄存器包含很多用来表明结果状态的标志,根据这些标志值可以作出不同的跳转。

CF(carry flag)标志

# jc.s

.section .rodata
msg:
   .asciz   "The result is: %d.\n"
err:
   .asciz   "overflow.\n"

.section .text
.globl main
main:
   movw  $55555,  %ax
   movw  $55555,  %bx
   addw  %ax,     %bx
   jc    overflow

   pushw $0
   pushw %bx
   pushl $msg
   call  printf
   addl  $8,   %esp
   jmp   end

overflow:
   pushl $err
   call  printf
   addl  $4,   %esp

end:
   pushl $0
   call  exit

第 14 行计算 55555+55555 的值并把结果保存在 bx 中,很明显的结果的值已经超出了 bx 的最大值范围。当结果超出目标位置的最大值时,EFLAGS 寄存器中的 CF 标志(carry flag)将会被设置为 1,说明计算结果发生了溢出。而jc(jump if carry)指令检查 CF 标志,如果为 1 则跳转。

OF(overflow flag)标志

CF 标志主要是给无符号整数运算使用的,用于反映计算结果是否超过最大值或小于 0。但是在使用有符号整数的加法时,不仅结果超出目标范围时会设置 CF 标志,当结果小于 0 的时候也会设置 CF 标志,所以有符号整数运算时一般使用溢出标志 OF(overflow flag)来判断结果是否超出有符号整数的上限或下限。

# jo.s

.section .rodata
msg:
   .asciz   "The result is: %d.\n"
err:
   .asciz   "overflow flag.\n"
err2:
   .asciz   "carry flag.\n"

.section .text
.globl main
main:
   movb  $0x7f,   %al
   addb  $1,      %al
   jc    carry_flag
   jo    overflow_flag

   pushw $0
   pushw %bx
   pushl $msg
   call  printf
   addl  $8,   %esp
   jmp   end

carry_flag:
   pushl $err2
   call  printf
   addl  $4,   %esp
   jmp   end

overflow_flag:
   pushl $err
   call  printf
   addl  $4,   %esp

end:
   pushl $0
   call  exit

第 15 行计算 0x7f(十进制的 127)加 1 的值,并把结果存放在 al 中。8 位无符号整数能表示的范围是 0 到 255,所以并不会执行 16 行的跳转;而 8 位有符号整数表示的范围是 -128 到 127,计算结果超出范围,所以jo(jump if overflow)指令跳转了。

内存中保存的值是以二进制形式存在的,所谓的有符号整数和无符号整数都是从用户的角度去看的,例如对于值 0xff,如果看成是无符号整数值是 255,而有符号整数值却是 -1,但是在内存里表示都是 11111111。

SF(sign flag)标志

判断变量是否从正数变成负数可以使用 SF(sign flag)标志,从负数变为正数可以使用前面提到的 CF 标志。

# js.s

.section .rodata
msg:
   .asciz   "Sign is changed.\n"

.section .text
.globl main
main:
   movw  $1,  %ax
   subw  $6,  %ax
   jns   end

   pushl $msg
   call  printf
   addl  $4,   %esp

end:
   pushl $0
   call  exit

EFLAGS 寄存器还包含许多其它表示状态的标志,如之前跳转和循环中提到的 ZF 标志,还有用于奇偶校验的 PF 标志,等等。下面的表来自 Richard Blum 写的《Professional Assembly Language》(中文名《汇编语言程序设计》,马朝晖等译),总结了部分标志的跳转指令:

+=============+==============================+=======================+
| instruction |          description         |         EFLAGS        |
+=============+==============================+=======================+
|     ja      | jump if above                | CF = 0 and ZF = 0     |
+-------------+------------------------------+-----------------------+
|     jae     | jump if above or equal       | CF = 0                |
+-------------+------------------------------+-----------------------+
|     jna     | jump if not above            | CF = 1 or ZF = 1      |
+-------------+------------------------------+-----------------------+
|     jnae    | jump if not above or equal   | CF = 1                |
+-------------+------------------------------+-----------------------+
|     jb      | jump if below                | CF = 1                |
+-------------+------------------------------+-----------------------+
|     jbe     | jump if below or equal       | CF =1 or ZF = 1       |
+-------------+------------------------------+-----------------------+
|     jnb     | jump if not below            | CF = 0                |
+-------------+------------------------------+-----------------------+
|     jnbe    | jump if not below or equal   | CF = 0 and  ZF = 0    |
+-------------+------------------------------+-----------------------+
|     jg      | jump if greater              | ZF = 0 and SF = OF    |
+-------------+------------------------------+-----------------------+
|     jge     | jump if greater or equal     | SF = OF               |
+-------------+------------------------------+-----------------------+
|     jng     | jump if not greater          | ZF = 1 or SF <> OF    |
+-------------+------------------------------+-----------------------+
|     jnge    | jump if not greater or equal | SF <> OF              |
+-------------+------------------------------+-----------------------+
|     jl      | jump if less                 | SF <> OF              |
+-------------+------------------------------+-----------------------+
|     jle     | jump if less or equal        | ZF = 1 or SF <> OF    |
+-------------+------------------------------+-----------------------+
|     jnl     | jump if not less             | SF = OF               |
+-------------+------------------------------+-----------------------+
|     jnle    | jump if not less or equal    | ZF = 0 and SF = OF    |
+-------------+------------------------------+-----------------------+
|     je      | jump if equal                | ZF = 1                |
+-------------+------------------------------+-----------------------+
|     jne     | jump if not equal            | ZF = 0                |
+-------------+------------------------------+-----------------------+
|     jc      | jump if carry                | CF = 1                |
+-------------+------------------------------+-----------------------+
|     jnc     | jump if not carry            | CF = 0                |
+-------------+------------------------------+-----------------------+
|     jo      | jump if overflow             | OF = 1                |
+-------------+------------------------------+-----------------------+
|     jno     | jump if not overflow         | OF = 0                |
+-------------+------------------------------+-----------------------+
|     js      | jump if sign                 | SF = 1                |
+-------------+------------------------------+-----------------------+
|     jns     | jump if not sign             | SF = 0                |
+-------------+------------------------------+-----------------------+
|     jz      | jump if zero                 | ZF = 1                |
+-------------+------------------------------+-----------------------+
|     jnz     | jump if not zero             | ZF = 0                |
+=============+==============================+=======================+

符号”<>”表示不等于。greater/less 用于有符号整数,above/below 用于无符号整数。

发表于 2011年5月25日
  1. 2012年4月14日 01:02 | #1

    你这个表好像emacs org生成的。内容不错,可以整理个pdf。另外,可否交换连接,联系我。

    • ou
      2012年4月14日 15:07 | #2

      表格是用vim画的,有一个叫drawit的插件,我的emacs水平仅仅是入门级菜鸟。

  2. 2012年4月14日 16:39 | #3

    drawit图大了就卡。

  3. william
    2012年8月16日 16:36 | #4

    “第13行计算55555+55555的值并把结果保存在ax中,很明显的结果的值已经超出了ax的最大值范围。”
    这句应该改为:
    “第14行计算55555+55555的值并把结果保存在bx中,很明显的结果的值已经超出了bx的最大值范围。”

    • ou
      2012年8月16日 16:41 | #5

      笔误……多谢指正~

发表评论

XHTML: 您可以使用这些标签: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>