Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1355694
  • 博文数量: 416
  • 博客积分: 13005
  • 博客等级: 上将
  • 技术积分: 3297
  • 用 户 组: 普通用户
  • 注册时间: 2006-04-05 16:26
文章分类

全部博文(416)

文章存档

2014年(1)

2013年(4)

2012年(46)

2011年(64)

2010年(12)

2009年(4)

2008年(40)

2007年(187)

2006年(58)

分类:

2007-09-24 19:52:31

8086指令系统
 
   学习一条指令时,要注意以下几个方面:
(1)指令功能----该指令能实现何种操作,通常指令助记符就是指令功能的英文缩写词。
(2)指令支持的寻址方式----指令中的源操作数和目的操作数字段允许采用的寻址方式。
(3)指令对标志位的影响----该指令执行后对各个标志位的影响。
(4)指令的特殊要求----该指令隐含使用或限定使用的寄存器以及需要预置的参数。
 
 8086指令系统分为以下6组:
1、 数据传送指令 ;2、 算术指令;3、 逻辑指令 ;4、 串处理指令;5、 控制转移指令 ;6、 处理机控制指令
一、 数据传送指令
⑴ 通用数据传送指令       ⑵ 累加器专用传送指令
MOV  传送           IN   输入
PUSH 进栈           OUT  输出
POP  出栈           XLAT 换码
XCHG 交换
⑶ 地址传送指令         ⑷ 标志寄存器传送指令
LEA  有效地址送寄存器      LAHF  标志送AH
LDS  指针送寄存器和DS     SAHF AH送标志寄存器
LES   指针送寄存器和ES     PUSHF 标志进栈
                POPF 标志出栈
⑴ 通用数据传送指令:
MOV dst, src;传送指令(move)
  执行操作:(dst) ← (src)
  功能: 将源操作数(字节或字)传送到目的地址。
注意:
   ● 目的操作数dst和源操作数src不能同时用存储器寻址方式,这个限制适用于所有指令;
   ● 目的操作数dst不能是CS,也不能用立即数方式;
   ● 目的操作数dst和源操作数src不允许同时为段寄存器;
   ● MOV指令不影响标志位。
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
PUSH   src ; 进栈指令(push onto the stack)
  执行操作: (SP) ← (SP)-2
        ((SP)) ← (src)
POP    dst ; 出栈指令(pop from the stack)
  执行操作: (dst) ← ((SP))
        (SP) ← (SP)+2
  PUSH和POP指令分别将数据存入堆栈或把堆栈中的数据取出。堆栈是以LIFO(后进先出)方式工作的一个存储区,程序中定义的堆栈段就是这样一个LIFO存储区。数据存入堆栈单元或从堆栈单元中取出都由堆栈指针SP指示,而SP总是指向栈顶,所以进栈和出栈指令都会自动修改SP。
  PUSH指令执行时,SP的内容先减2,然后将数据压入SP所指示的字单元,存储的方法同样是高8位存入高地址字节,低8位存入低地址字节。POP指令执行时,将SP所指示的栈顶地址的内容取出放入目的地址,然后SP增2,指向新的栈顶地址。
注意:
   ● PUSH和POP指令只能是字操作,因此存取字数据后,SP的修改必须是+2或-2;
   ● PUSH和POP指令不能使用立即数方式;
   ● POP指令的dst不允许是CS寄存器;
   ● PUSH和POP指令都不影响标志位。
   PUSH指令在程序中常用来暂存某些数据,而POP指令又可将这些数据恢复。
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
XCHG  opr1, opr2 ; 交换指令(exchange)
  执行操作:(opr1) ←→ (opr2)
  XCHG指令使两个操作数opr1,和opr2互相交换,其中一个操作数必须在寄存器中,另一个操作数可以在寄存器或存储器中。
  注意:
   ● 不允许使用段寄存器
   ● 不影响标志位
 例3.12 假设(DS)=1000H, (SS)=4000H, (SP)=100H, (BX)=2100H, (12100)=00A8H, 指出连续执行下列各条指令后,有关寄存器、存储单元以及堆栈的情况。
     PUSH   DS
     PUSH   BX
     PUSH   [BX]
     POP    DI
     POP    WORD PTR [DI+2]
     POP    DS
 
 
 
执行结果: (SP)=100H-2=0FEH    (SP)=0FE-2=0FCH   (SP)=0FC-2=0FAH
     (400FEH)=1000H       (400FCH)=2100H    (400FAH)=00A8H
 
 
  
执行结果: (SP)=0FA+2=0FCH    (SP)=0FC+2=0FEH     (SP)=0FE+2=100H
      (DI)=00A8H       (100AAH)=2100H      (DS)=1000H
  例3.13 已知(AX)=6634H, (BX)=0F24H, (SI)=0012H, (DS)=1200H, (12F36H)=2500H, 写出下列指令执行的结果。
      XCHG  AH,AL    ; 执行前: (AH)=66H, (AL)=34H
                ; 执行后: (AH)=34H, (AL)=66H
      XCHG  AX,[BX+SI] ; 执行前: (AX)=6634H, (12F36H)=2500H
                ; 执行后: (AX)=2500H, (12F36H)=6634HH
⑵ 累加器专用传送指令:
这组指令只限于使用累加器(ac:AX 或AL)传送信息。
IN  ac, port ; 输入指令(input), port≤0FFH
  执行操作: (AL) ← (port) 传送字节
       或 (AX) ← (port+1,port) 传送字
IN  ac, DX  ; 输入指令, DX中的port>0FFH
  执行操作: (AL) ← ((DX)) 传送字节
       或 (AX) ← ((DX)+1,(DX)) 传送字
OUT  port, ac  ; 输出指令(output), port≤0FFH
  执行操作: (port) ← (AL) 传送字节
       或 (port+1,port) ← (AX) 传送字
OUT  DX, ac   ; 输出指令(output), DX中的 port>0FFH
  执行操作: ((DX)) ← (AL) 传送字节
       或 ((DX)+1,(DX)) ← (AX) 传送字
  注意:
   ● 只限于在AL或AX与I/O端口之间传送信息
   ● 不影响标志位
  对8086及其后继机型的微处理机,所有I/O端口与CPU之间的通信都由输入输出指令IN和OUT来完成。IN指令将信息从I/O输入到CPU,OUT指令将信息从CPU输出到I/O端口,因此,IN和OUT指令都要指出I/O端口地址。微处理机分配给外部设备最多有64K个端口,其中前256个端口(0~FFH)称为固定端口,可以直接在指令中指定。当端口地址超过8位(≥256),称为可变端口,它必须先送到DX寄存器,然后再用IN或OUT指令传送信息。CPU与I/O端口传送信息的寄存器只限于累加器ac (AX或AL),传送16位信息用AX,传送8位信息用AL,这取决于外设端口的宽度。
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
XLAT   ; 换码指令(translate)
  执行操作: (AL) ← ((DS)×16+(BX)+(AL))
  这条指令根据AL寄存器提供的位移量,将BX指示的字节表格中的代码换存在AL中。该指令还可写为:XLAT opr,opr为字节表格的首地址,因为opr所表示的偏移地址已存入BX寄存器,所以opr在换码指令中可有可无,有则可提高程序的可读性。
  注意:
   ● 所建字节表格的长度不能超过256字节,因为存放位移量的是8位寄存器AL;
   ● XLAT指令不影响标志位。
例3.14  IN   AL, 61H   ; (AL) ← 端口61H的内容
     MOV   DX, 278H   ; (DX) ← 端口地址278H
     IN   AL, DX    ; (AL) ← 端口278H的内容
例3.15  OUT   61H, AL   ; 61H端口 ← (AL)
     MOV   DX, 279H   ; (DX) ← 端口地址279H
     OUT   DX, AX    ; 279H端口 ← (AX)
例3.16 将表格TABLE中位移量为3的代码取到AL中。
 
    
⑶ 地址传送指令:
这组指令完成把地址送到指定寄存器的功能。
LEA reg, src ; 有效地址送寄存器(load effective address)
  执行操作:(reg) ← offset of src
  LEA指令把源操作数的有效地址送到指定的寄存器,这个有效地址是由src选定的一种存储器寻址方式确定的。
LDS reg, src ; 指针送寄存器和DS(load DS with point)
  执行操作: (reg) ← (src)
       (DS) ← (src+2)
LES reg, src ; 指针送寄存器和ES(load ES with point)
  执行操作: (reg) ← (src)
       (ES) ← (src+2)
  LDS和LES指令把确定内存单元位置的偏移地址送寄存器,段地址送DS或ES。这个偏移地址和段地址(也称地址指针)是由src指定的两个相继字单元提供的。
 注意:
  ● 指令中的reg不能是段寄存器;
  ● 指令中的src必须使用存储器寻址方式;
  ● 该指令不影响标志位。
例3.17 假设某数据段定义如下:
  0000        DATA SEGMENT
  0000 0040      TABLE   DW  0040H
  0002 3000           DW  3000H
  0004        DATA ENDS
  请指出下列指令的执行结果,并说明它们之间的区别。
  ① MOV BX, TABLE
  ② LEA BX, TABLE
  ③ MOV BX, OFFSET TABLE
  答:第①条指令执行后,(BX)=0040H,
    第②条指令执行后,(BX)=0000,
   第③条指令执行后,(BX)=0000。
  比较①②两条指令,第①条MOV指令是用直接寻址方式把变量TABLE的内容送入BX,而LEA指令是把TABLE的地址送入BX。
  比较②③两条指令可以看到,LEA和用OFFSET指示符实现的功能是相同的,都是将TABLE的偏移地址0000送BX。既然功能相同,它们之间还有什么区别呢?
  首先,LEA指令可以使用各种存储器寻址方式,如,LEA BX,[DI],LEA BX,TABLE[DI],LEA SI,[BX+DI]等,这些指令都是把计算出来的有效地址送目的寄存器,而OFFSET不能使用这些寻址方式,它只作用于像TABLE这样的简单变量(或标号)。
  其次,对简单变量,OFFSET指示符比LEA执行速度快,因为MOV BX, OFFSET TABLE指令在汇编时,由汇编程序计算出了TABLE的偏移地址,并被汇编成立即数传送指令,因此效率很高,而LEA指令是在执行时才计算地址,然后再传送到指定寄存器,因此执行速度相对慢一些。
 例3.18 对例3.17的数据定义,下列两条指令的执行结果是什么?
      ① LDS BX, TABLE
      ② LES BX, TABLE
  答:LDS指令执行后,(BX)=0040H, (DS)=3000H
    LES指令执行后,(BX)=0040H, (ES)=3000H
 
 (4)标志寄存器传送指令:
LAHF 标志寄存器的低字节送AH(load AH with flags)
  执行操作:
  (AH) ← (FLAGS)0-7
SAHF AH送标志寄存器低字节(store AH into flags)
  执行操作:
  (FLAGS) 0-7 ← (AH)
PUSHF 标志进栈(push the flags)
  执行操作:
  (SP) ← (SP)-2
  ((SP)+1,(SP)) ← (FLAGS)0-15
  POPF 标志出栈(pop the flags)
  执行操作:
  (FLAGS) 0-15 ← ((SP)+1,(SP))
  (SP) ← (SP)+2
  注意:
   ● LAHF和SAHF指令隐含的操作寄存器是AH和FLAGS
   ● LAHF和PUSH不影响标志位,SAHF和POPF则由装入的值来确定标志位的值。
二、算术指令
 算术指令包括加、减、乘、除指令,它包括对二进制数进行的算术运算的指令,以及对十进制数(用BCD码表示)运算进行调整的指令。执行算术指令都会影响条件标志位,条件标志位包括CF、PF、AF、ZF、SF和OF,它们标志算术运算结果的特征。
⑴ 加法指令            ⑵ 减法指令
ADD  加法              SUB  减法  CMP  比较
ADC  带进位加            DEC  减1
INC  加1               NEG  求补
⑶ 乘法指令            ⑷ 除法指令
MUL  无符号数乘法          DIV  无符号数除法
IMUL 带符号数乘法          IDIV 带符号数除法
⑸ 符号扩展指令          ⑹ 十进制调整指令
CBW  字节转换为字          DAA  加法的十进制调整
CWD  字转换为双字         DAS  减法的十进制调整
                  AAA  加法的ASCII调整
                   AAS  减法的ASCII调整      
                  AAM  乘法的ASCII调整
                   AAD  除法的ASCII调整
⑴ 加法指令:
ADD dst,src 加法指令(addition)
  执行操作: (dst) ← (src)+(dst)
ADC dst,src 带进位加指令(add with carry)
  执行操作: (dst) ← (src)+(dst)+CF
INC opr 加1指令(increment)
  执行操作: (opr) ← (opr)+1
  ADD和ADC指令是双操作数指令,它们的两个操作数不能同时为存储器寻址方式,也就是说,除源操作数为立即数的情况外,源和目的操作数必须有一个是寄存器寻址方式。INC指令是单操作数指令,它可以使用除立即数方式外的任何寻址方式。
  ADD和ADC指令影响条件标志位(也称条件码),INC指令影响除CF外的其它条件码。条件码中最主要的是SF、ZF、CF和OF,加法运算对这四个条件码的设置方法如下:
  SF=1 加法结果为负数(符号位为1)
  SF=0 加法结果为正数(符号位为0)
  ZF=1 加法结果为零
  ZF=0 加法结果不为零
  CF=1 最高有效位向高位有进位
  CF=0 最高有效位向高位无进位
  OF=1 两个同符号数相加(正数+正数,或负数加负数),结果符号与其相反
  OF=0 不同符号数相加时,或同符号数相加,结果符号与其相同
  计算机在执行运算时,并不区别操作数是带符号数还是无符号数,一律按上述规则设置条件码,因此,程序员要清楚当时处理的是什么类型的数据。例如,当加法运算结果的最高有效位为1时,机器将SF置1。如果参加运算的是两个带符号数,那么和的最高有效位是符号位,SF置1说明结果是一个负数。如果参加运算的是两个无符号数,那么和的最高有效位也是数值位,此时SF置0或置1都失去了表示正负数的意义。
  对带符号数和无符号数,它们表示结果溢出的条件标志位也是不同的。上述OF位的设置条件显然只符合带符号数的溢出情况,OF=1表示运算结果是错误的。而无符号数溢出(运算结果超出了有限位的表示范围)时,表现为最高有效位产生进位,因此,CF=1是无符号数溢出的标志。另外,在双字长数运算时,低位字相加设置的CF,说明低位字向高位字有无进位的情况。
例3.19  MOV  BX,9B8CH  ; (BX)=9B8CH
         ADD  BX,6478H  ; now (BX)=0000H
         9B8A     1001 1011 1000 1010
        + 6476     + 0110 0100 0111 0110
       -----------  --------------------------
       1← 0000    1← 0000 0000 0000 0000
  条件码设置: SF=0  最高有效位(D15)为0
         ZF=1  结果为0
         CF=1  最高有效位向高位有进位
         OF=0  不同符号数相加,不产生溢出
 例3.20 编写执行双精度数(DX,CX)和(BX,AX)相加的指令序列,DX是目的操作数的高位字,BX是源操作数的高位字。指令执行前:
      (DX,CX)= A248 2AC0H,(BX,AX)= 088A E25BH。
   指令序列:  ADD  CX, AX  ;(CX)= 0D1BH
         ADC  DX, BX  ; now,(DX)=0AAD3H
   执行ADD指令:
         2AC0     0010 1010 1100 0000
        + E25B    + 1110 0010 0101 1011
       ---------   ------------------------
       1← 0D1B   1← 0000 1101 0001 1011
  条件码设置: SF=0  最高有效位(D15)为0,无符号位意义
         F=0  结果不为0
         CF=1  最高有效位向高位有进位
         OF=0  加数最高位分别为0、1,溢出位置0,OF对低位字无溢出意义
  执行ADC指令:
         A248     1010 0010 0100 1000
         088A     0000 1000 1000 1011
        +   1     +          1←CF
       ----------  ----------------------------
         AAD3     1010 1010 1101 0011
  条件码设置: SF=1  最高有效位(D31)为1,对带符号数运算表示结果为负
         ZF=0  结果不为0
         CF=0  最高有效位向高位无进位
         OF=0  结果符号与操作数相同,未产生溢出
⑵ 减法指令:
SUB dst,src 减法指令(subtract)
  执行操作: (dst) ← (dst)-(src)
SBB dst,src 带借位减法指令(subtract with borrow)
  执行操作: (dst) ← (dst)-(src)-CF
DEC opr 减1指令(decrement)
  执行操作: (opr) ← (opr)-1
CMP opr1,opr2 比较指令(compare)
  执行操作: (opr1)-(opr2),根据相减结果设置条件码,但不回送结果
  以上指令除DEC指令不影响CF外,其他都影响条件码。与加法类似,SF和ZF分别表示减法结果的符号以及为零的情况;CF表明无符号数相减结果溢出与否;OF表明带符号数相减结果溢出与否。但在对CF和OF位的设置方法上减法和加法有所不同,下面对此做进一步说明:
  CF=1   二进制减法运算中最高有效位向高位有借位(被减数<减数,不够减的情况)
  CF=0   二进制减法运算中最高有效位向高位无借位(被减数≥减数,够减的情况)
  OF=1   两数符号相反(正数-负数,或负数-正数),而结果符号与减数相同
  OF=0   同符号数相减时,或不同符号数相减,其结果符号与减数不同
NEG opr 求补指令(negate)
  执行操作: (opr) ← -(opr),
                        
  求补操作即把操作数变为与其符号相反的数:正数(求补)→负数(求补)→正数
  机器在执行求补指令时,把操作数各位求反后末位加1,因此执行的操作也可表示为:
  (opr) ← 0FFFFH-(opr)+1
  NEG指令的条件码设置方法为:
   CF=1  不为0的操作数求补时
   CF=0  为0的操作数求补时
   OF=1  当求补运算的操作数为-128(字节)或-32768(字)时
   OF=0  当求补运算的操作数不为-128(字节)或-32768(字)时
例3.21 字长为8位的两数相减,其可表示数的范围为:带符号数 -128~127(80H~7FH),无符号数0~255(0~FFH)。运算结果超出可表示数范围即为溢出,说明结果错误。
  ① 43H-16H=2DH
    0100 0011     0100 0011   条件码设置:CF=0
  - 0001 0110    + 1110 1010         OF=0
 --------------  --------------
    0010 1101  1← 0010 1101

  说明:机器作减法运算时,先将减数求补,然后转化为加法运算,所以实际上机器设置CF的方法是:最高有效位不产生进位时,CF=1;最高有效位产生进位时,CF=0。这和做减法时有借位CF=1,无借位CF=0是一致的。
  本例参加运算的数无论是看作带符号数还是无符号数,运算结果均有效。
  ② 0C8H-66H=62H
    1100 1000     1100 1000   条件码设置:CF=0
  - 0110 0110    + 1001 1010         OF=1
  --------------  ------------
    0110 0010  1← 0110 0010
  说明:如果是无符号数的运算,被减数够减无借位,所以CF置0,表明结果有效。如果操作数是带符号数,且被减数与减数符号相反,而结果符号与减数符号相同,所以OF置1,表明结果无效。
   ③ 54H-76H=0DEH
    0101 0100     0101 0100    条件码设置:CF=1
   - 0111 0110   + 1000 1010          OF=0
   -------------    -------------
    1101 1110    1101 1110

  说明:如果是无符号数的运算,本例中被减数<减数,减运算向高位有借位(或加运算无进位),则CF置0,表明结果无效。如果是带符号数的运算,同符号数相减,OF置0,结果有效。
   ④ 4BH-0B6H=0DEH
    0100 1011     0100 1011    条件码设置:CF=1
   - 1011 0110     + 0100 1010          F=1
   ---------------   -----------
    1001 0101     1001 0101
  说明:如果是无符号数的运算,本例中被减数<减数,减运算向高位有借位(或加运算无进位),则CF置0,表明结果无效。如果是带符号数的运算,不同符号数相减,且结果符号与减数符号相同,OF置1,结果也是无效的。
  例3.22 分析下列程序的执行情况:
  
        DATA_A   DD   62562FAH
        DATA_B   DD   412963BH
        RESULT   DD   ?
         …    …   …
        MOV     AX, WORD PTR DATA_A   ; (AX)=62FAH
        SUB    AX, WORD PTR DATA_B   ; sub 963BH from AX
        MOV    WORD PTR RESULT, AX   ; save the result
        MOV    AX, WORD PTR DATA_A+2  ; (AX)=0625H
        SBB    AX, WORD PTR DATA_B+2  ; sub 0412H with borrow
        MOV    WORD PTR RESULT, AX   ; save the result
  答:SUB指令执行后,(AX)= 62FAH-963BH=0CCBFH,CF=1(有借位)。执行SBB指令后,(AX)= 625H-412H-1=212H,CF=0,OF=0,因此,保存于RESULT的结果数据为0212CCBFH。  
⑶ 乘法指令:
MUL  src  无符号数乘法(unsigned multiple)
  IMUL src 带符号数乘法(signed multiple)
  字节操作: (AX) ← (AL)×(src)
  字操作:  (DX, AX) ← (AX)×(src)
MUL和IMUL指令的区别仅在于操作数是无符号数还是带符号数,它们的共同点是,指令中只给出源操作数src,它可以使用除立即数方式以外的任一种寻址方式。目的操作数是隐含的,它只能是累加器(字运算为AX,字节运算为AL)。隐含的乘积寄存器是AX或DX(高位)和AX(低位)。
乘法指令只影响CF和OF,其它条件码位无定义。无定义是指指令执行后,条件码位的状态不确定,因此它们是无用的。
  MUL指令的条件码设置为:
  CF OF= 0 0 乘积的高一半为0(字节操作的(AH)或字操作的(DX))
  CF OF= 1 1 乘积的高一半不为0
  这样的条件码设置可以指出字节相乘的结果是8位(CF=0)还是16位(CF=1),字相乘的结果是16位(CF=0)还是32位(CF=1)。
  IMUL指令的条件码设置为:
  CF OF= 0 0 乘积的高一半为低一半的符号扩展
  CF OF= 1 1 其他情况
  符号扩展是指做字节乘法时,乘积低8位的最高位为0,高8位也扩展为0,或者低8位的最高位为1,高8位也扩展为1的情况。对两个字相乘,符号扩展是指乘积的低16位的最高位为0,高16位也扩展为0,或者低16位的最高位为1,高16位也扩展为1的情况。
例3.23 无符号数乘法 
    ; from the data segment
    DATA1  DB  25H
    DATA2  DB  65H
    RESULT DW ?
    ; from the code segment
      MOV   AL,DATA1
      MOV   BL,DATA2
      MUL   BL        ; register addressing mode
      MOV   RESULT,AX
    or
      MOV   AL,DATA1
      MUL   DATA2       ; direct addressing mode
      MOV   RESULT,AX
    or
      MOV   AL,DATA1
      MOV   SI,OFFSET DATA2
      MUL   BYTE PTR [SI]   ;register indirect addressing mode
      MOV   RESULT,AX
  本例25H×65H=0E99H,高16位不为0,所以CF=1,OF=1。
 
 
  例3.24 
    DATA3  DW  2378H
    DATA4  DW  2F79H
    RESULT1 DW  2 DUP(?)
    …    …
      MOV   AX, DATA3   ; load first operand into AX(装入 第一个 操作数)
      IMUL   DATA4     ; multiply it by the second operand
      MOV   RESULT1, AX  ; store the lower word result(存储 低字 结果)
      MOV   RESULT1+2, DX ; store the higher word result
  本例2378H×2F79H=0693 CBB8H,即(DX)=0693H,(AX)=0CBB8H。因为高16位不是低16位的符号扩展,所以条件码设置为CF=1,OF=1。
⑷ 除法指令:
DIV  src 无符号数除法(unsigned divide)
IDIV src 带符号数除法(signed divide)
 字节操作: (AL) ← (AX) / src 的商
      (AH) ← (AX) / src 的余数
 字操作: (AX) ← (DX, AX) / src 的商
     (DX) ← (DX, AX) / src 的余数
参加运算的除数和被除数是无符号数时,使用DIV指令,其商和余数也均为无符号数。IDIV指令执行的操作与DIV相同,但操作数必须是带符号数,商和余数也均为带符号数,而且余数的符号与被除数的符号相同。
  这两条除法指令的被除数必须存放在AX或DX,AX中,源操作数src作为除数,可用除立即数以外的任一种寻址方式来取得。
  除法指令对所有条件码均无定义,因此对除法指令产生的错误,如除数为0或商溢出等错误,程序员都不能用条件码进行判断,而是由系统直接转入0型中断来处理。所谓商溢出,是指被除数高一半的绝对值大于除数的绝对值时,商超出了16位的表示范围(字操作)或8位的表示范围(字节操作)。
  由于使用除法指令的需要,经常要将字节数据扩展为字数据,或者将字数据扩展为双字数据,所以我们先介绍下面的符号扩展指令,然后再对除法指令举例。
⑸ 符号扩展指令:
CBW 字节扩展为字(convert byte to word)
 执行操作:
 (AH)= 00H 当(AL)的最高有效位为0时
 (AH)= FFH 当(AL)的最高有效位为1时
CWD 字扩展为双字(convert word to double word)
 执行操作:
 (DX)=0000H当(AX)的最高有效位为0时
 (AH)=FFFFH当(AX)的最高有效位为1时
 这是两条无操作数指令,进行符号扩展的操作数必须存放在AL寄存器或AX寄存器中。这两条符号扩展指令都不影响条件码。
 注意:
 除法指令要求字操作时,被除数必须为32位,除数是16位,商和余数是16位的;
 字节操作时,被除数必须为16位,除数是8位,得到的商和余数是8位的。
例3.25  假设(AX)= 0BA45H,下列指令分别执行后的结果是什么?
          CBW   ; 执行后,(AH)=00, (AL)=45H, 或 (AX)=0045H
          CWD   ; 执行后,(DX)=0FFFFH, (AX)=0BA45H
  例3.26  编写程序,分别实现下列数据的无符号除法和带符号除法。
       DATA7  DW 9400H  ; numerator
       DATA8  DW 0060H  ; denominator
       QUOT   DW ?    ; quotient
       REMAIN DW ?    ; remainder
       ; unsigned divide
        MOV  AX,DATA7  ; AX holds numerator
        MOV  DX,0    ; (DX,AX)= 0000 9400H
        DIV  DATA8    ; unsigned divide
        MOV  QUOT,AX   ; quotient is in AX,(AX)=018AH
        MOV  REMAIN,DX ; remainder is in DX,(DX)=0040H
       ; signed divide
        MOV  AX,DATA7  ; (AX)=9400H
        CWD        ; (DX,AX)=0FFFF, 9400H
        IDIV DATA8   ; signed divide
        MOV  QUOT,AX  ; quotient is in AX,(AX)=0FEE0HH
        MOV  REMAIN,DX ; remainder is in DX,(DX)=0

⑹ 十进制调整指令:
80x86微型机提供了一组十进制调整指令,用来处理ASCII码和BCD码表示的数。
 
  BCD码:
  BCD(Binary Coded Decimal)是用二进制编码表示的十进制数(见表3.3),十进制数采用0~9十个数字,是人们最常用的。在计算机中,同一个数可以用两种BCD格式来表示:①压缩的BCD码 ②非压缩的BCD码
  压缩的BCD码:
  压缩的BCD码用4位二进制数表示一个十进制数位,整个十进制数用一串BCD码来表示。例如,十进制数59表示成压缩的BCD码为0101 1001,十进制数1946表示成压缩的BCD码为0001 1001 0100 0110。
  非压缩的BCD码:
  非压缩的BCD码用8位二进制数表示一个十进制数位,其中低4位是BCD码,高4位是0。例如,十进制数78表示成压缩的BCD码为0000 0111 0000 1000。
  从键盘输入数据时,计算机接收的是ASCII码,要将ASCII码表示的数转换成BCD码是很简单的,只要把ASCII码的高4位清零即可。
  压缩的BCD码调整指令
  DAA和DAS指令完成加法和减法的调整功能。
DAA 加法的十进制调整(decimal adjust for addition)
  执行操作:(AL)← 把AL中的和调整为压缩的BCD格式
DAS 减法的十进制调整(decimal adjust for subtraction)
  执行操作:(AL)← 把AL中的差调整为压缩的BCD格式
DAA和DAS指令的调整方法如下:
  执行加法指令(ADD、ADC)或减法指令(SUB、SBB)后,
  1.如果结果的低4位 (AL)0~3>9或AF=1,则(AL)←(AL)±06H,且AF置1;
  2.如果结果的高4位 (AL)4~7>9或CF=1,则(AL)←(AL)±60H,且CF置1。
  对上述方法,加法调整作+06H和+60H,减法调整作-06H和-60H。这两个调整的条件,如果满足其一,则±06H或±60H;如果同时满足,则±06H后,再±60H。
  非压缩的BCD码调整指令
AAA 加法的ASCII调整(ASCII adjust for add)
  执行操作:
  (AL)← 把AL中的和调整为非压缩的BCD格式
  (AH)←(AH)+ 调整产生的进位值
AAS 减法的ASCII调整(ASCII adjust for sub)
  执行操作:
  (AL)← 把AL中的差调整为非压缩的BCD格式
  (AH)←(AH)- 调整产生的借位值
  加法和减法的操作数可以直接使用ASCII码,而不必把高位0011清为0000,AAA和AAS指令就是专门为ASCII码操作数或非压缩BCD码操作数的加减法而设计的。
AAA和AAS的调整方法如下:
  执行加法指令(ADD、ADC)或减法指令(SUB、SBB)后,结果存放在AL寄存器中:
  (1)如果(AL)0~3= 0~9,且AF=0,则(AL)4~7= 0,AF的值送CF;
  (2)如果(AL)0~3=A~F,或AF=1,则(AL)←(AL)±06H,(AL)4~7= 0,(AH)←(AH)±1,AF的值送CF。
  AAA和AAS指令除影响AF和CF标志外,其余标志位均无定义。
  AAM 乘法的ASCII调整(ASCII adjust for mul)
  执行操作:(AX)← 把AX中的积调整为非压缩的BCD格式
  AAD 除法的ASCII调整(ASCII adjust for div)
  执行操作:(AX)← AX中的被除数(非压缩的BCD格式)转化为二进制数
  以上两条指令是专为非压缩的BCD码的乘除法而设计的,它们将乘法和除法的结果转换为非压缩的BCD码。
  
  注意:AAM和AAD都只对AX寄存器中的数进行调整,它们只影响SF、ZF和PF标志位,其它标志位无定义。
  AAM的调整方法为:
  执行乘法指令(MUL)后,调整存放在AL寄存器中的乘积:
   (AH)←(AL)/ 0AH的商
   (AL)←(AL)/ 0AH的余数
  AAM实际上是将两个一位数的非压缩BCD码相乘后得到的乘积进行二化十的转换,十位数放在AH中,个位数放在AL中,那么AX中就是乘积的非压缩BCD码。
  注意:如果是两个ASCII码数相乘,要先将它们转换成非压缩BCD码。
  AAD的调整方法为:
  执行除法指令之前,对AX中的非压缩BCD码(被除数)执行:
   (AL)←(AH)×10+(AL)
   (AH)← 0
  与其它调整指令不同的是,AAD用在DIV指令之前,即先将AX中的被除数调整成二进制数,并存放在AL中,再用DIV指令作二进制数的除法。AX中的被除数是二位非压缩BCD码,AH中的十位数乘10,再加上AL中的个位数,即转换为二进制数。
表ASCII和BCD码
十进制数字 ASCII码 压缩的BCD码 非压缩的BCD码 
0 0011 0000 0000 0000 0000 
9 0011 1001 1001 0000 1001 
注:数字1~8略,可依次类推
例3.27  ASCII码转换为BCD码。
     
    ASC   DB '9562481273' ; ASCII string
        ORG   0010H
        UNPACK DB  10 DUP(?) ; store BCD number
    …    …
    MOV   CX,10   ; load the counter
    SUB   BX,BX   ; clear BX
  AGAIN:  MOV   AL,ASC[BX]; move to AL content of mem [BX+ASC]
    AND   AL,0FH   ; mask the upper nibble
    MOV   UNPACK[BX],AL  ; move to mem [BX+UNPACK] the AL
    NC    BX     ; make the pointer to point at next ASCII number
    LOOP   AGAIN   ; loop until finished
  上例中的AND指令完成逻辑与操作,AL寄存器的内容和0FH相与,结果使ASCII码的高4位清零,低4位保持不变,于是一个ASCII码数就转换成了BCD码。
例3.28  编写程序,实现BCD数据的加法和减法。
     ① BCD3←BCD1+BCD2  ; BCD3=2784+1839=4623
     ② BCD3←BCD1-BCD2  ; BCD3=2784-1839=0945
    编写程序如下:
     DATA SEGEMENT
     BCD1 DB 84H,27H ; BCD format of 2784
     BCD2 DB 39H,18H ; BCD format of 1839
     BCD3 DB 2 DUP(?)
     DATA ENDS
    ① MOV  AL,BCD1   ; AL←84H
      ADD  AL,BCD2   ; AL←84H+39H=0BDH (B>9,D>9)
      DAA        ; AL←0BDH+06+60H=23H, AF=1,CF=1
      MOV  BCD3,AL   ; BCD3←23H
      MOV  AL,BCD1+1  ; AL←27H
      ADC  AL,BCD2+1  ; AL←27H+18H+1=40H, AF=1,CF=0
      DAA        ; AL←40H+06=46H, because AF=1
      MOV  BCD3+1,AL  ; BCD3+1←46H
    ② MOV  AL,BCD1   ; AL←84H
      SUB  AL,BCD2   ; AL←84H-39H=4BH (4≯9,B>9)
      DAS        ; AL←4BH-06=45H, AF=1, CF=0
      MOV  BCD3,AL   ; BCD3←45H
      MOV  AL,BCD1+1  ; AL←27H
      SBB  AL,BCD2+1  ; AL←27H-18H=0FH
      DAS        ; AL←0FH-06=09H, because F>9
      MOV  BCD3+1,AL  ; BCD3+1←09H
   使用DAA和DAS指令,注意:
   · 被调整的数必须在AL寄存器中;
   · 影响除OF外的其它条件码标志;
   · DAA必须紧接在加指令之后,DAS必须紧接在减指令之后。
  例3.29  两个ASCII码数5和2相加,要求结果也为ASCII码。
     
     MOV  AL,'5'    ; AL←35H
     ADD  AL,'2'    ; AL←35H+32H=67H, AF=0
     AAA         ; changes 67H to 07H,
     OR   AL,30     ; OR AL with 30H to get ASCII
  例3.30  编写15和7的非压缩BCD码的减法程序,要求结果也为非压缩BCD码。
     MOV  AX,0105H   ; unpacked BCD for 15
     MOV  CL,07
     SUB  AL,CL     ; (AL)←05-07 =-2 (FEH)
     AAS         ; adjusted: 0FE-06=0F8→08→(AL),
               ; 01-1=00→(AH), leaving (AX)=0008
 例3.31  两个ASCII码数7和8相乘,要求结果也为ASCII码。
     MOV  AL,'7'    ; (AL)=37H
     AND  AL,0FH    ; (AL)=07 unpacked BCD
     MOV  DL,'6'    ; (DL)=36H
     AND  DL,0FH    ; (DL)=06 unpacked BCD
     MUL  DL      ; (AX)=07×06=002AH=42
     AAM         ; (AX)=0402 (7×6=42 unpacked BCD)
     OR   AX,3030H   ; (AX)=3432 result in ASCII
 例3.32 编写ASCII码数的除法程序。
     MOV  AX,3539H   ; (AX)=3539, ASCII for 59
     AND  AX,0F0FH   ; (AH)=05,(AL)=09,unpacked BCD data
     AAD         ; (AX)=003BH=59
     MOV  BH,08H    ; divide by 08
     DIV  BH      ; 3BH/8 gives (AL)=07,(AH)=03
     OR   AX,3030H   ; (AL)=37H (quotient), (AH)=33H (remainder)
三、逻辑指令:
⑴ 逻辑运算指令          ⑵ 移位指令
AND     逻辑与          SAL     算术左移
OR      逻辑或          SHR     逻辑右移
OT      逻辑非          SAR     算术右移
XOR     异或           ROL    循环左移
TEST     测试           ROR    循环右移
                  RCL    带进位循环左移
                  RCR    带进位循环右移
⑴ 逻辑运算指令:
AND dst,src ;逻辑与(logic and)
 执行操作: (dst)←(dst) (src)
OR dst,src ;逻辑或(logic or)
 执行操作: (dst)←(dst) (src)
NOT opr ;逻辑非(logic not)
 执行操作: (opr)←(opr)
XOR dst,src ;异或 (exclusive or)
 执行操作: (dst)←(dst) (src)
TEST opr1,opr2 ;测试(test)
 执行操作: (opr1) (opr2),根据与运算结果设置条件码,结果不回送
  逻辑运算指令是一组位操作指令,它们可以对字或字节按位执行逻辑操作,因此,源操作数经常是一个位串。以上五条指令除NOT不影响标志位外,其它四条指令执行后,CF和OF置0,AF无定义,SF、ZF和PF根据运算结果设置
例3.33 (1) 可使某些位置0的AND运算
      MOV   AL,35H    ; (AL)=0011 0101B
      AND   AL,0FH    ; (AL)=35H 0FH=0000 0101B
       ; flag settings will be: SF=0,ZF=0,PF=1,CF=OF=0
(2) 可使某些位置1的OR运算
       MOV   AX,0504H   ; (AX)=0000 0101 0000 0100B
       OR   AX,80F0H   ; (AX)=0504H 80F0H=1000 0101 1111 0100B,
                 ; flags will be: SF=1,ZF=0,PF=0,CF=OF=0
注意:标志位PF按结果的低8 位来设置。
3) XOR运算使两个操作数不同值的位置1,相同值的位置0
  
       A.使某些位求反,其余位不变
       MOV  BL,86H    ; (BL)=1000 0110B
       XOR  BL,03H    ; (BL)=86H 03H=1000 0101B,
          ; flags will be: SF=1,ZF=0,PF=0,CF=OF=0
       B.使某寄存器清0
       XOR  AX,AX  ; (AX)=0, clear AX by XORing it with itself
(4) 测试某些位为0或为1
       A.测试某数的奇偶性
       MOV  DL,0AEH    ; (DL)=1010 1110B
       TEST DL,01H ; 0AEH 01H=0000 0000, ZF=1,but DL is unchanged
       JZ EVEN ; if ZF=1,then tested number is even, if ZF=0, odd
       B.测试某数为正数或负数
       MOV  DH,9EH    ; (DL)=1001 1110B
       TEST DH,80H    ; 9EH 80H=1000 0000, ZF=0
       JZ EVEN ; if ZF=0,then the value is negative, if ZF=1,it is
⑵ 移位指令:
移位指令包括逻辑移位指令、算术移位指令、循环移位指令和带进位循环移位指令。指令中的目的操作数dst可以是除立即数外的任何寻址方式。移位次数(或位数)cnt=1时,1可直接写在指令中;cnt>1时,cnt必须放入CL寄存器。
 
SHL dst,cnt ; 逻辑左移(shift logical left)
 执行操作:
 
SHR dst,cnt ; 逻辑右移(shift logical right)
 执行操作:
 
SAL dst,cnt ; 算术左移(shift arithmetic left)
 执行操作:

SAR dst,cnt ; 算术右移(shift arithmetic right)
 执行操作:
  
SHL和SAL指令向左移动的操作是相同的,在每次逐位移动后,最低位用0来补充,最高位移入CF。SHR与SHL移动的方向相反,每次向右移动后,最高位用0来补充,最低位移入CF。SAR在每次右移都用符号位的值补充最高位,最低位仍然是移入CF。
由此可以看出,算术移位适于带符号数的移位处理。我们知道,一个数左移n位相当于乘以2n,右移n位相当于除以2n, 所以,当一个带符号数需要乘(或除)2n时,可使用算术移位指令SAL(或SAR)。当一个无符号数需要乘(或除)2n时,可使用逻辑移位指令SHL(或SHR)。使用移位指令将一个数扩大或缩小2n倍,比使用乘法或除法指令的速度快。
  移位指令的条件码设置:
  CF= 移入的数值
  OF=1 当cnt=1时,移动后最高位的值发生变化
  OF=0 当cnt=1时,移动后最高位的值未发生变化
  SF、ZF、PF根据移动后的结果设置
ROL dst,cnt ; 循环左移(rotate left)
 执行操作:
 
 
ROR dst,cnt ; 循环右移(rotate right)
 执行操作:
 

RCL dst,cnt ; 带进位循环左移(rotate left through carry) 
 执行操作:
 

RCR dst,cnt ; 带进位循环右移(rotate right through carry)
 执行操作:
 
  
这组指令完成位循环移位的操作,ROL和ROR是简单的位循环指令,RCL和RCR是连同CF位一起循环移位的指令。它们左右移动的方法以及移位次数的设置与移位指令类似。
循环移位指令执行后,CF和OF的设置方法与移位指令相同;SF、ZF和PF标志位不受影响。
例3.34 写DATA1除以8的程序,假设:⑴DATA1为无符号数⑵DATA1为带符号数。
      DATA1  DB   9AH
      TIMES  EQU   3
      ; ⑴ DATA1 is unsigned operand
         MOV   CL,TIMES   ; set number of times to shift
         SHR    DATA1,CL   ; DATA1 will be 13H, CF=0
         
       ; ⑵ DATA1 is signed operand
         MOV    CL,TIMES   ; set number of times to shift
         SAR    DATA1, CL   ; DATA1 will be 0F3H, CF=0
例3.35 编写统计DATAW字数据中1的个数COUNT的程序,要求COUNT是BCD码。
  
      DATAW  DW   97F4H
      COUNT  DB   ?
      …    …
       XOR   AL,AL   ; clear AL to keep the number of 1s in BCD
       MOV   DL,16   ; rotate total of 16 times
       MOV   BX,DATAW ; move the operand to BX
    AGAIN: ROL   BX,1    ; rotate it once
       JNC   NEXT   ; check for 1, if CF=0 then jump
       ADD   AL,1   ; if CF=1 then add one to count
       DAA        ; adjust the count for BCD
    NEXT: DEC   DL     ; go through this 16 times
        JNC   AGAIN   ; if not finished go back
        MOV   COUNT,AL ; save the number of 1s in COUNT
四、串处理指令:
⑴ 串处理指令
 MOVSB / MOVSW   串传送
  STOSB / STOSW   存串
  LODSB / LODSW   取串
  CMPSB / CMPSW   串比较
  SCASB / SCASW   串扫描
⑵ 串重复前缀
  REP        重复串操作
  REPE / REPZ    相等/为零时重复
  REPNE / REPNZ   不等/不为零时重复
⑶ 设置方向标志
  CLD        使DF=0
  STD        使DF=1
串处理指令处理存放在存储器中的字节串或字串,串处理的方向由方向标志位DF决定,串处理指令之前可加重复前缀,在执行串处理指令时,源串的指针SI和目的串的指针DI根据DF的指示自动增量(+1或+2)或自动减量(―1或―2)。
这组串处理指令用于处理连续存储单元中的字操作数或字节操作数,它们有几个共同点:
  1. 它们一般都分两步执行,第一步完成处理功能,如传送、存取、比较等。第二步进行指针修改,以指向下一个要处理的字节或字。
  2. 源串必须在数据段中,目的串必须在附加段中,串处理指令隐含的寻址方式是SI和DI寄存器的间接寻址方式。源串允许使用段跨越前缀来指定段。
  3. 串处理的方向取决于方向标志DF,DF=0时,地址指针SI和DI增量(+1或+2);DF=1时,地址指针SI和DI减量(-1或-2)。程序员可以使用指令CLD和STD来建立方向标志。
  4. MOVS、STOS、LODS指令不影响条件码,CMPS、SCAS指令根据比较的结果设置条件码。
  与串传送指令MOVS和串存入指令STOS联用的重复前缀是REP,取串指令LODS一般不加重复前缀。 与串比较指令和串扫描指令联用的重复前缀是REPE(REPZ)或REPNE(REPNZ)。
设置方向标志指令
  CLD DF置0(clear direction flag)
  STD DF置1(set direction flag)
  为了处理连续存储单元中的字符串或数串,地址指针需要连续地增量或减量,指针增量或减量决定了串处理的方向。当用CLD指令使DF=0时,源串的指针SI和目的串的指针DI自动增量(+1或+2),当用STD指令使DF=1时,指针SI和DI自动减量(―1或―2)。地址指针是±1还是±2,取决于串操作数是字节还是字,处理字节串时,地址指针每次+1或―1,处理字串时,地址指针每次+2或―2。
(1)串处理指令:
MOVSB / MOVSW 串传送(move string byte/word)
  执行操作:
  (ES:DI)←(DS:SI)
  (SI)←(SI)±1(字节)或±2(字)
  (DI)←(DI)±1(字节)或±2(字)
STOSB / STOSW 存串(load from string byte/word)
  执行操作:
  (ES:DI)←(AL)或(AX)
  (DI)←(DI)±1(字节)或±2(字)
LODSB / LODSW 取串(store into string byte/word)
  执行操作:
  (AL)或(AX)←(DS:SI)
  (SI)←(SI)±1(字节)或±2(字)
CMPSB / CMPSW 串比较(compare string byte/word)
  执行操作:
  (DS:SI)-(ES:DI),根据比较的结果设置条件码
  (SI)←(SI)±1(字节)或±2(字)
  (DI)←(DI)±1(字节)或±2(字)
SCASB / SCASW 串扫描(scan string byte/word)
  执行操作:
  (AL)-(ES:DI)或(AX)-(ES:DI),根据扫描比较的结果设置条件码
  (DI)←(DI)±1(字节)或±2(字)
(2)串重复前缀:
REP 重复执行串指令,(CX)=重复次数
  执行操作:
  ① (CX)=0时,串指令执行完毕,否则执行② ~ ④
  ② (CX)←(CX)-1
  ③ 执行串指令(MOVS或STOS)
  ④ 重复执行①
REPE / REPZ 相等/为零时重复执行串指令,(CX)=比较/扫描的次数
  执行操作:
  ① (CX)=0或ZF=0时,结束执行串指令,否则继续② ~ ④
  ② (CX)←(CX)-1
  ③ 执行串指令(CMPS或SCAS)
  ④ 重复执行①
REPNE / REPNZ 不等/不为零时重复执行串指令,(CX)=比较/扫描的次数
  执行操作:
  ① (CX)=0或ZF=1,结束执行串指令,否则继续② ~ ④
  ② (CX)←(CX)-1
  ③ 执行串指令(CMPS或SCAS)
  ④ 重复执行①
 REP对其后的串指令(MOVS或STOS)只有一个结束条件,即重复次数(CX)=0。在进行串比较和串扫描时,串指令前应加前缀REPE(REPZ)或REPNE(REPNZ),这两条重复前缀用重复次数(CX)和比较结果(ZF)来控制串指令的结束。当(CX)=0时,说明每个串数据都比较(或扫描)过了,此时串操作正常结束;当因ZF=1或0而结束串操作时,说明在满足比较结果相等或不等的条件下,可提前结束串操作。
例3.36 编写程序,传输20字节的字符串。
      DATSEG  SEGMENT
      DATAX   DB 'ABCDEFGHIJKLMNOPQRST'
      DATAY   DB 20 DUP(?)
      DATSEG  ENDS
      ; - - - - - - - - - - - - - - - - - - - -
      CODSEG  SEGMENT
      ASSUME  CS:CODSEG,DS:DATSEG,ES:DATSEG
  START: MOV    AX,DATSEG
      MOV    DS,AX    ; initialize the data segment
      MOV    ES,AX    ; initialize the extra segment
      CLD          ; clear direction flag for autoincrement
      MOV    SI,OFFSET DATAX  ; load the source pointer
      MOV   DI,OFFSET DATAY  ; load the destination pointer
      MOV    CX,20    ; load the counter
      REP    MOVSB    ; repeat until CX becomes zero
      MOV   AX,4C00H  ; return to DOS
      INT    21H
  CODSEG ENDS
      END    START
  串传送指令将SI所指示的数据段中的数据传送到由DI指示的附加段中,本例将源串和目的串都设置在同一个段DATSEG中,因此,DS和ES都定义为DATSEG。
例3.37 编写程序:
(1)用STOS指令将0AAH存入100个存储器字节;
(2)利用LODS指令测试这些存储器单元的内容是否是0AAH,如果不是则显示"bad memory"。
      DTSEG  SEGMENT
      DATAM  DB 100 DUP(?)
      MESG   DB 'bad memory', '$'
      DTSEG  ENDS
      ; - - - - - - - - - - - - - - - - - -
      CDSEG  SEGMENT
      ASSUME CS:CDSEG,DS:DTSEG,ES:DTSEG
  START: MOV   AX,DTSEG   ; initialize
      MOV   DS,AX    ; DS register
      MOV   ES,AX    ; and ES register
      CLD         ; clear DF for increment
      MOV   CX,50    ; load the counter(50 words)
      MOV   DI,OFFSET DATAM ; load the pointer for destination
      MOV   AX,0AAAAH   ; load the pattern
      REP   STOSW    ; repeat until CX=0
      ; bring in the pattern and test it one by one
      MOV   SI,OFFSET DATAM  ; load the pointer for source
      MOV   CX,100       ; load the counter(100 bytes)
  AGAIN: LODSB           ; load into AL from DS:SI
      XOR   AL,0AAH      ; is pattern the same?
      JNZ   OVER       ; if not the same, then exit
      LOOP  AGAIN       ; continue until CX=0
      JMP   EXIT       ; exit program
  OVER: MOV   AH,09       ; display
      MOV   DX,OFFSET MESG   ; the message
      INT   21H        ; routine
  EXIT: MOV   AX,4C00H      ; return to DOS
      INT   21H
      CDSEG  ENDS
      END   START
  把0AAH存入100个字节是通过执行50次的字操作来完成的。在测试部分,LODSB指令把存储器字节的内容取到AL,并和数据0AAH异或,如果这两个数相同,ZF=1,则继续进行下一个数的测试。如果两数不同,则ZF=0,转去执行显示字符串的BIOS功能调用。显示字符串用了三条指令,首先在AH中装入的显示字符串的功能号09,然后在DX中装入字符串的地址,再用INT 21H调用BIOS例程,完成显示指定字符串的功能。
例3.38 假设有人将电子字典中的"LABEL"误拼为"LABLE",编写程序比较这两个词,并根据比较结果显示
(1)如果相同,则显示"The spelling is correct";
(2)如果不同,则显示"Wrong splling"。
       DATASEG SEGMENT
        DAT_DICT DB 'LABEL'
        DAT_TYPE DB 'LABLE'
        MESS1 DB 'The spelling is correct ','$'
        MESS2 DB 'Wrong spelling ','$'
       DATASEG ENDS
       ; - - - - - - - - - - - - - - - - - - - - -
       CODESEG SEGMENT
       ASSUME CS:CODESEG,DS:DATASEG,ES:DATASEG
   START: MOV  AX,DATASEG
       MOV  DS,AX   ; initialize the data segment
       MOV  ES,AX   ; initialize the extra segment
       CLD       ; DF=0 for autoincrement
       MOV  SI,OFFSET DAT_DICT ; SI is source pointer
       MOV  DI,OFFSET DAT_TYPE ; DI is destination pointer
       MOV  CX,05   ; load the counter
       REPE CMPSB   ; repeat as long as equal or until CX=0
       JE  OVER   ; if ZF=1 then display mess1
       MOV  DX,OFFSET MESS2 ; if ZF=0 then display mess2
       JMP  DISP
    OVER: MOV  DX,OFFSET MESS1
    DISP: MOV  AH,09   ; display message
       INT  21H
       MOV  AX,4C00H ; return to DOS
       INT  21H
   CODSEG ENDS
       END START
   用CMPSB指令可将两个串中的字符逐一比较,在比较SI和DI指向的第一对字符时,根据比较结果设置ZF并使(SI)+1,(DI)+1以及(CX)-1。因为第一对字符是相同的('L'),所以ZF=1,于是由REPE控制再重复比较下一对字符。直到比较第四对字符'E'和'L'时,由于它们不相同,ZF设置为0,所以串比较结束。打印的信息应是:'Wrong spelling '。
例3.39 编写程序,将姓名中的HU DAMING(胡大明)修改为HU DANING(胡大宁),并显示出正确的姓名。
      DATA SEGMENT
      NAME DB 'HU DAMING', '$'
      DATA ENDS
      ; - - - - - - - - - - - -
      CODE  SEGMENT
      ASSUME CS:CODE,DS:DATA,ES:DATA
   START: MOV   AX,DATA
      MOV  DS,AX    ; initialize the data segment
      MOV  ES,AX    ; initialize the extra segment
      CLD         ; DF=0 for autoincrement
      MOV   AL,'M'
      MOV   DI,OFFSET NAME ; DI is destination pointer
      MOV  CX,09    ; load the counter
      REPNE SCASB    ; repeat as long as equal or until CX=0
      JNE  DISP    ; if ZF=0 then display name
      DEC  DI     ; decrement to point at 'M'
      MOV  BYTE PTR [DI],'N' ; replace 'M' with 'N'
   DISP: MOV  AH,09    ; display the corrected name
      MOV  DX,OFFSET NAME
      INT  21H
      MOV  AX,4C00H   ; return to DOS
      INT  21H
   CODE  ENDS
      END  START
  本例中,AL寄存器中的字符'M'与NAME中的每个字符进行比较,如果串中字符与'M'不同,则DI增量,CX减量,继续进行下一个字符的扫描比较,一直到发现'M'或CX=0为止。在本例中,因为发现了'M',比较的结果使ZF=1,同时DI已指向了下一个字符'I',所以DI退回一个字符位置(DEC DI),并用N取代M。
五、控制转移指令:
⑴ 无条件转移
      JMP 跳转
⑵ 条件转移
      JZ/JNZ    结果为零/不为零则转移
      JS/JNS    结果为负/为正则转移
      JO/JNO    溢出/不溢出则转移
      JP/JNP    奇偶位为1/为0则转移
      JB/JNB    低于/不低于则转移
      JBE/JNBE   低于等于/高于则转移
      JL/JNL    小于/不小于则转移
      JLE/JNLE   小于等于/大于则转移
      JCXZ     CX为零则转移
⑶ 循环指令
      LOOP      循环
      LOOPZ/LOOPE  为零/相等时循环
      LOOPNZ/LOOPNE 不为零/不等时循环
⑷ 子程序调用与返回
      CALL      调用
      RET       返回
⑸ 中断及中断返回
      INT       中断
      INTO      溢出则中断
      IRET       中断返回
程序中指令的执行顺序是由CS:IP来决定的,程序转移类指令可改变IP或CS、IP的内容,从而控制指令的执行顺序,实现指令转移、程序调用等功能。
控制转移指令通过改变CS:IP来控制程序的执行流程。这类指令包括无条件转移指令、条件转移指令、循环指令、子程序调用和返回指令以及中断和中断返回指令
 (1)无条件转移:
短转移的目标地址(或称转向地址)相对于当前IP值的位移量在-128至+127字节之间,当前IP值是指JMP指令的下一条指令的地址(如图3.11所示)。对短转移JMP,机器指令的第一个字节为操作码EB,第二个字节为位移量00~FF,这是一个带符号的补码数。转向地址的计算方法为:(IP)当前+8位位移量。操作符SHORT指示汇编程序将JMP指令汇编成一个2字节指令。

① JMP SHORT label 短转移(short jump)
    执行操作:(IP) ← (IP)当前+8位位移量
 图3.11 短转移示意图
 
  
 
 
② JMP NEAR PTR label 近转移(near jump)
  近转移是JMP指令的缺省格式,可以写为"JMP label"。它可在当前代码段内转移,机器指令的操作码是E9,位移量是16位的带符号补码数。指令中的转向地址可以是直接寻址方式、寄存器寻址方式、寄存器间接方式和存储器寻址方式。
● JMP label 直接转移(direct jump)
  执行操作:(IP) ← OFFSET label = (IP)当前+16位位移量
  转移的目标地址在指令中可直接使用符号地址,由于位移量为16位,它的转移范围应是-32768至+32767,也就是说,近转移指令可以转移到段内的任一个位置。
● JMP reg 寄存器间接转移(register indirect jump)
  执行操作:(IP) ← (reg)
  转移的目标地址在寄存器中,例如指令"JMP BX"执行的结果,将BX的内容送给IP。
● JMP WORD PTR OPR 存储器间接转移(memory indirect jump)
  执行操作:(IP) ← (PA+1,PA)
  存储器的物理地址PA由指令中的寻址方式确定,JMP指令执行的结果,把PA单元的字内容送到IP寄存器中。例如"JMP WORD PTR [DI]",物理地址PA = (DS)×24+(DI),指令执行的结果是(IP)= (PA+1,PA)。
③JMP FAR PTR label 远转移(far jump)
  执行操作:(IP) ← label的段内偏移地址
       (CS) ← label所在段的段地址
远转移实现的是段间的跳转,即从当前代码段跳转到另一个代码段中,这意味着指令执行后,不仅要改变IP的值,CS也会得到一个新的段地址。在汇编指令中,远转移的目标地址也可以使用除立即寻址方式外的任何寻址方式来表示。
(2)条件转移指令(conditional jump):
条件转移指令是在满足了规定的条件后才控制程序转移的一类指令,8086的条件转移指令总结在表3.4中。
所有条件转移指令都是短转移指令,转移的目标地址必须在当前IP地址的-128至+127字节范围之内,因此条件转移指令是2字节指令。
计算转向地址的方法和无条件短转移指令是一样的,看例3.40的反汇编代码。
例3.40程序中的"JNZ AGAIN"汇编成"JNZ 000D",000D是标号AGAIN的地址,指令"JNZ 000D"的机器代码是75FA,75是操作码,FA是位移量。当CPU读取JNZ指令后,IP寄存器自动加2(JNZ的指令长度)指向了下一条指令(MOV),此时IP的当前值是0013。计算转向地址时,(IP)当前+位移量 = 0013+FA = 0013+FFFA = 000D,这正是AGAIN的偏移地址。实际上FA是-6的补码,8位的FA与16位的0013相加时,FA符号扩展成为FFFA,相加的加结果为000D。
 表3.4 条件转移指令 
分类 指令 转移条件 说明 
(I) JZ/JE ZF=1 为零/相等,则转移 
 JNZ/JNE ZF=0 不为零/不相等,则转移 
 JS SF=1 为负,则转移 
 JNS SF=0 为正,则转移 
 JO OF=1 溢出,则转移 
 JNO OF=0 不溢出,则转移 
 JP PF=1 奇偶位为1,则转移 
 JNP PF=0 奇偶位为0,则转移 
 JC CF=1 进位位为1,则转移 
 JNC CF=0 进位位为0,则转移 
(II) JB/JNAE/JC CF=1 低于/不高于等于,则转移 
 JNB/JAE/JNC CF=0 不低于/高于等于,则转移 
 JBE/JNA (CF或ZF)=1 低于等于/不高于,则转移 
 JNBE/JA (CF或ZF)=0 不低于等于/高于,则转移 
(III) JL/JNGE (SF异或OF)=1 小于/不大于等于,则转移 
 JNL/JGE (SF异或OF)=0 不小于/大于等于,则转移 
 JLE/JNG ((SF异或OF)或CF)=1 小于等于/不大于,则转移 
 JNLE/JG ((SF异或OF)或CF)=0 不小于等于/大于,则转移 
(IV) JCXZ (CX)=0 CX的内容为0,则转移 
注: (Ⅰ)根据条件码的值转移 (Ⅱ)比较两个无符号数,根据比较的结果转移
(Ⅲ)比较两个带符号数,根据比较的结果转移 (Ⅳ)根据CX寄存器的值转移
 例3.40
    1050:0000  B86610    MOV AX,1040
    1050:0003  8ED8     MOV DS,AX
    1050:0005  B90500    MOV CX,0005
    1050:0008  BB0000    MOV BX,0000
    1050:000D  0207 AGAIN: ADD AL,[BX]
    1050:000F  43      INC BX
    1050:0010  49      DEC CX
    1050:0011  75FA     JNZ 000D
    1050:0013  A20500    MOV [0005],AL
    1050:0016  B44C     MOV AH,4C
    1050:0018  CD21     INT 21
例3.41 假设程序进行两个带符号数的比较,并根据比较结果转移,其中(AL)=80H,(BL)=01,请指出下面两组指令的转向地址。
  ⑴ CMP AL,BL     ⑵ CMP AL,BL
    JL XY         JB XY  
答:⑴ 转向目标地址XY;⑵不能实现转移。
 执行CMP指令时,(AL)-(BL)=80-01=7F,条件码设置为:SF=0,OF=1,CF=0。执行JL指令时,测试转移条件:SF异或OF = 0异或1 =1,说明满足(AL)<(BL)的转移条件,因此,(IP)←XY的偏移地址,程序即转移到XY单元执行新的指令。
JB指令的转移条件为CF=1,而CMP的执行结果使CF=0,所以不能引起转移。
⑶ 循环指令:
这一组指令在循环结构的程序中用来控制一段程序(称为循环体)的重复执行,在汇编指令中循环的转向地址用标号来表示,而在机器指令中给出的是位移量,所以执行循环指令时,若满足循环条件,CPU就计算转向地址:(IP)当前+8位位移量→(IP),即实现循环。
若不满足循环条件,即退出循环,程序继续顺序执行。
循环指令都是短转移格式的指令,也就是说,位移量是用8位带符号数来表示的,转向地址在相对于当前IP值的-128 ~ +127字节范围之内。
对条件循环指令LOOPZ(LOOPE)和LOOPNZ(LOOPNE),除测试CX中的循环次数外,还将ZF的值作为循环的必要条件,因此,要注意将条件循环指令紧接在形成ZF的指令之后。
在多重循环的程序结构中,如果各层循环都使用循环指令来控制,则应注意对CX中循环计数值的保存与恢复。
循环指令均不影响条件码。
LOOP  label    循环(loop)
  执行操作:① (CX)←(CX)-1
       ② 若(CX)≠0,则(IP)←(IP)当前+位移量,否则循环结束
LOOPZ/LOOPE label 为零/相等时循环(loop while zero,or equal)
  执行操作:① (CX)←(CX)-1
       ② 若ZF=1且(CX)≠0,则(IP)←(IP)当前+位移量,否则循环结束
LOOPNZ/LOOPNE label 不为零/不等时循环(loop while nonzero,or not equal)
  执行操作:① (CX)←(CX)-1
       ② 若ZF=0且(CX)≠0,则(IP)←(IP)当前+位移量,否则循环结束
例3.42 编写程序,实现两个数据块BLOCK1和BLOCK2相加,结果存入BLOCK2。
       DATA   SEGMENT
       BLOCK1   DW   100 DUP(?)
       BLOCK2   DW   100 DUP(?)
       DATA  ENDS
       ; - - - - - - - - - - - - - - - - - -
       CODE   SEGMENT
       ASSUME CS:CODE,DS:DATA,ES:DATA
   START: MOV   AX,DATA
       MOV   DS,AX        ; initialize the data segment
       MOV   ES,AX        ; initialize the extra segment
       CLD             ; DF=0 for autoincrement
       MOV   CX,100        ; load the counter
       MOV   SI,OFFSET BLOCK1  ; address of block1
       MOV   DI,OFFSET BLOCK2  ; address of block2
    NEXT: LODSW            ; load the data of block1 into AX
       ADD   AX,ES:[DI]     ; add the data of block2 to AX
       STOSW            ; store the sum to block2
       LOOP   NEXT         ; repeat 100 times
       MOV   AX,4C00H      ; return to DOS
       INT   21H
    CODE ENDS
       END   START
 
 ⑷ 子程序调用与返回:
子程序是一种非常重要的计算机编程结构,它存储在存储器中,可供一个或多个调用程序(主程序)反复调用。主程序调用子程序时使用CALL指令,由子程序返回主程序时使用RET指令。由于调用程序和子程序可以在同一个代码段中,也可以在不同的代码段中,因此,CALL指令和RET指令也有近调用、近返回及远调用、远返回两类格式。
① CALL NEAR PTR SUBPROUT 近调用(near call)
近调用是CALL指令的缺省格式,可以写为"CALL subrotine"。它调用同一个代码段内的子程序(子过程),因此,在调用过程中不用改变CS的值,只需将子程序的地址存入IP寄存器。CALL指令中的调用地址可以用直接和间接两种寻址方式表示。
② CALL FAR PTR SUBPROUT 远调用(far call)
远调用适用于调用程序(也称为主程序)和子程序不在同一段中的情况,所以也叫做段间调用。和近调用指令一样,远调用指令中的寻址方式也可用直接方式和间接方式。
③RET 返回指令(return)
RET指令执行的操作是把保存在堆栈中的返回地址出栈,以完成从子程序返回到调用程序的功能。
● CALL SUBROUT 段内直接调用
  执行操作:① (SP) ← (SP)-2,((SP)) ← (IP)当前
       ② (IP) ← (IP)当前+16位位移量(在指令的第2、3个字节中)
  
  ● CALL DESTIN 段内间接调用
  执行操作:① (SP) ← (SP)-2,((SP)) ← (IP)当前
       ② (IP) ← (EA) ; (EA)为指令寻址方式所确定的有效地址
  ● CALL FAR PTR SUBROUT 段间直接调用
  执行操作:① (SP) ← (SP)-2,((SP)) ← (CS)当前
         (SP) ← (SP)-2,((SP)) ← (IP)当前
       ② (IP) ← 偏移地址(在指令的第2、3个字节中)
         (CS) ← 段地址(在指令的第4、5个字节中)
  ● CALL WORD PTR DESTIN 段间间接调用
  执行操作:① (SP) ← (SP)-2,((SP)) ← (CS)当前
         (SP) ← (SP)-2,((SP)) ← (IP)当前
       ② (IP) ← (EA) ; (EA)为指令寻址方式所确定的有效地址
         (CS) ← (EA+2)
  从CALL指令执行的操作可以看出,第一步是把子程序返回调用程序的地址保存在堆栈中。对段内调用,只需将IP的当前值,即CALL指令的下一条指令的地址存入SP所指示的堆栈字单元中。对段间调用,保存返回地址则意味着要将CS和IP的当前值分别存入堆栈的两个字单元中。
  CALL指令的第二步操作是转子程序,即把子程序的入口地址交给IP(段内调用)或CS:IP(段间调用)。对段内直接方式,调转的位移量,即子程序的入口地址和返回地址之间的差值就在机器指令的2、3字节中。对段间直接方式,子程序的偏移地址和段地址就在操作码之后的两个字中。对间接方式,子程序的入口地址就从寻址方式所确定的有效地址中获得。
  ● RET 段内返回(近返回)
  执行操作:(IP) ← ((SP)),(SP) ← (SP)+2
  ● RET 段间返回(远返回)
  执行操作:(IP) ← ((SP)),(SP) ← (SP)+2
       (CS) ←((SP)),(SP) ← (SP)+2
  ● RET N 带立即数返回
  执行操作:① 返回地址出栈(操作同段内或段间返回)
       ② 修改堆栈指针:(SP) ← (SP)+N
  子程序的最后一条指令必须是RET指令,以返回到主程序。如果是段内返回,只需把保存在堆栈中的偏移地址出栈存入IP即可,如果是段间返回,则要把偏移地址和段地址都从堆栈中取出送到IP和CS寄存器中。
  带立即数返回指令,除完成偏移地址出栈或偏移地址和段地址出栈的操作外,还要再使SP的内容加上一个立即数N,使堆栈指针SP移动到新的位置。指令中的N可以是一个常数,也可以是一个表达式。带立即数返回指令适用于C或PASCAL的调用规则,这些规则在调用过程(子程序)前先把参数压入堆栈,子程序使用这些参数后,如果在返回时丢弃这些已无用的参数,就在RET指令中包含一个数字,它表示压入到堆栈中参数的字节数,这样堆栈指针就恢复到参数入栈前的值。
  CALL指令和RET指令都不影响条件码。
 例3.43 根据下面调用程序和子程序的程序清单,画出RET指令执行前和执行后的堆栈情况。假设初始的SS:SP=A000:1000。
 
    0000  B8 001E   MOV  AX,30
    0003  BB 0028   MOV  BX,40
    0006  50      PUSH AX     ; push data1 into stack
    0007  53      PUSH BX     ; push data2 into stack
    0008  E8 0066   CALL ADDM    ; call subroutine
    000B  B4 02    MOV  AH,2
    …   …      …
    0071  ADDM     PROC NEAR    ; entry point (IP)←0071=000b+0066
    0071  55      PUSH BP     ; save BP
    0072  8B E4    MOV  BP,SP    ; addressing the stack with BP
    0074  8B 46 04  MOV  AX,[BP+4] ; get data2 from stack
    0077  03 46 06   ADD  AX,[BP+6]  ; add data1
    007A  CD      POP  BP      ; get back BP
    007B  C2      0004 RET 4   ; return and revert SP
    007E  ADDM     ENDP
 图3.12 CALL指令和RET指令对堆栈的影响
 
 
 

如图3.12所示,主程序中的两条PUSH指令将数据30和40压入堆栈,CALL指令执行后,返回地址000B又压入堆栈,紧接着程序控制转移到子程序ADDM。子程序中的PUSH指令又使BP的值进栈,此时SP指向栈顶0FFA。MOV指令将0FFA传送给BP,使BP作为寻址堆栈数据的指针。(BP+4)指向的是40,(BP+6)指向的是30,取出数据后用POP指令恢复了BP原先的值,此时,(SP)=0FFC,这是RET 4指令执行前的堆栈状态。
执行RET 4指令时,先使返回地址出栈:(IP)←000B,(SP)←0FFC+2=0FFD,然后,(SP)+4=0FFD+4=1000,结果使SP跳过了堆栈数据而回到了原始位置。
 
 ⑸ 中断及中断返回:
INT n 中断指令(interrupt),n为中断类型号
IRET 中断返回指令(return from interrupt)
INTO 溢出则中断(中断类型为4)
INT n 中断指令(interrupt),n为中断类型号
  执行操作:① 入栈保存FLAGS:  (SP) ← (SP)-2,((SP)) ← (FLAGS)
       ② 入栈保存返回地址:(SP) ← (SP)-2,((SP)) ← (CS)
                  (SP) ← (SP)-2,((SP)) ← (IP)
       ③ 转中断处理程序: (IP) ← (n×4)
                  (CS) ← (n×4+2)
IRET 中断返回指令(return from interrupt)
  执行操作:① 返回地址出栈:(IP) ← ((SP)),(SP) ← (SP)+2
                (CS) ← ((SP)),(SP) ← (SP)+2
       ② FLAGS出栈:(FLAGS) ← ((SP)),(SP) ← (SP)+2
INTO 溢出则中断(中断类型为4)
  执行操作:若OF=1(有溢出),则:
       ① 入栈保存FLAGS:(SP) ← (SP)-2,((SP)) ← (FLAGS)
       ② 入栈保存返回地址:(SP) ← (SP)-2,((SP)) ← (CS)
                  (SP) ← (SP)-2,((SP)) ← (IP)
       ③ 转中断处理程序:(IP) ← (4×4)= (10H)
                 (CS) ← (4×4+2)= (12H)
中断指令用于调用中断例行程序(又称中断服务程序),这是一种远调用。完成各种功能的中断例行程序都有一个编号,称为中断类型号。各种中断例行程序的入口地址按中断类型号的顺序存储在一个表中,这个表称为中断向量表。每个中断例行程序的入口地址占用4个字节,因此,它在中断向量表中的地址可用中断类型号乘4来求得。执行中断指令时,首先要入栈保存调用程序执行的现场,即当时的标志寄存器的值和断点的地址,然后,根据中断类型号(n×4)到中断向量表中取得中断例行程序的入口地址,分别送给IP和CS,以实现调用中断例行程序的功能。
中断返回指令IRET的操作和INT指令相反,即从堆栈中取出返回地址和标志位,然后返回到被中断的程序。
INTO指令隐含的中断类型号为4,因此保存断点地址和标志位后,从中断向量表的10H和12H两个字中取出中断例行程序的入口地址,从而转去运行中断例行程序。
INT指令(包括INTO)执行后,把IF和TF置0,但不影响其它标志位。
 
六、处理机控制指令:
⑴ 标志位处理指令       ⑵ 处理机控制指令
CLC CF置0  CLI IF置0    NOP 无操作
STC CF置1  STI IF置1    HLT 停机
CMC CF求反           WAIT 等待
CLD DF置0           ESC 转义
STD DF置1           LOCK 封锁
处理机控制指令包括一组置0或置1标志位的指令,还有一些控制处理机状态的指令。
⑴ 标志位处理指令 :
这一组指令分别对标志位CF、DF、IF执行置0、置1或求反的操作,如,CLD指令执行的操作是:DF←0;STD执行的操作是:DF←1。
标志位处理指令只影响本指令指定的标志,而不影响其它标志位。
⑵ 处理机控制指令:
NOP 无操作指令(no operation)
  执行操作:不执行任何操作,其机器码占用1个字节单元,执行时间为3个时钟周期,因此,该指令的作用表现在时间和空间上。时间上它可使上下两条指令的执行有一点间隔,这使某些指令的执行,特别是控制硬件接口的指令因为有一点延时而增加可靠性。空间上它的位置可在调试指令时用其它指令来代替。
  HLT 停机指令(halt)
  执行操作:使处理机停止软件的执行并等待一次外部中断的到来,中断结束后处理机继续执行下面的程序。使用该指令的目的通常是为了保持外部硬件中断与软件系统的同步。
  WAIT 等待指令(wait)
  执行操作:测试微处理器的BUSY/TEST管脚,如果执行WAIT指令时,BUSY/TEST=1(指示不忙),则继续执行下一条指令。如果执行WAIT指令时,BUSY/TEST=0(指示忙),则微处理器等待直到BUSY/TEST管脚变为1。
  ESC mem 转义指令(escape)
  执行操作:mem指定存储单元,执行ESC指令时,从存储器取得指令或操作数通过总线送给8087~80387数值协处理器。协处理器能处理算术运算、函数运算、对数运算等数值运算,其运算速度比使用常规指令写的软件快的多。
  LOCK前缀 封锁(lock)
  执行操作:指令前加LOCK,使得在锁定指令期间保持锁存信号LOCK=0,以禁止外部总线上的主控制器或系统其它部件。例如,LOCK MOV AL,[SI]执行时,总线封锁直至MOV指令执行完毕。
转自:
阅读(1776) | 评论(3) | 转发(0) |
给主人留下些什么吧!~~