800 likes | 893 Views
21 世纪高等院校规划教材. 汇编语言程序设计. 相 伟 主编 徐小平 李珍香 副主编. 中国水利水电出版社. 第 3 章 顺序程序设计. 本章主要讲解汇编语言中的常用机器指令 和顺序程序设计方法。通过本章学习,读者应 该掌握以下内容: 数据传送指令 算术运算指令 逻辑运算和移位指令 处理机控制指令 顺序程序设计方法. 3.1 数据传送指令.
E N D
21世纪高等院校规划教材 汇编语言程序设计 相 伟 主编徐小平 李珍香 副主编 中国水利水电出版社
第3章 顺序程序设计 本章主要讲解汇编语言中的常用机器指令 和顺序程序设计方法。通过本章学习,读者应 该掌握以下内容: • 数据传送指令 • 算术运算指令 • 逻辑运算和移位指令 • 处理机控制指令 • 顺序程序设计方法
3.1 数据传送指令 • 数据传送是计算机中最基本、最重要的一种操作。数据传送指令主要负责把数据、地址或立即数传送到寄存器或存储单元中。它又可分为通用数据传送指令、地址传送指令、I/O指令和标志寄存器传送指令等四组。除标志寄存器传送指令外,均不影响标志位。本节主要介绍通用数据传送指令和地址传送指令。
3.1.1 通用数据传送指令 通用数据传送指令包括MOV、XCHG和XLAT三条指令。 1.数据传送指令MOV • 指令格式:MOV dest , src • 功能:将源操作数传送至目的地址中,源操作数保持不变,即dest(src)。 • 其中:MOV为操作码助记符; • dest为目的操作数,可以是通用寄存器、段寄存器、存储单元; • src为源操作数,可以是立即数、通用寄存器、段寄存器、存储单元。
立即数 通用寄存器 存储单元 段寄存器 图3-1 MOV指令传送路径 • MOV指令可以实现CPU内部通用寄存器之间、寄存器和存储单元之间、立即数到存储单元、立即数到内部通用寄存器的数据传送。 • 具体传送路径如图3-1所示: • 图中箭头离开的操作数为源操作数,箭头指向的操作数为目的操作数。
(1)立即数到通用寄存器的传送 • 立即数传送到通用寄存器主要用于给通用寄存器赋初值,立即数(8位或16位)与通用寄存器的类型必须匹配。立即数可以是各种数制(十进制、二进制、八进制、十六进制)的常数、ASCII字符和符号常数。
例3-1:分析下列立即数到通用寄存器的传送指令。例3-1:分析下列立即数到通用寄存器的传送指令。 • MOV AL ,6 ;AL6,字节传送 • MOV AX ,10 ;AX10,字传送 • MOV AL ,1000H ;非法指令,1000H为字,AL为字节寄存器 • MOV CX ,0FFH ;CX0FFH,字传送(十六进制) • MOV AL ,1010B ;AL00001010B,字节传送(二进制) • MOV AL ,‘$’;AL24H
(2)通用寄存器之间的数据传送 • CPU内部通用寄存器之间可以相互传送,传送时要注意两操作数类型必须匹配,即同为字节型或同为字型。 例3-2:分析下列各条指令。 • MOV AX ,BX ; AX(BX),字型 • MOV CL ,AL ; CL(AL),字节型 • MOV AL ,CX ; 非法指令,两操作数类型不一致
(3)通用寄存器与存储单元之间数据传送 • 通用寄存器与存储单元之间相互传送数据时,传送类型由通用寄存器类型来定。 例3-3:分析下列各条指令。 • MOV [2000H] ,AL ; [2000H](AL),字节型传送 • MOV [2000H] ,AX ;[2000H](AL),[2001H](AH),字型传送 • MOV BH ,[1050H] ;BH([1050H]),字节型传送 • MOV BX ,[1050H] ;BL([1050H]),BH ([1051H]),字型传送
(4)通用寄存器与段寄存器之间、存储单元与段寄存器之间的数据传送(4)通用寄存器与段寄存器之间、存储单元与段寄存器之间的数据传送 • 由于段寄存器皆为16位寄存器,因此,通用寄存器与段寄存器之间、存储单元与段寄存器之间只能是字传送。另外,CS段寄存器不能作为传送指令的目标操作数。 例3-4:分析下列各条指令。 • MOV DS ,AX ;DS(AX) • MOV BX ,CS ;BX (CS) • MOV CS ,AX ;非法指令,不允许给CS寄存器赋值 • MOV DS ,AL ;非法指令,操作数的类型不匹配 • MOV [2000H] ,DS ;将16位段寄存器DS的内容送入1000H (低字节)和1001H(高字节)单元中
(5)立即数传送到存储单元 • 当存储单元的类型不确定时,必须用BYTE PTR 或WORD PTR属性操作符来指定存储单元的类型。 例3-5:分析下列各条指令。 • MOV BUF1,20 ;BUF1为字节变量 • MOV SUM,0FFFFH ;SUM为字变量 • MOV BYTE PTR [1000H],8 ;字节型传送,表示将08传送到 1000H单元中 • MOV WORD PTR [1000H],8 ;字传送,将08传送到1000H 单元, 将00传送到1001H单元 • MOV [2000H] ,10H ; 非法指令,无法确定操作类型
以上介绍了MOV指令的各种形式,具体应用时要特别注意以下几点:以上介绍了MOV指令的各种形式,具体应用时要特别注意以下几点: • ① MOV指令不改变源操作数内容,不影响标志位。 • ② 源操作数和目的操作数应该有相同的类型,即必须同为字节型或同为字型。 • ③ 代码段寄存器CS不能用作目的操作数,即不允许给CS赋值。 • ④ 立即数不能用作目的操作数,立即数也不能直接传送给段寄存器。
例3-6: • 若要设置数据段寄存器DS的初值为2000H,不能直接用指令 • MOV DS,2000H • 可用如下两条指令表示: • MOV AX,2000H • MOV DS,AX
⑤ 源操作数和目的操作数不能同时为存储单元操作数。 例3-7:交换两个存储单元BUF1和BUF2的 内容。 • MOV AX ,BUF1 ; AX (BUF1) • MOV BUF2 ,AX ; BUF2 (AX) ⑥ 不允许在段寄存器之间直接传送数据。 • 例如:MOV DS,ES 为非法指令。
2.交换指令XCHG • 指令格式:XCHG dest , src • 功能:将源操作数和目的操作数的内容互换,不影响标志位。 • 其中:XCHG为操作码助记符; dest为目的操作数,可以是通用寄存器或存储单元; src为源操作数,可以是通用寄存器或存储单元。 • 说明:XCHG指令中操作数可以是字,也可以是字节。可以在通用寄存器与通用寄存器之间、通用寄存器和存储单元之间交换数据。但不允许在两个存储单元之间直接交换数据。指令执行后不影响状态标志位。
例3-8:下列三条指令执行后,将寄存器AX和BX的内容互换。例3-8:下列三条指令执行后,将寄存器AX和BX的内容互换。 • MOV AX ,1234H ;(AX) = 1234H • MOV BX ,5678H ; (BX) = 5678H • XCHG AX ,BX ;(AX) = 5678H ,(BX) = 1234H
3.换码指令XLAT • 指令格式: XLAT 或 XLAT 标号 • 功能:将以(BX)为首址、(AL)为偏移量的字节存储单元中的内容传送给AL,即:AL((BX)+(AL))。 • 其中:XLAT为操作码助记符; • 说明:换码指令的两种格式完全等效。标号表示首地址,是为了提高程序的可读性而设置的。本指令只能是字节操作。指令执行结果不影响标志位。 • 换码指令常用于代码转换,即将一种代码转换为另一种代码。
例3-9:分析下列程序段。 • DATA SEGMENT • TAB DB ‘0123456789ABCDEF’ • DATA ENDS • …… • MOV BX ,OFFSET TAB ; BXTAB的偏移地址 • MOV AL ,6 ;将TAB表中第七项的偏移地址6送AL中 • XLAT TAB ;(AL)= 36H • …… • 该程序段的功能就是将AL中的一位十六进制数转换成对应的ASCII码。
3.1.2 地址传送指令 8086/8088中有三条地址传送指令:LEA、LDS和LES。 1.传送偏移地址指令LEA • 指令格式:LEA dest , src • 功能:按源操作数提供的寻址方式计算偏移地址,并将其送入目的操作数中。 • 其中:LEA为操作码助记符; • dest为目的操作数,只能是16位通用寄存器; • src为源操作数,只能是存储单元。 • 该指令的执行不影响标志位。
例3-10:阅读下面程序段,分析各条指令的执行过程。例3-10:阅读下面程序段,分析各条指令的执行过程。 • DATA SEGMENT • BUF1 DB ‘ABCDEF’ • NUM DW 20 ,35 ,-10 • COUNT DW 0 • DATA ENDS • …… • ① MOV BX ,OFFSET NUM ;将NUM的偏移地址6送入BX中 • ② LEA BX ,NUM ;将NUM的偏移地址6送入BX中 • ③ MOV AX ,[BX] ;将偏移地址为6的单元中内容20送入AX • ④ LEA AX ,[BX] ;将BX所指存储单元的偏移地址6送AX中 • ⑤ MOV COUNT ,OFFSET BUF1 ;将BUF1的偏移地址送COUNT • ⑥ LEA COUNT ,BUF1 ;非法指令,目的操作数是存储单元 • …… • 上述程序段中指令前面的数字标号①~⑥是为方便说明问题而加的。
2.传送偏移地址及数据段首址指令LDS • 指令格式:LDS dest ,src • 功能:将源操作数所指存储单元中的第一个字传送给指定的16位通用寄存器,第二个字传送给段寄存器DS,即dest (src),DS (src + 2)。 • 其中:LDS为操作码助记符; dest为目的操作数,只能是16位通用寄存器; src为源操作数,只能是存储单元(四个字节)。 • 该指令执行结果不影响标志位。
例3-11 :有如下指令 LDS DI ,[20H] • 指令执行前,假设:(DS)= C000H , (C0020H)= 34H , (C0021H)= 12H , (C0022H)= 00H , (C0023H)= 60H • 指令执行后, (DI)= 1234H ,(DS)= 6000
3.传送偏移地址及附加数据段指令LES • 指令格式:LES dest , src • 功能:将源操作数所指存储单元中的第一个字传送给指定的16位通用寄存器,第二个字传送给段寄存器ES,即dest(src) , ES(src+2)
3.2 算术运算指令 • 8086/8088的算术运算指令主要包括二进制运算指令和十进制调整指令。 • 二进制算术运算指令是指对二进制数进行加、减、乘、除运算的指令。它们中有单操作数指令,如加1指令INC、减1指令DEC、求补指令NEG等;也有双操作数指令,如加法指令ADD、减法指令SUB、乘法指令MUL、除法指令DIV等。单操作数指令的操作数不允许用立即数和段寄存器,而双操作数指令的两个操作数中除源操作数为立即数情况外,其中必须有一个是寄存器操作数。除加1、减1指令不影响CF,其余指令均对CF、OF、ZF、SZ、PF、AF产生影响。
3.2.1 加法类指令 • 包括ADD、ADC和INC三条指令,执行字或字节的加法运算。 1.加法指令ADD • 指令格式:ADD dest , src • 功能:将目的操作数与源操作数相加,结果保存在目的操作数单 元中,源操作数保持不变。即dest (dest)+(src) 。 • 其中:ADD为操作码助记符; dest为目的操作数,可以是通用寄存器或存储单元; src为源操作数,可以是立即数、通用寄存器或存储单元。 • 指令执行后对状态标志CF、OF、ZF、SZ、PF、AF产生影响。
例3-12:分析下列指令执行后AX、CX寄存器和标志寄存器中各状态位的值。例3-12:分析下列指令执行后AX、CX寄存器和标志寄存器中各状态位的值。 ADD AX ,CX • 指令执行前,假设(AX)= 022AH,(CX)= 14E8H。 • 具体执行过程用二进制表示如下: • 0000 0010 0010 1010 B • + 0001 0100 1110 1000 B • 0001 0111 0001 0010 B • 由上式可知,最高位无进位,CF=0;低四位有进位,AF=1;最高位为0,SF=0;运算结果不为0,ZF=0;运算结果中1的个数为偶数,PF=1;运算结果无溢出,OF=0。 • 指令执行后,CF=0 , AF=1,SF=0,ZF=0 , PF=1, OF=0。 (AX)= 022AH +14E8H = 1712H;(CX)= 14E8H,内容不变。
2.带进位加法指令ADC • 指令格式:ADC dest , src • 功能:与ADD指令基本相同,区别是ADC指令执行时要将进位标志位CF加进去。即 dest (dest)+(src)+ CF。 • 该指令主要用于多字节数或多字数的相加运算。在多字节或多字相加时,先进行低字节或低字相加(用ADD指令实现),再进行高字节或高字相加。在进行高字节或高字相加时必须加上低位的进位CF。
例3-13:分析以下程序段 • DATA SEGMENT • NUM1 DW 5678H ,1234H ; 双精度数12345678H • NUM2 DW 0ABCDH ,6789H ; 双精度数6789ABCDH • SUM DW 0 ,0 • DATA ENDS • …… • MOV AX ,NUM1 • ADD AX ,NUM2 ;两低位字相加 • MOV SUM ,AX ;和放在SUM中 • MOV AX ,NUM1+2 • ADC AX ,NUM2+2 ;两高位字相加,同时加上进位CF • MOV SUM+2 ,AX • ……
该例完成两个双精度数的加法运算。 • 运算过程如下所示: • ① 两低位字相加 0101 0110 0111 1000 B • 5678H+ 0ABCDH = 0245H + 1010 1011 1100 1101 B • 进位CF= 1 1 0000 0010 0100 0101 B • ② 两高位字相加 0001 0010 0011 0100 B • 1234H + 6789H = 79BDH + 0110 0111 1000 1001 B • 0111 1001 1011 1101 B • 再加进位CF + 1 B • 79BDH +1 = 79BEH 0111 1001 1011 1110 B
3.加1指令INC • 指令格式:INC dest • 功能:操作数自身加1,结果再送回到原操作数单元中。即dest(dest)+1 。 • 其中:INC为操作码助记符; dest为操作数,可以是通用寄存器或存储单元,若 为存储单元,必须指明其操作类型(字或字节)。 • 该指令执行结果影响除CF外的所有条件标志,主要用于对计数器或地址指针的调整,常用在循环结构程序中。
例3-14:以下指令可实现对寄存器或存储单元加1(注意存储单元的类型)。例3-14:以下指令可实现对寄存器或存储单元加1(注意存储单元的类型)。 • INC AL • INC CX • INC WORD PTR [BX] • INC BYTE PTR [1000H]
3.2.2 减法类指令 • 包括SUB、SBB、DEC、NEG和CMP五条指令,执行字或字节的减法运算。 1.减法指令SUB • 指令格式:SUB dest , src • 功能:将目的操作数与源操作数相减,结果保存在目的操作数单元中,源操作数保持不变。即dest(dest)-(src) 。 • 其中:SUB为操作码助记符; dest为目的操作数,可以是通用寄存器或存储单元; src为源操作数,可以是立即数、通用寄存器或存储单元。
例3-15:分析下列指令 • MOV AX ,8765H • SUB AX ,1234H • 上述两条指令可以对两个立即数8765H与1234H求差运算,最终结果保存在AX中,即(AX)= 7531H 2.带借位减法指令SBB • 指令格式:SBB dest , src • 功能:与SUB指令基本相同,区别是SBB指令执行时要减去借位标志CF。即dest(dest)- (src)-CF。 • 该指令主要用于多字节数或多字数相减运算。运算时,先进行低字节或低字相减(用SUB指令实现),再进行高字节或高字相减。在进行高字节或高字相减时,必须减去低位的借位CF。
例3-16:有两个双精度数0A1365724H和9248B578H,计算两数之差,结果的高位放在DX中,低位放在AX中。例3-16:有两个双精度数0A1365724H和9248B578H,计算两数之差,结果的高位放在DX中,低位放在AX中。 • 程序段如下: • MOV AX ,5724H • SUB AX ,0B578H ;低字相减,有借位 • MOV DX ,0A136H • SBB DX ,9248H ;高字相减,再减去借位
3.减1指令DEC • 指令格式:DEC dest • 功能:操作数自身减1,结果送回到原操作数单元中。即dest(dest)-1 。 • 其中:DEC为操作码助记符; • dest与INC指令中规定相同。 • 注意:该指令不影响进位标志CF的状态,常用在循环结构程序中。 例3-17: • DEC CX ;CX(CX)-1 • DEC BYTE PTR[BX] ;必须指明存储单元的操作类型(字或字节)
4.求补指令NEG • 指令格式:NEG dest • 功能:将目的操作数按位取反后加1,送回原操作数单元中。即dest0-(dest) 。 • 其中:NEG为操作码助记符; • dest与INC指令中规定相同。 • 注意:该指令影响所有的条件标志。
例3-18:分析下列指令的执行结果。 NEG AX • 指令执行前,(AX)= 10H • 指令执行后,(AX)= (0010H)+1 = 0FFF0H 例3-19:假设有一双精度数,低字保存在 AX中,高字保存在DX中。若要求其补码, 可用如下指令实现: • NEG AX • MOV BX ,0 • SBB BX ,DX • MOV DX ,BX
5.比较指令CMP • 指令格式:CMP dest , src • 功能:目的操作数减源操作数,但不送结果。即 (dest)-(src) 。 • 其中:CMP为操作码助记符; dest为目的操作数,可以是通用寄存器或存储单元; src为源操作数,可以是立即数、通用寄存器或存储单元。 • 该指令与SUB指令一样执行减法操作,但不回送相减结果,仅影响全部状态标志位。CMP指令通常用在选择结构程序中,其后紧跟着条件转移指令,用来根据比较结果转向不同的程序分支。
例3-20:比较AX是否大于100,可用如下代码段实现。例3-20:比较AX是否大于100,可用如下代码段实现。 • CMP AX ,100 ;(AX)-100 • JB BELOW ;若(AX)<100,则转移 到BELOW执行 • SUB AX ,100 ;否则,AX←(AX)-100 • …… • BELOW: ……
3.2.3 乘法指令 • 乘法指令用来实现两个二进制操作数的字节或字相乘运算。根据操作数是无符号数还是带符号数,乘法指令可分为无符号数乘法指令和带符号数乘法指令两种。 • 1.无符号数乘法指令MUL • 指令格式:MUL src • 功能:两个无符号数相乘。 • 字节乘法:AX←(AL)*(src) • 字乘法: DX(高字),AX(低字)←(AX)*(src) • 其中:MUL为操作码助记符; src为源操作数(乘数),可以是寄存器或存储单元,但不能使用立即数或段寄存器。 • 注意:指令中只指定乘数,被乘数默认在寄存器AL或AX中。 • 该指令只影响状态标志CF和OF,对其它标志位无定义。
例3-21:假设(AL)= 0B5H,(BL)= 12H,分析下列指令的执行情况。 • MOV AL,0B5H • MUL BL • 指令执行前,(AL)= 0B5H,为无符号数181; • (BL)= 12H,为无符号数18。 • 执行指令时,字节相乘,(AL)×(BL)= 3258 = 0CBAH。 • 指令执行后,(AX)=0CBAH,OF=CF=1 例3-22:假设(AL)= 0B5H,(BL)= 12H,分析 下列指令的执行情况。 • IMUL BL • 指令执行前,(AL)= 0B5H,为带符号数-75; • (BL)= 12H,为无符号数18。 • 执行指令时,字节相乘,(AL)×(BL)= -1350 = 0FABAH。 • 指令执行后,(AX)= 0FABAH,OF=CF=1
2.带符号数乘法指令IMUL • 指令格式:IMUL src • 功能:两个带符号数相乘。 字节乘法:AX←(AL)*(src) 字乘法:DX(高字),AX(低字)←(AX)*(src) • 其他说明同MUL指令。 • 该指令只影响状态标志CF和OF,对其它标志位无定义。指 令执行后,如果乘积的高一半是低一半的符号扩展,则OF =CF=0;否则,OF=CF=1。
例3-22:假设(AL)= 0B5H,(BL)= 12H,分析下列指令的执行情况。 IMUL BL • 指令执行前,(AL)= 0B5H,为带符号数-75; • (BL)= 12H,为无符号数18。 • 执行指令时,进行字节相乘,(AL)×(BL)= -1350 = 0FABAH。 • 指令执行后,(AX)= 0FABAH,OF=CF=1
3.2.4 除法指令 • 除法指令用来实现两个二进制操作数的字节或字相除运算。根据操作数不同,又分为无符号数除法指令和带符号数除法指令。 1.无符号数除法指令DIV • 指令格式:DIV src • 功能:两个无符号数相除。 • 字节除法:AL←(AX)÷(src)的商 • AH←(AX)÷(src)的余数 • 字除法: AX←(DX,AX)÷(src)的商 • DX←(DX,AX)÷(src)的余数 • 其中:DIV为操作码助记符; src为源操作数(除数),可以是寄存器或存储单元,但 不能使用立即数或段寄存器。 • 注意:指令中只指定除数,被除数默认在寄存器AX或(DX、 AX)中。该指令对所有状态标志位无定义。
例3-23:假设(AX)=0CBAH,(BL)= 12H,分析下列指令的执行情况。 DIV BL • 指令执行前,(AX)=0CBAH,为无符号数3258; (BL)= 12H,为无符号数18。 • 执行指令时,进行字节相除,(AX)÷(BL)=3258÷18=181=0B5H,余数为0。 • 指令执行后,(AH)= 0,(AL)= 0B5H
2.带符号数除法指令IDIV • 指令格式:IDIV src • 功能:两个带符号数相除。 • 字节除法:AL←(AX)÷(src)的商 AH←(AX)÷(src)的余数 • 字除法:AX←(DX,AX)÷(src)的商 DX←(DX,AX)÷(src)的余数 • IDIV执行与DIV相同,但操作数为带符号数。相除后,商的符号与数学上规定相同,即两个同符号数相除,商为正数,两个异符号数相除,商为负数;余数与被除数同号。 • 在例3-23中,若(AX)=0CBAH,(BL)= 12H,均为带符号数,请自己分析用带符号数的除法指令执行后的结果。
3.2.5 符号扩展指令 • 在实际应用中,我们有时需要将操作数由字节型转换成字型,或由字型转换成双字型。这时不能简单地通过在高位补0的方法实现,因为带符号数在计算机中是以补码形式存放。扩展时,正数前补0,负数前全补1。为便于扩展,8086/8088提供了两条符号扩展指令CBW和CBD。
1.字节扩展指令CBW • 指令格式:CBW • 功能:将AL中数的符号位扩展到AH中。若AL中的数为正数,则(AH)=00,若AL中的数为负数,则(AH)=0FFH。 例3-24:分析下列程序段的执行过程。 MOV AL,-15 ;AL←0F1H CBW • 执行上述2条指令后,(AX)= 0FFF1H。
2.字扩展指令CWD • 指令格式:CWD • 功能:将AX中数的符号位扩展到DX中。若AX中的数为正数,则(DX)=0000,否则(DX)=0FFFFH。 例3-25:有如下程序段 • MOV DX,0 • MOV AX,0FA48H • CWD • 指令执行后,(AX)= 0FA48H,(DX)= 0FFFFH。 • 注意:以上两条指令在使用时均不带操作数,即它们只能对隐含的累加器中的内容进行操作。
例3-26:阅读程序,分析程序完成功能。 • STACK SEGMENT STACK • DB 200 DUP(?) • STACK ENDS • DATA SEGMENT • X DW 25 • Y DW 140 • Z DW 235 • BUF DW 2 DUP(0) • DATA ENDS • CODE SEGMENT • ASSUME DS:DATA , CS:CODE , SS:STACK • BEGIN: MOV AX ,DATA • MOV DS ,AX ;数据段首址送DS • MOV AX ,X • IMUL Y ;DX,AX←X*Y • MOV CX ,AX • MOV BX ,DX • MOV AX ,Z • CWD ;对Z进行符号扩展 • ADD AX ,CX • ADC DX ,BX ;DX,AX←X*Y+Z • SUB AX ,385 • SBB DX ,0 ;DX,AX←X*Y+Z-385 • IDIV X • MOV BUF , AX • MOV BUF+2 ,DX • MOV AH ,4CH • INT 21H ;程序结束 • CODE ENDS • END BEGIN