版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第3章IBMPC汇编语言程序设计3.1基本概念
3.2Intel80x86系列CPU指令系统
3.3汇编语言程序设计的基本方法
3.4汇编语言程序上机过程
小结
习题三 3.1基本概念
3.1.1汇编语言与机器语言
计算机语言是人与计算机之间传递信息的媒介,经历了从机器语言、汇编语言到高级语言的发展过程。无论哪种语言,它都规定了一系列用于编写程序的基本语句和语法规则。人们根据一种语言给定的基本语句及其语法规则可以写出程序,计算机通过执行已编好的程序来完成人们要求它完成的各种功能。汇编语言与高级语言的区别在于,汇编语言是与CPU紧密相关的,例如把针对Intel80x86系列CPU设计的汇编语言称为Intel80x86汇编语言,把针对Zilog公司生产的Z80CPU所设计的汇编语言称为Z80汇编语言。用Intel80x86汇编语言开发的程序在Z80CPU上是不能运行的,同样用Z80汇编语言开发的程序,在Intel80x86CPU上也是无法运行的。高级语言则不然,我们不把C语言命名为Intel80x86C语言或Z80C语言,这是因为用C语言开发的一个程序,在各种型号的CPU上都可以正确地运行。因此,高级语言是与CPU无关的。
那么,什么是机器语言?汇编语言与机器语言之间又有什么关系呢?下面通过一个应用实例说明机器语言和汇编语言的区别。问题:利用Intel8086CPU实现如下操作:在寄存器AX中加上一个常数2,在寄存器BX中减去一个常数3,把寄存器CX中的内容传送到寄存器DX中。
解答:针对Intel80x86CPU,解决上述问题的机器语言程序为
000001010000001000000000
100000111110101100000011
1000101111010001
针对Intel80x86CPU,解决上述问题的汇编语言程序为
ADDAX,02H
SUBBX,03H
MOVDX,CX上面两段程序实现的功能是完全相同的。显然,用汇编语言编写的程序比用机器语言编写的程序更清晰、更容易阅读和调试。
机器语言是这样一种语言,它的每条语句就是计算机可以直接执行的一条指令,这些指令以二进制码的形式表示。汇编语言的每条语句则是用一种让人容易记忆的符号表示的一条指令,这些符号必须转换成计算机所能够认识的二进制码的形式即机器语言指令之后,才能够被计算机所理解并执行。汇编语言的基本思想是采用一组字母、数字或符号来代替一条二进制码表示的指令,例如上面所述的指令000001010000001000000000,可采用字符ADDAX,02来代替,它表示将累加器AX中的内容加上一个常数02。显然,这要比一串二进制码清晰多了,既容易书写,也容易记忆。表示一条指令的这些字符常称为助记符。
必须指出,采用助记符写出的程序计算机是不能直接执行的,因为CPU在设计时是按二进制指令码考虑的。所以,采用汇编语言编写的程序在执行前还必须将其“翻译”成机器语言。通常将采用助记符写成的程序称为源程序,将它翻译生成的机器语言程序称为目标程序。将源程序翻译成目标程序的工作是由汇编程序来完成的。汇编语言中规定了两种类型的指令,即指令和伪指令。每条指令由汇编程序翻译成一组二进制代码,对应CPU的一个基本操作。伪指令则仅在汇编过程中告诉汇编程序如何汇编,例如告诉汇编程序已写出的汇编语言源程序有几个段,各段的名称是什么,汇编到某处是否需要留出存储空间,是否要用到外部变量等。指令与伪指令都是组成汇编语言源程序的基本语句。本章将逐步介绍这些内容,并在此基础上介绍汇编语言程序设计的基本方法。3.1.2汇编语言语句的组成
汇编语言源程序是由若干条语句组成的,语句则由标识符、操作助记符、操作数、注释四部分组成,如下所示:
例如:
CYCLE:ADDAX,02 ;(AX)←(AX)+02
DATA1DB20H,30H,40H,50H
1.标识符
语句中的标识符是一个统称(Identifier)。标识符又可以分为标号(Label)和名称(Name)两大类。通常把指令前的标识符称为标号,书写时在标号与指令之间加冒号;把定义数据(或变量)的伪指令和其它伪指令之前的标识符称为名称,书写时在名称与伪指令之间加空格。
标识符可由大小写英文字母、数字(0~9)及特殊符号(?、· 、@、-、$)组成。标识符必须由字母打头,若标识符中有圆点符,则圆点符必须用作第一个字符,数字不能用作第一个字符。构成标识符的字符总数可多达31个;若超过31个字符,则31个字符以后的字符无效。语句的标识符是它后面各项所在内存单元首地址的符号表示,称为符号地址。标识符不是所有语句都必需的。
2.操作助记符
操作助记符是汇编语言中规定了明确含义的一组符号,指出该语句的基本功能。每条语句都必须有操作助记符,上面例中的ADD是加法指令的助记符,DB则是定义字节变量的伪指令助记符。
3.操作数
语句中的操作数部分,可以是数据本身,也可以是指出如何获得操作数的信息。前者可以是一个常数,也可以是代表常数的一个标识符或表达式;后者通常是以某种寻址方式给出的存放操作数的地址,如上例中的第一条语句中的第一个操作数部分,它指出该操作数存放在AX中,而第二个操作数部分则为参加运算的操作数本身。操作数不是每条语句所必需的。若语句为指令,那么语句中可以没有操作数,也可以有1个或2个操作数,如上例中的第一条语句,具有2个操作数。若语句为伪指令,则可以有多个操作数。如上例中的第二条语句,具有4个操作数。当语句中具有2个以上的操作数时,操作数之间用逗号“,”分隔,操作数与操作助记符之间必须以空格分隔。
4.注释
注释仅用作语句或程序段的说明,汇编时不形成任何目标码。注释部分以分号“;”开头,表示在一行中,从“;”开始到该行末的部分不进行汇编。3.1.3常数与表达式
1.常数
常数分为数值常数和字符串常数两类。数值常数可以有二进制、八进制、十进制、十六进制等不同的表示形式,汇编语言中采用不同的后缀加以区分。
B:表示二进制数。例如,10110011B。
D:表示十进制数。例如,179D(或略去D,记为179)。
O:表示八进制数。例如,263O。
H:表示十六进制数。例如,B3H。
例中的4个数据是以不同的基数形式表示的同一个数值。当一个数值数据后面没有后缀时,将默认为十进制数。字符串常数是由单引号括起来的一串字符。例如:‘THISISASUBROUTINE’,‘179’;要指出的是,此处的‘179’其值并不表示十进数179,而是1、7、9三个数字的ASCII码,即31H、37H、39H。
最后还应指出,汇编语言中的数值常数的第一位必须是数字,否则汇编时将被看成是标识符,例如十六进制数FFH应表示成0FFH。
2.表达式
表达式由操作数和操作符组成。操作数可以是常数或标识符,也可以是表达式。操作符在汇编语言中非常丰富,包括算术操作符、逻辑操作符、关系操作符、属性操作符及其它操作符等。这里主要说明前三种操作符。
算术操作符主要有:+、-、*、/、MOD。
算术运算都是双操作数运算,操作数必须为数字操作数。取模运算(MOD)是取两数相除的余数,两操作数的值必须为正整数。例如:
79MOD16 结果为15
0B5HMOD10H 结果为5逻辑操作符有:AND(逻辑与)、OR(逻辑或)、NOT(逻辑非)、XOR(逻辑异或)。
逻辑运算的操作数的值也应为数字。汇编语言中的逻辑运算是位操作运算,运算时对应位分别进行相应运算。例如:
11001100B AND 11110000B 结果为11000000B
11001100B OR 11110000B 结果为11111100B
NOT 11110000B 结果为00001111B
11001100B XOR 11110000B 结果为00111100B值得注意的是,逻辑操作符同时又是逻辑运算指令的操作助记符,只有当它们出现在指令的操作数部分时,才是逻辑操作符。例如,指令:
ANDAL,0CHOR0FH
其中,AND是指令的操作助记符,而OR是逻辑操作符。该指令将AL中的内容与第二操作数的表达式的值(即两数相或的结果)相与,结果存放于AL中。
关系操作符有:EQ(相等)、EN(不等)、LT(小于)、GT(大于)、LE(小于或等于)、GE(大于或等于)。关系运算的操作数也必须为数字操作数。当关系成立时,其结果为真,用0FFFFH表示;当关系不成立时,其结果为假,表示为0。
汇编语言中的表达式不能构成单独语句,只能是语句的一个部分,例如:
MOVAX,BUF+2
ADDAL,VALAND0FH
JMPAGAIN+3
MOVBL,VBLEVA
语句中表达式的求值不是在执行指令时完成的,而是在对源程序进行汇编时完成的。所以,语句中各表达式的值在汇编时必须是确定的。3.1.4标号、变量及伪指令
1.标号
标号是写在指令前的标识符,表示该指令在内存中的存储地址,也称符号地址。
标号有三个属性:段地址、偏移地址和类型。标号的段地址和偏移地址是指该标号对应的指令所在段的段首址和段内的偏移地址。标号的类型属性有NEAR和FAR两种。
标号定义成NEAR类型,表示该标号在段内使用,而定义成FAR类型则表示该标号可以在段间使用。标号的定义方法是在指令的助记符前加上标识符和冒号,例如:
START:PUSHDS
这里,START为一标号,代表了指令PUSHDS所在内存单元的地址。标号可以作为程序转移指令的操作数(即要转向的地址)。不是每条指令语句前都必须有标号。
2.变量
汇编语言与高级语言一样也有变量,变量的值在程序运行期间是可以改变的。
1)变量定义
汇编语言中的变量是通过伪指令定义的,定义格式如下:
变量名DB表达式;定义字节变量(1字节)
变量名DW表达式;定义字变量(2字节)
变量名DD表达式;定义双字变量(4字节)
变量名DQ表达式;定义四字变量(8字节)
变量名DT表达式;定义一个十字节变量
变量名是一个标识符。变量名后面只能用空格。变量的类型由变量名后的关键字DB、DW、DD、DQ、DT确定,它们分别定义了单字节变量(或称字节变量)、双字节变量(或称字变量)、四字节变量(或称双字变量)、八字节变量(或称长字变量)和十字节变量。
格式中的表达式可以有下面几种情况:
(1)一个或多个常数或表达式。当为多个常数或表达式时,其间用逗号隔开。
(2)带引号的字符串,如例3.1中的变量DATA5、DATA6。
(3)一个问号‘?’,只定义一个变量,不赋初值。
(4)重复方式,此时表达式部分的格式为:重复次数DUP(表达式)。例3.1
DADA1
DB20H;
DATA2
DW0204H,1000H;
DATA3
DB(-1*3),(15/3);
DATA4
DD12345H;
DATA5
DB‘0123’;
DATA6
DW‘AB’,‘C’,‘D’
DATA7
DB?
DATA8
DD?
DATA9
DB5DUP(00)
DATA10
DW3DUP(?)上述伪指令的功能是在变量名所对应的地址开始的内存区依次存入表达式中的各项值。表达式中的每项值所占内存的字节数与变量的类型相对应,见表3.1。表3.1各变量在内存中的存放表3.1给出了例3.1中所定义的各变量在内存存放的具体形式。表3.1中最左边一列为内存区的地址。假设变量DATA1的段地址和偏移地址为0100:0000H。中间一列为对应内存单元所存放的内容,右边一列为对应的变量名。表3.1中的问号‘?’表示只分配地址,不给相应单元赋值,该内存单元中的内容是不确定的,或者说,当表达式为问号时,变量所对应的内存区在汇编过程中没有确定数值,而只留出了相应的存储空间。如表3.1中地址为0100:0015H~0100:0019H单元中仍保持内存中原来的内容,而没有送入确定的新值。重复方式指出表达式的值可以重复地存到变量对应的内存区,重复的次数由伪指令给出。当表达式的值为字符串时,对于字节类型变量,每个变量为一个字节,每个字节内存入一个字符的ASCII码,整个字符串可以在同一个引号内给出。对于字类型变量,每个变量的值不能超过2个字符,若为2个字符时同样遵循高位存入高字节,低位存入低字节的规则;若为1个字符时,该字符的ASCII码存入低字节,高字节为00。对于双字长字类型变量,每个变量的值也不能超过2个字符并存入2个低位字节。
2)变量的属性
变量具有下列属性:
(1)段地址(SEG):变量所在段的首地址。
(2)偏移地址(OFFSET):变量相对于所在段首地址的地址偏移。
(3)类型(TYPE):变量的类型是所定义的每个变量所占据的字节数,对于DB、DW、DD、DQ、DT定义的变量,其类型值分别为1、2、4、8、10。通常又将DB、DW、DD所定义的变量分别称为BYTE类型、WORD类型、DWORD类型的变量。
(4)长度(LENGTH):变量定义时,一个变量名所定义的变量个数。在含有DUP操作符的变量定义中,变量名所定义的变量个数为定义格式中的重复次数。在其它各种变量定义中,每个变量名所定义的变量个数均为1。
(5)大小(SIZE):变量定义语句中,分配给同一变量名的所有变量的总的字节数,其值为该变量的类型与长度的乘积。
例3.1中所定义的部分变量的属性值列于表3.2中。表3.2部分变量的属性3.1.5属性操作符及表达式
前面我们已介绍了几种操作符及其表达式,这些操作符的操作对象都是数值数据。下面我们将介绍用来获取属性或重新定义某种属性的操作符,称其为属性操作符。对应这样的操作符,也有其相应的表达式。
1.获取属性的操作符
标号或变量一旦定义,它们都具有相应的属性,获取属性的操作符及其表达式列于表3.3中。表3.3操作符及其表达式例如对表3.1中所定义的各变量,有:
SEGDATA1 ;结果为0100H
OFFSETDATA1 ;结果为0000
LENGTHDATA6 ;结果为1
TYPEDATA6 ;结果为2
SIZEDATA9 ;结果为5
这些表达式与上面提到的运算表达式一样,不能构成单独的语句,只能是语句的一个成分,并且表达式的求值也是在汇编过程中完成的。有如下的变量定义:
DAT1DB 02H
DAT2DW 0F00H
DAT3DW 5DUP(?)
DAT4DB LENGTHDAT3
DAT5DW DAT3
经汇编以后,DAT4对应的内存单元中存放的是变量DAT3的长度(即5),DAT5所对应的2个字节中存放的将是变量DAT3的偏移地址。
2. PTR操作符
格式:类型PTR表达式
格式中的类型可以是:BYTE、WORD、DWORD、NEAR和FAR。前三个类型为变量类型,后两个为标号类型。格式中的表达式可以是变量名、标号或其它地址表达式。
PTR操作符的功能是用来重新定义已定义的变量或标号的类型。例如上例中的变量DAT3是字变量,若程序中需将它作为字节变量使用时,必须用PTR操作来重新定义其类型。可以有
MOVBYTEPTRDAT3,AL这里将DAT3重新定义为字节类型。 整个语句的功能将是AL中的内容送到DAT3对应的一个字节中。要指出的是变量DAT3仅在该语句中作为字节变量使用,DAT3原来定义的字变量类型并没有修改。 3.2Intel80x86系列CPU指令系统
CPU的指令系统是指该CPU所有机器指令的集合,它是在CPU设计时就确定了的。指令系统是表征一种CPU性能的重要因素。 不同CPU的指令系统中所包含的指令是不相同的。习惯上将美国Intel公司设计生产的8086系列CPU统称为Intel80x86CPU,包括早期的8088、8086、80286、80386、80486及最新的奔腾CPU。Intel80x86系列CPU采用了软硬件兼容的设计思想,即最新设计的CPU在指令系统和硬件资源方面兼容以前生产的CPU。最早设计的8086CPU的指令系统构成了Intel80x86系列CPU指令系统的基本核心,后续推出的各种CPU的指令系统,如80386、80486及最新的奔腾CPU等,都包含了8086指令系统,并在此基础上进行了扩展。按照功能可将80x86指令分成下面几类:
(1)数据传送指令;
(2)算术运算指令;
(3)逻辑运算指令;
(4)移位指令;
(5)标志处理指令和CPU控制指令;
(6)转移和循环控制指令;
(7)调用和返回指令;
(8)字符串操作指令;
(9)输入、输出指令。对于指令系统的介绍,重点将放在各条指令的功能和它们的使用上。学习指令系统着重要掌握指令的基本操作功能、合法的寻址方式以及对标志位的影响。本书中描述指令操作时用到的各种缩写和符号列于表3.4中。表3.4缩 写 与 符 号3.2.1数据传送类指令
数据传送指令负责把数据、地址或立即数送到寄存器或存储单元中,指令基本格式及功能说明见表3.5。表中除了SAHF和POPF指令外,标志寄存器F的各位均不受影响。指令中出现两个操作数时,目的操作数在前,源操作数在后,并且目的操作数不能为立即数和段寄存器CS。表3.5数据传送类指令的格式与功能
1.通用传送指令(MOV)
格式:MOVDST,SRC
执行操作:(DST)←(SRC)
功能:将操作数从SRC传输到DST。
源操作数可以是通用寄存器、段寄存器、立即数和内存单元;目的操作数可以是通用寄存器、段寄存器和内存单元,但不能为立即数和CS。内存单元可以通过第2章所指出的各种寻址方式寻址。当目的操作数为段寄存器时,源操作数不能为立即数;当源操作数不是立即数时,两个操作数中必须有一个是寄存器。例如:上述指令都是合法的。前两条指令的源操作数与目的操作数的寻址方式均为寄存器寻址方式;第3条指令的目的操作数仍为寄存器寻址方式,而源操作数的寻址方式则为立即数方式;第4条指令的源操作数为寄存器间接寻址,源操作数的有效地址为BX的内容即EA=(BX),因而指令的功能是将EA所对应单元中的一个字送入SI。
下面着重说明后面三条指令的寻址方式和传送过程。
1) MOVAL,4[DI]
该指令的源操作数为寄存器相对寻址方式,或称变址寻址方式,其有效地址EA=(DI)+4,EA即为源操作数在段内的偏移地址。 指令的功能是将有效地址EA所对应的单元中的一个字节送入AL中,当(DI)=0400H时,该指令执行后,AL中的内容为0AH。指令的传送过程见图3.1(a)。图3.1指令的传送过程(a) MOVAL,4[DI]传送过程;(b) MOVAX,[BX+2]传送过程;(c) MOV[BX][DI],DX传送过程
2) MOVAX,[BX+2]
该指令的源操作数的寻址方式也为寄存器相对寻址方式(或称基址寻址方式),其有效地址EA=(BX)+2,当(BX)=1000H时,那么,EA=1002H,指令的功能是将EA所对应单元中的一个字送入AX。由于一个字的数据在内存占据两个字节单元,所以,该指令完成的传送应为(EA)→(AL),(EA+1)→(AH),传送过程见图3.1(b)。
3) MOV[BX][DI],DX
该指令的源操作数的寻址方式为寄存器方式,目的操作数的寻址方式为基址变址寻址方式,其有效地址EA=(BX)+(DI)。指令的功能是将DX中的16位数送入有效地址EA所指的2个字节单元中,具体过程应为(DL)→(EA),(DH)→(EA+1)。传送过程见图3.1(c)。
当程序中采用伪指令定义了一组变量后,传送指令可以有下面的形式:上述传送指令都是合法的。第1条指令的源操作数和第2条指令的目的操作数的寻址方式为直接寻址方式,其有效地址EA即为变量DATA1和DATA3的偏移地址,可以表示为EA=OFFSETDATA1和EA=OFFSETDATA3。所以第1条指令的功能是将变量DATA1对应地址单元中的一个字送入AX,故(AX)=0020H。第3条指令的源操作数和第4条指令的目的操作数的寻址方式为寄存器相对寻址方式,其有效地址分别为EA=(DI)+ OFFSETDATA2和EA=(SI)+OFFSETDATA3,即将变址寄存器的内容加上变量DATA1或DATA3的偏移地址。若(DI)=1,(SI)=0,(DX)=103FH,那么,执行第3条指令后,(AL)=60H,第4条指令执行后偏移地址为DATA3的内存单元内容为3FH,下一单元的内容为10H。第5条指令采用了表达式LENGTHDATA3,即取变量DATA3的长度,由于变量定义时DATA3分配了10H个字变量空间,所以,该指令执行后,(CX)=10H。第6条指令取的是变量DATA3所占的字节数,所以,指令执行后(BX)=20H。第7条指令用了操作符OFFSET,它是将DATA2的偏移地址送入SI。最后3条指令的寻址方式均属于立即数寻址方式,因为在汇编后,源操作数已是已知的确定数值了。指令中传送的是一个字还是一个字节,通常由操作数的类型确定。当操作数是寄存器时,那么,16位寄存器将指出该操作数为字类型,8位寄存器则指出对应的操作数为字节类型,若操作数是某种寻址方式所指出的内存单元时,那么,相应的操作数的类型有时是明确的,而有时可能是不明确的。如下面3条指令:
MOVDATA3[SI],02
MOV2[SI],AL
MOV4[DI],02上述指令中的目的操作数均为寄存器相对寻址方式所指的内存某单元,第1条指令的目的操作数的类型将取决于变量DATA3的类型,只要变量DATA3已定义,其类型是明确的,而后两条指令的目的操作数的类型就不明确了,但因第2条指令的源操作数的类型是明确的,从而指令属于字节传送。第3条指令因源操作数与目的操作数的类型均不明确,因而为非法指令,此时,必须用前面介绍的PTR操作符来指明其操作类型,格式如下:
MOVBYTEPTR4[DI],02
这样就指出了指令为字节操作。此外,传送指令的两个操作数的类型必须一致,否则,指令将为非法指令。对于通用传送类指令,应着重掌握的是进行传送的两个操作数的寻址方式及其书写格式,也就是传送数据的两个操作数的有效地址以什么方式获得,并在指令中如何表示。这些寻址方式及其书写格式不仅适用于传送类指令,同样也适用于其它各类指令。下面对通用传送指令中与寻址方式有关的内容归纳如下:
(1)两操作数进行数据传送的正常通路如图3.2所示。图中的箭头指出了两者之间可以进行数据传送的方向。例如存储器与寄存器AX、BX、CX、DX、DI、SI、SP、BP之间可以双向传送,而存储器与段寄存器CS之间只能单向传送。图3.2数据传送的正常通路
(2)寄存器间接寻址、寄存器相对寻址、基址变址寻址和基址变址相对寻址方式中所用到的寄存器不能是数据寄存器AX、CX和DX,只能使用变址寄存器DI、SI和基址寄存器BX、BP。
(3)寄存器相对寻址和寄存器基址变址相对寻址方式中的位移量DISP可以是常量,也可以是变量,并且可以有多种书写格式。下面以寄存器相对寻址为例,给出几种可用的书写格式:
MOVAX,DISP[BX]
MOVAX,[BX+DISP]
MOVAX,[BX].DISP
MOVAX,[BX]+DISP
上述4条指令的功能是完全一样的,源操作数的有效地址均为EA=(BX)+DISP。指令中的寄存器BX也可以是其它的基址、变址寄存器。按某种寻址方式计算得到的有效地址是段内的偏移地址,对于某存储单元的完整地址还应包括其段地址,段地址则在相应的段寄存器中。数据段的段地址在DS中,在执行上述指令之前,首先必须通过传送指令将段地址送入段寄存器DS中。例如可以采用下面两条传送指令:
MOVAX,SEGDATA1 ;将变量DATA1的段地址送入AX
MOVDS,AX若程序中所用的数据段的段址寄存器不是DS,而是ES,那么,指令中必须用段前缀加以说明,其格式为
MOVAX,ES:[SI]
它告诉汇编程序,这条指令中要取的数据的段址在ES中,而不在DS中,汇编后形成的机器指令也增加一个前缀字节,以说明所用的段寄存器。
2.取有效地址指令(LEA)
格式:LEAREG,SRC
执行操作:(REG)←SRC
功能:将源操作数SRC的有效地址(偏移地址)送入寄存器REG中。
这里的REG不允许是段寄存器,源操作数的寻址方式不允许是立即数和寄存器方式。这是一条特殊指令,它传送的不是操作数本身,而是操作数的有效地址。为说明问题,比较下面两行指令执行的结果:
MOVAX,10H[DI]
LEAAX,10H[DI]假设(DI)=0500H,(DS)=0200H,对应内存单元的内容如图3.3所示。那么,第一条指令执行后,AX的内容为(AX)
=00FFH,它是将0200H段中的偏移地址为0510H处的16位数送入AX。第二条指令执行后,AX的内容为(AX)=0510H,也即将源操作数的有效地址的偏移地址送入了AX。
取有效地址指令也可以有下面的形式:
LEADI,DATA1
LEABX,AGAIN指令中的DATA1及AGAIN可以是已定义的变量,也可以是程序中的语句标号,不论是变量还是标号,它们都有段和偏移地址的属性。在该指令中,它们将取变量或标号的偏移地址送入相应的寄存器。所以,下面两条指令是完全等效的:
MOVAX,OFFSETDATA1
LEAAX,DATA1图3.3内存单元的内容
3.取地址指针指令(LDS,LES)
格式:LDSREG,SRC
LESREG,SRC
执行操作:(REG)←(SRC),(SREG)←(SRC+2)
功能: 该指令的功能是将源操作数SRC的有效地址所对应的内存单元中的32位内容分别送入DS(或ES)和指令中所指出的寄存器REG中。同样,这里的REG不允许为段寄存器,源操作数的寻址方式不允许是立即数和寄存器方式。可以有下面的变量定义和指令:
TABLEDB10H,20H,30H,40H,50H
POINT1DD02001000H
POINT2DDTABLE
…
LDSDI,POINT1
LESSI,POINT2指令LDSDI,POINT1执行后,(DI)=1000H,(DS)=0200H;指令LESSI,POINT2执行后,(SI)=OFFSETTABLE,(ES)=SEGTABLE。需要指出的是,汇编后双字变量POINT2中的32位内容将是变量TABLE的32位地址,其高16位是TABLE的段地址,低16位是TABLE的偏移地址,这正是双字变量的一种重要用途。上面两条指令的源操作数的寻址方式为直接寻址方式,也可采用其它寻址方式,但不同寻址方式所指的内存单元都应是双字类型。
4.标志传送指令(LAHF,SAHF)
CPU中有一标志寄存器FLAG,其中的每一位标志了CPU的一种状态。许多指令的执行结果会影响标志寄存器中的某些位,同时,有些指令的执行也受标志寄存器中的某些位控制。标志寄存器的内容与指令的执行有着密切的关系。现在介绍的两条指令实现标志寄存器中的低8位与寄存器AH之间的传送。
格式:LAHF
SAHF功能:LAHF是将标志寄存器中的低8位内容送入寄存器AH,SAHF是将AH中的8位内容送入标志寄存器的低8位中。显然,SAHF指令可以同时改变标志寄存器FLAG的低8位中的各位的值。
5.数据交换指令(XCHG)
格式:XCHGOPR1,OPR2
执行操作:(OPR1)←→ (OPR2)
功能:完成寄存器与寄存器或寄存器与存储单元之间的内容交换。该指令要求两个操作数之一必须是寄存器,允许两个操作数都是寄存器,但不允许是段寄存器。例如:
XCHGAX,BX;(AX)←→ (BX)
XCHGCX,[DI];(CX)←→ ([DI])
XCHGBX,DATA1上述指令都是合法的,其中第2条指令和第3条指令完成的是寄存器与内存单元的内容交换。第2条指令源操作数为寄存器间接寻址,即由DI的内容指明了要交换的内存单元的偏移地址。第3条指令的源操作数为直接寻址,DATA1是已定义的变量,DATA1的偏移地址直接指明了要交换数据的内存单元的偏移地址。
6.字节转换指令(XLAT)
格式:XLAT
执行操作:(AL)←((BX)+(AL))
功能:该指令的寻址方式是隐含的,其有效地址EA=(BX)+(AL)。指令的功能是将EA所对应的内存单元中的一个字节送入AL中。
该指令可用于两种代码的转换,例如要将表3.6中的代码CODE1转换成代码CODE2,只要将表中的代码CODE2依次存入地址连续的内存单元中,如表3.7所示,那么,若将其首地址TABLE送入BX,将需要转换的一个CODE1的代码送入AL,执行XLAT指令后,AL中便是对应的CODE2的代码了。例如,求CODE1代码中的5所对应的CODE2代码,可以用下面的程序段:
MOVAX,SEGTABLE
MOVDS,AX
MOVBX,OFFSETTABLE
MOVAL,05
XLAT
该程序段执行后,(AL)=35H。表3.6代码转换表3.7内存单元
7.堆栈操作指令
1)堆栈
堆栈是以后进先出(LIFO)的规则存取信息的一种存储机构。在PC机中,堆栈通常是存储器的一部分。为了保证堆栈区的存储器能按后进先出的规则存取信息,该存储区的存取地址由一个专门的地址寄存器来管理,这个地址寄存器称为堆栈指示器或称堆栈指针SP。当信息存入堆栈(通常称为进栈)时,堆栈指针将自动减量并将信息存入堆栈指针所指出的存储单元,当需要从堆栈中取出信息(通常称为出栈)时,也将从堆栈指针所指出的存储单元中读取信息,并自动将堆栈指针增量。所以,堆栈指针始终指向堆栈中最后存入信息的那个单元,我们称该单元为堆栈顶。在信息的存与取的过程中,栈顶是不断移动的,也称它为堆栈区的动端,而堆栈区的另一端则是固定不变的,这端被称为栈底。堆栈指针寄存器用来存放堆栈区的偏移地址,当堆栈地址长度为16位时,用SP作为堆栈指针寄存器,当堆栈地址长度为32位时(80386及其后继机型)用ESP。堆栈区的段地址则存于段寄存器SS中。SP或ESP的内容在任何时刻都指向栈顶。堆栈的存取在16位指令中必须以字为单位(不允许字节堆栈),在32位指令中必须以双字为单位。
在程序设计中,堆栈是十分有用的一种结构。后面要介绍的子程序的调用与返回都将离不开堆栈。此外,堆栈还可以用来保存程序中的某些信息,这些信息需要以后进先出的规则存取。在输入输出系统中,中断响应和返回的正确操作也必须由堆栈来保证。
2)堆栈操作指令
堆栈的主要操作是对堆栈进行信息的存取,将信息送入堆栈的过程称为进栈操作,从堆栈中取出信息的过程称为出栈操作。指令的助记符及功能说明见表3.5。
(1)进栈指令(PUSH)。
格式:PUSHSRC
执行操作:(SP)←(SP)-2,((SP)+1,(SP))←(SRC)上述都是合法指令。第1条指令是将AX中的内容送入堆栈。首先,SP内容减2,然后,将AL的内容送入SP所指单元,AH的内容送入(SP)+1所指单元。第2条指令是将段寄存器的16位内容送入堆栈,并修正SP内容。第3条指令是将内存某单元的16位内容送入堆栈。同样,首先将SP内容减2,然后,将(SI)所指单元的8位内容送入(SP)所指单元,((SI)+1)所指单元的8位内容送入((SP)+1)所指单元。 最后一条指令是将标志寄存器的内容压入堆栈,其过程与上面相同,其低位送入低字节,高位送入高字节。应注意的是,进栈指令不能将一个常数压入堆栈,若需要将一常数送入堆栈,必须通过寄存器来实现。例如:
MOVAX,0FFFFH
PUSHAX
(2)出栈指令(POP)。
格式:POPDST
执行操作:(DST)←((SP)+1,(SP)),(SP)←(SP)+2
功能:将SP所指出的栈顶的内容取出,并送入DST所指寄存器、内存某单元或标志寄存器FLAG,并修正SP内容。
DST也必须为字类型,它可以是通用寄存器和除了CS以外的段寄存器,也可以是某种寻址方式所指的内存单元,但不能为立即数。指令POP DST对标志位不产生影响。由于SP所指的就是堆栈中最后存入信息的单元,弹出指令正是弹出该单元的内容,所以,执行POP指令时先弹出栈顶内容,后修正SP的内容,并且SP以加2修正。若有下面的程序段:
MOVSP,0100H
PUSHAX
PUSHBX
POPAX
POPBX
则程序执行后,SP将仍指向0100H单元,即(SP)=0100H,而寄存器AX,BX的内容进行了交换。这告诉我们,程序中的PUSH指令与POP指令若成对出现,那么,程序执行后,堆栈指针将保持程序执行前的内容,或者说栈顶位置保持不变。
8.符号扩展传输和零扩展传输指令(80386及以后微处理器)
1) MOVSX带符号扩展传送指令
格式:MOVSX DST,SRC
执行操作:(DST)←符号扩展(SRC)
该指令的源操作数可以是8位或16位的寄存器或存储单元的内容,而目的操作数则必须是16位或32位寄存器,传送时把源操作数进行符号扩展,即将SRC内容送入DST的低位,用SRC的符号位填充DST的高位。可以是8位符号扩展到16位,也可是16位符号扩展到32位。MOVSX不影响标志位。
2) MOVZX带零扩展传送指令
格式:MOVZX DST,SRC
执行操作:(DST)←零扩展(SRC)
该指令的源操作数可以是8位或16位的寄存器或存储单元的内容,而目的操作数则必须是16位或32位寄存器,传送时把源操作数进行零扩展,即将SRC内容送入DST的低位,用0填充DST的高位。可以是8位符号扩展到16位,也可是16位符号扩展到32位。MOVSX不影响标志位。3.2.2算术运算类指令
1.加法与减法指令
加法与减法指令的助记符格式及其功能说明见表3.8。指令中参加运算的两个操作数一个称为目的操作数(DST),一个为源操作数(SRC),运算结束后,目的操作数被运算结果所代替,源操作数保持不变。加、减法指令对标志寄存器的各位均有影响。表3.8加法与减法指令的助记符与功能指令中两操作数可以采用多种寻址方式。源操作数可以为立即数、通用寄存器和任一寻址方式所指定的内存单元。目的操作数可以为通用寄存器和任一寻址方式所指定的内存单元,但不允许是立即数。当源操作数不是立即数时,两个操作数中必须有一个是寄存器。例如下面的指令都是合法的:上述指令中,第1条与第5条指令为8位数运算指令,其余均为16位数运算指令。无论是8位数运算还是16位数运算,两个操作数的类型必须一致,否则为非法指令。如上面的最后一条指令,变量DATA1必须是字变量,否则将因类型不一致而非法。
上述指令中的最后两条指令是带进位的加、减运算,即在运算时,除了完成指令所指出的两个操作数的加、减运算外,还必须考虑进位(或借位)标志CF的当前状态。对于ADC指令,则在实现两操作数的加法运算基础上应加上CF的当前值;对于SBB指令,则在实现两操作数的相减运算的基础上还应减去CF的当前值。应该注意,CF的当前值是由程序中本指令之前的指令产生的。下面分析两条指令的执行结果,以说明指令的功能。
1) ADDAX,[SI]
该指令为16位数加法指令,目的操作数的寻址方式为寄存器方式,源操作数的寻址方式为寄存器间接方式,其功能是将AX的内容与寄存器SI的内容所指的内存单元中的16位数相加,结果送入AX,并设置标志寄存器FLAG各位。执行过程见图3.4。
本节所讨论的指令对标志寄存器中DF、IF、TF均不产生影响。
CF作为进位(或借位)标志时是对无符号数而言的, 而OF作为溢出标志是对带符号数而言的。不论是无符号数还是带符号数,在执行指令时的运算是完全一样的,包括对标志位的影响也没有区别。图3.4ADDAX,[SI]执行过程
2) SBBCX,DATA1
该指令为带借位的16位数减法指令,目的操作数的寻址方式为寄存器方式,源操作数的寻址方式为直接方式。其功能是CX中的16位数减去变量DATA1对应的内存单元中的16位数及标志寄存器中CF的当前值,相减后的差值送寄存器CX,并设置标志寄存器FLAG的各位。执行过程见图3.5。图3.5SBBCX,DATA1执行过程图3.5中指出,指令执行前(CX)=3F50H,变量DATA1在数据段内的偏移地址为0006H,对应单元中的16位数为1728H,借位标志(CF)=1。指令执行后其结果如下:
在减法指令中,标志位CF和AF分别为最高位和第3位向高位的借位,其余各位的含义与加法指令相同。由于SBB指令是一条带借位的减法指令,因此,应注意该指令执行前借位标志的当前值。对于ADC指令有相同的情况。
带进位的加、减法指令主要用于多位数的加、减运算。例如在内存中偏移地址为ADR1开始的连续单元中存放着两个4字节操作数A和B,求该两数之和C,并将结果存放于偏移地址为ADR2开始的连续单元中,如图3.6所示。在8086指令系统中,加法指令只能完成两个8位数相加或两个16位数相加,如要完成32位数(4个字节)的相加,必须分两步实现。首先完成低16位数的相加,并保存所得的和与进位值,然后再完成高16位数的相加,并加上低16位数相加时可能产生的进位。这样,32位数的相加就完成了。在此基础上,可以实现更多位数的相加运算。对于80386及其后继机型,32位的加法和减法运算则可以直接用一条ADD或SUB指令完成。图3.6多位数的加法
2.比较指令
格式:CMPDST,SRC
执行操作:(DST)-(SRC),根据结果设置标志位
功能:目的操作数减去源操作数,并根据相减结果置各标志位。指令中两操作数的寻址方式与加、减法指令的寻址方式相同。它与减法指令不同的是所产生的两数之差并不取代目的操作数,因而指令执行后,仅仅改变了标志寄存器的内容,两操作数的值保持不变。指令中两操作数的类型必须一致。比较指令可以有如下的形式:
CMPAL,BL
CMPAL,[DI]
CMPAX,CX
CMPAX,06H
上述指令都是合法的,前两条指令为8位数比较指令,后两条指令为16位数比较指令。
比较指令执行后的结果仅仅体现在标志寄存器中,它是为后面的具有判别功能的指令提供条件的。
3.增量和减量指令
指令助记符格式及其功能说明见表3.9。两条指令均为单操作数指令,操作数的寻址方式可采用除立即数外的各种寻址方式,但不能是段寄存器。指令的功能是对目的操作数加1或减1。指令除对进位标志CF不影响外,其余标志都受影响。表3.9增量和减量指令助记符与功能有下面的合法指令:
INCAL ;(AL)←(AL)+1
INCBX ;(BX)←(BX)+1
INCWORDPTR4[BX] ;((BX)+4)←((BX)+4)+1
DECCX ;(CX)←(CX)-1
指令可以为字操作和字节操作两种,指令中还必须明确其操作类型。如上面的第3条指令必须用PTR操作符指出指令要对内存中的一个16位数加1,而不是对8位数加1。
4.乘法与除法指令
指令助记符格式及其功能说明见表3.10。表3.10乘法和除法指令助记符与功能乘除法指令分带符号运算和不带符号运算两种。带符号运算时,操作数和结果均以补码表示。
乘法指令中的目的操作数的寻址方式是隐含的,并且一定是累加器AX或AL。源操作数的寻址方式可采用除立即数以外的各种寻址方式,但不能是段寄存器。
指令是字运算还是字节运算由源操作数的类型确定。当字运算时,目的操作数为AX,相乘后的32位结果送DX:AX,DX中为高16位,AX中为低16位。当字节运算时,目的操作数为AL,相乘后的16位结果送AX。乘法指令执行后,标志寄存器中只有CF和OF位有意义,其它各位的值均为不确定。对于MUL指令,若相乘后的结果中高16位(字运算)或高8位(字节运算)均为0,则CF和OF被置为0,否则CF和OF被置为1。对于IMUL指令,若相乘后的结果中高16位或高8位为低16位或低8位的符号扩展,则CF和OF被置为0,否则CF和OF被置为1。所以,标志位CF和OF可用来判断相乘的结果中高位字或高位字节是否有值。下面的乘法指令均是合法的:
MULDAT1 ;(DX:AX)←(AX)*(DAT1)
IMULCL ;(AX)←(AL)*(CL)
MULBYTEPTR[BX] ;(AX)←(AL)*([BX])
上述指令中的第1条指令的操作类型由变量DAT1确定,由指令的注释可以看出,DAT1一定是字变量。第2条指令的操作类型是明显的,即为字节操作。第3条指令的源操作数在BX所指出的内存某单元中,此时必须用PTR操作符来明确源操作数的类型,否则指令将为非法。
5.符号扩展指令
有时会遇到两个长度不等的数进行加、减法运算,此时,应将长度短的数的位数扩展,以使两数的长度一致,只有这样,才能保证参加运算的两个操作数的类型是一致的。此外,除法指令中的被除数必须放在AX或DX:AX中,因此有时也需要将一个8位或16位数进行扩展。对于一个无符号数来说,这种扩展是简单的,只要将其高位补“0”就可以,但对一个带符号数来说就不一样了,扩展时高位补“0”还是补“1”,取决于被扩展数的符号位,也就是说,当被扩展数是正数时高位应补“0”,为负数时高位应补“1”。表3.11中的两条指令就是实现带符号数扩展功能的。它们都是单操作数指令,其寻址方式是隐含的,并且一定为AL或AX。
指令CBW是将AL中的一个字节扩展成AX中的一个字,扩展后AH中的内容与AL中的最高位(符号位)一致。指令CWD是将AX中的一个字扩展成DX:AX中的一个双字,扩展后DX中的内容与AX中的最高位一致。例如,AL中的内容为0F2H,那么执行指令CBW后AX中的内容将为0FFF2H。显然,扩展前后的两个数都是-0EH的补码。表3.11符号扩展指令助记符与功能
6. BCD数调整指令
指令助记符格式及其功能列于表3.12中。指令的操作数均为隐含寻址,并且为AL或AX。表3.12BCD数调整指令助记符与功能
BCD数是用4位二进制码表示的一位十进制数。在计算机中,所有运算均以二进制运算为基础,要实现对BCD数进行十进制运算,通常分两步进行,首先对BCD数按二进制进行运算,然后对运算结果进行相应的调整。本书对本组指令不加详细说明,读者如有需要,请查阅相关手册。
3.2.3逻辑运算类指令
逻辑运算指令的格式及功能说明列于表3.13。表3.13逻辑运算指令格式与功能指令中源操作数可以为立即数、通用寄存器和任一寻址方式所指定的内存单元。目的操作数可以为通用寄存器和任一寻址方式所指定的内存单元,但不允许是立即数,当源操作数不是立即数时,两个操作数中必须有一个是寄存器。
指令的运算都是按位进行的。NOT指令是将操作数的各位取反,其它指令则是两个操作数的对应位执行相应的逻辑运算。指令可以是字节操作,也可以是字操作。除了NOT指令对标志位不产生影响外,其余指令将使CF、OF置0,并以正常规则设置SF、ZF和PF的状态。例如:表3.14指令及执行后的结果表3.14中结果项给出了指令执行后,标志寄存器的各位以及有关寄存器和变量对应单元的内容。累加器AX的内容包含了高8位(AH)的内容和低8位(AL)的内容两部分,对于与AL有关的字节操作指令,AH的内容将不受影响。对字节操作指令,标志位的设置也按相应字节的结果考虑,例如表3.14第5条指令执行后,AL的内容为A5H,此时的SF=1而不是0。
TEST指令与AND指令的区别类似于CMP指令与SUB指令的区别。TEST指令的结果只体现在对标志位的影响上,并不改变原目的操作数的值。AND指令则不同,除对标志位有影响外,相与后的结果将取代目的操作数的原来值。3.2.4移位指令和循环移位指令
表3.15中给出了移位指令和循环移位指令的指令格式和功能说明。表3.15移位、循环移位指令格式与功能指令的功能是将DST所指出的操作数的各位左移或右移若干位,移位的次数由CNT确定。
指令中的目的操作数的寻址方式可以是除立即数外的各种寻址方式,但不能是段寄存器。CNT可以是立即数或寄存器CL。当CNT为立即数时,其值只能为1;当移位次数超过1时,CNT应为寄存器CL,CL中的内容为移位次数。
左移指令,即表中的SHL/SAL指令,移位时操作数的最低位将移入0,而最高位移入CF中;若左移若干位,那么CF中只保留最后一次移出的内容。右移指令有两种情况:①即表中的SHR指令,称逻辑右移指令,移位时操作数的最高位将移入0,最低位移入CF中;②即表中的SAR指令,称算术左移指令,移位时操作数的最高位移入的是它原来的值,即最高位保持不变,最低位同样移入CF中。算术右移主要用于带符号数的右移。同样,若右移若干位,那么CF中只保留最后一次移出的内容。
循环移位指令,即表中的后面4条指令,它们是将操作数本身或者操作数与CF一起构成一个环形移位,移位的次数也由CNT确定。同样,若移位若干次,CF中只保留最后一次移出的内容。移位指令与循环移位指令对标志位的影响是不一样的,移位指令将影响除AF外的各标志位,AF的内容为不定。循环移位指令只影响标志位CF和OF。不论是移位指令还是循环移位指令,只有当CNT的值为1时,OF才有意义,并且OF的设置规则为:当操作数的高位在移位前后不发生变化时OF=0,否则OF=1。例如,可以有如下的移位指令:
SHRAX,1 ;将AX的内容右移1位,最高位补0
SALAL,CL ;将AL的内容左移CL中指出的位数,且每次移位最低位补0
ROLDAT1[SI],CL;将内存某单元的内容循环左移CL中所指的位数
例中的第3条指令的目的操作数的寻址方式为寄存器相对寻址, DAT1是已定义的变量,该指令实现对有效地址EA=DAT1的偏移地址+(SI)所指单元的内容循环左移,移位次数由CL中的内容决定。3.2.5位测试指令
386及其后继机型增加了本组指令。
1. BT位测试指令
格式:BTDST,SRC
执行操作:把目的操作数中右源操作数指定位的值(0或1)送往标志位CF。
2. BTS位测试指令并置1指令
格式:BTSDST,SRC
执行操作:把目的操作数中右源操作数指定位的值(0或1)送往标志位CF,并将目的操作数中的该位置1。
3. BTR位测试指令并置0指令
格式:BTRDST,SRC
执行操作:把目的操作数中右源操作数指定位的值(0或1)送往标志位CF,并将目的操作数中的该位置0。
4. BTC位测试指令并取反指令
格式:BTCDST,SRC
执行操作:把目的操作数中右源操作数指定位的值(0或1)送往标志位CF,并将目的操作数中的该位取反。
5. BSF正向位扫描指令
格式:BSFREG,SRC
执行操作:从位0开始,自右向左扫描源操作数,检测第一个为1的位。如遇到第一个为1的位,则将该位的位位置装入目的寄存器REG,并将ZF置0;若源操作数为0,则目的寄存器无定义,并将ZF置1。
6. BSR反向位扫描指令
格式:BSRREG,SRC
执行操作:从最高有效位开始,自左向右扫描源操作数,检测第一个为1的位。如遇到第一个为1的位,则将该位的位位置装入目的寄存器REG,并将ZF置0;若源操作数为0,则目的寄存器无定义,并将ZF置1。3.2.6处理器控制指令与标志处理指令
表3.16给出了处理器控制指令与标志处理指令的格式及主要功能说明。表中的前7条指令分别是对状态寄存器的CF、DF、IF置位、复位或取反的。这些指令功能比较简单,这里不作更多说明。表3.16控制指令与标志处理指令格式及功能
1. NOP指令
CPU执行该指令时,不完成任何具体功能,也不影响标志位,只占用机器的3个时钟周期。所以,NOP指令也称为空操作指令。
2. HLT指令
该指令使CPU进入暂停状态。只有当下面三种情况之一发生时,CPU才退出暂停状态:CPU的复位输入端RESET线上有复位信号;非屏蔽中断请求输入端NMI线上出现请求信号;可屏蔽中断输入端INTR线上出现了请求信号且标志寄存器的中断标志IF=1。
3. WAIT指令
CPU执行该指令时,测试CPU的引线。当线为高电平时,CPU进入等待状态,且每隔3个时钟周期对的状态进行一次测试,直到引线出现低电平时,CPU退出等待,顺序执行下一条指令。
4. LOCK指令
这是一条前缀指令,可放在任何指令的前面,使得相应指令执行时,总线被锁定,使别的主设备不能使用总线。本指令不影响标志位。
5. ESC指令
指令格式:ESCDATA,SRC
这条指令主要用于CPU与外部处理器(如协处理器8087)配合工作。CPU执行该指令时,相应的协处理器应配合工作。SRC将指出送给协处理器的操作数。DATA是一个事先规定的6位立即数,执行ESC指令时,利用这6位数控制外部处理器完成预定操作。
表3.16中的后两条指令主要用于多处理器配合工作,相关内容超出本书知识范畴,不作详细说明。
3.3汇编语言程序设计的基本方法
3.3.1汇编语言程序设计的基本步骤
1.分析问题
首先必须明确求解问题的意义和任务,明确所要解决的问题的物理过程及其工作状态、输入信息的形式和种类、要求输出什么样的信息,等等。经过详细了解和分析,将一个实际问题转化为一个计算机可以处理的问题。
2.确定算法
所谓算法,简单地说就是计算机能够实现的有限的解题步骤。我们知道,计算机只能进行最基本的算术运算和逻辑运算,要完成较为复杂的运算和控制操作,必须选择合适的算法,这是正确编程的基础。
算法可以用自然语言、类程序设计语言(也称半自然语言)或流程框图来描述。本书将主要采用流程图描述。图3.7给出了流程图中较为通用的几种符号。
(1)起始和终止框是表示程序开始和结束的符号,它总是在一个流程框图的开头与结尾处。图3.7流程图通用的几种符号
(2)执行框用来表示完成的某项功能,它可以是一条指令或一段程序,无论哪种情况,该框只能有一个入口和一个出口。
(3)判断框是用来表示程序在此处要根据不同情况形成分支,框内需写明比较的条件,此框有一个入口,两个出口。
(4)连接符是用来连接两个流程框图的符号,圆形符号内可写入标识符,不同流程框图中连接符中的标识符相同的各点将连接在一起。
3.编写程序
编写程序是采用程序设计语言来实现上面已确定的算法。此过程有些书上则称为编码。本书所介绍的是采用汇编语言编写程序。采用汇编语言编写程序应注意以下几个问题:
(1)必须详细了解所用CPU的编程模型、指令系统、寻址方式及有关伪指令;
(2)必须进行存储空间和工作单元的合理分配;
(3)多次使用的程序段可采用子程序或宏指令;
(4)尽可能用标号或变量来代替绝对地址和常数。
4.程序的检验
程序编好以后,必须经过书面的检查和上机调试,以便说明程序是否正确。检验时,应预先选择典型数据,检查是否可以得到预期结果。
5.编写说明文件
一个完整的软件必须有相应的说明文件,这不仅便于用户使用,也便于对程序的维护和扩充。说明文件主要应包括程序的功能和使用方法,程序的基本结构和所采用的主要算法以及程序的必要说明和注意事项等。3.3.2IBMPC汇编语言源程序的完整结构及伪指令
IBMPC汇编语言源程序由若干个段(Segment)组成。这意味着源程序编写时,要把程序中出现的数据、程序指令以及程序中用到的堆栈等都必须分别写入不同的段中,在源程序汇编成目的程序加载到内存时也是按段结构进行的。
本节讨论的伪指令在源程序编写时能清晰地定义各种段,在汇编时能告诉汇编程序哪些段属于指令代码段,哪些段属于数据段,哪些段属于堆栈段,以及如何分配内存空间。下面首先介绍构成完整程序的有关伪指令。
1.段定义伪指令
一对伪指令分别用于定义段的开始和结尾,助记符分别为SEGMENT和ENDS。
格式:
段名SEGMENT[定位类型][组合类型][使用类型][‘类别’]
…;指令语句或伪指令语句
段名ENDS
1)段名
段名是标识符,是所定义的段的名称。段名除了有段地址和偏移地址的属性以外,还有定位类型、组合类型和类别三个属性。定位类型、组合类型和类别是可选的。SEGMENT到ENDS之间的部分则定义该段的具体内容。
2)定位类型
定位类型表示对段的起始边界的要求,其类型有PAGE、PARA、WORD、BYTE等4种。指定段的起始地址应分别可以被256、16、2、1整除,分别称为以页、节、字、字节为边界。例如,若定位类型为WORD类型,那么,该段的起始地址应能被2整除。定位类型的缺省项(默认类型)是PARA。
3)组合类型
组合类型说明程序连接时的不同模块中的同名段的合并方式,它们可以是:
PRIVATE:该段为私有段,在连接时不与其他模块中的同名段合并。
PUBLIC:该段连接时和不同模块中的同名段连接而形成一个段,其连接次序由连接命令指定。每一分段都从小段的边界开始,因此各模块的原有段之间可能存在间隙。
COMMON:该段连接时可以把不同模块中的同名段重叠而形成一个段,各同名段有相同的起始地址,所以会产生覆盖。COMMON的连接长度是各分段中的最大长度,重叠部分的内容取决于排在最后的段的内容。
ATexpression:使段地址是表达式所计算的16位值,不能用来指定代码段。
MEMORY:同PUBLIC。
STACK:该段连接时和不同模块中的同名段连接而形成一个堆栈段,其连接次序由连接命令指定,段的长度为各原有段的总和。各原有段之间无间隙,而且栈顶可自动指向连接后形成的大堆栈段的栈顶。
组合类型缺省项为PRIVATE。
4)使用类型
只适用于386及其后继机型,用来说明使用16位寻址方式还是32位寻址方式。可以是:
USE16使用16位寻址方式
USE32使用32位寻址方式
当使用16位寻址方式时,段长不超过64KB,地址形式是16位段地址和16位偏移地址。当使用32位寻址方式时,段长可达4GB,地址形式是16位段地址和32位偏移地址。在实模式下,应使用USE16。
使用类型的缺省项为USE16。
5)‘类别’
‘类别’给出在连接时组成段组的类型名。类别说明并不能把相同类别的段合并起来,但在连接后形成的装入模块中,可以把它们的位置靠在一起。
段定义时,段名是不能省略的,定位类型、组合类型和‘类别’均可省略,若不省略,它们的书写顺序不能随意更改。
段定义必须以ENDS伪指令结束,在同一个段定义中,SEGMENT与ENDS前的段名必须一致。同一个程序中可以出现多个段,这是通过多次段定义实现的。
IBMPC汇编语言源程序的典型段结构如下:上面程序中有4个段,即堆栈段(STACK)、数据段(DATA)、代码段(CODE)和附加段(EXTERN)。代码段是程序的主体部分,由一系列指令组成,实现程序的基本功能。不是所有程序都必须有4个段,有些程序
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2027年中考福建省英语中考苏教版全真模拟卷(含答案)
- 超越自我 2026年秋季高二语文部编版第一阶段阶段检测卷(含答案)
- 2027年山东省历史九年级北师大版考前抢分卷(含答案)
- 稳扎稳打 2026-2027学年第一学期高一语文部编版上学期期末测试卷(含答案)
- 精准预测 2027年海南省语文九年级苏教版中考仿真卷(含答案)
- 2027年天津市历史九年级押题密卷(含答案)
- 更上一层楼 2026-2027学年第一学期高三历史人教版第七单元单元归类复习卷(含答案)
- 2027年河南省道德与法治初三中考仿真卷(含答案)
- 山东事业编财会岗 2026 面试专项练习试卷
- 四川事业编综合管理岗 2026 历年真题试卷
- 2025中国红十字会救护员培训理论考试试题及答案
- T/JSSES 64-2025污水处理厂低碳运行管理技术指南
- 2027年中国邮政集团有限公司秋季校园招聘笔试模拟试题及答案详解
- 2026年七十岁老年人三力测试模拟附答案
- 西梅制干、分级技术规范
- AQ 3026-2026《化工企业设备检修作业安全规范》宣贯解读课件
- 小红书 2026家生活情绪需求洞察白皮书
- 雨课堂学堂在线学堂云《漫游插画星(昆明理工)》单元测试考核答案
- 2026年中核科技行测笔试题库
- 2026年及未来5年市场数据中国铜拉丝行业市场全景分析及投资规划建议报告
- 考评员国家职业技能鉴定考试题及答案
评论
0/150
提交评论