版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第5章 汇编语言程序设计 5.1 汇编语言的基本概念5.2 汇编语言源程序的格式 5.3 伪指令语句 5.4 宏指令语句 5.5 汇编语言程序的上机过程 5.6 汇编语言程序设计的基本方法 5.7 发挥80386及其后继机型的优势 5.1 汇编语言的基本概念 1机器语言(Machine Language) 机器语言是一种用二进制表示指令和数据,能被机器直接识别的计算机语言。 缺点:不直观,不易理解和记忆,因此编写、阅读和修改机器语言程序都比较繁琐。 优点:机器语言程序是计算机惟一能够直接理解和执行的程序,具有执行速度快、占用内存少等特点。 任何计算机实际上只能直接识别设计微处理器时所规定好的,
2、 一整套用“0”、 “1”数字代码表示的机器指令。这些机器指令的全体是指令系统。不同类型的CPU,其机器语言必然是不同的。这种直接用机器指令来编制计算机程序的方法就称为机器语言程序设计。 微机原理及应用课程实验教学用的单板计算机就是直接采用机器语言编程的机器。 这种直接用机器语言编程的方法难度大,阅读、查错和修改程序也很不方便。通常,只有当编程者对CPU指令系统比较熟悉, 编写的程序较短时,才有可能直接用机器语言来编写计算机程序。但是,单板计算机对硬件操作很直观,可以帮助大家了解和理解计算机在实际中的应用。 2高级语言(High Level Language) 如果说机器语言是面向机器的语言,
3、那么高级语言(如BASIC,FORTRAN等,C等)则是“面向过程”的语言。 利用高级语言编程,程序员可以完全不考虑机器的结构特点,不必了解和熟记机器的指令系统,仅使用一些接近人们书写习惯的英语和数学表达式形式的语句去编制程序。利用高级语言编写的程序与问题本身的数学模型之间有着良好的对应关系,可在各种机器上通用(不同机器之间仅做少量修改)。 但是,用高级语言编写的源程序并不能在机器上直接执行,需要被翻译成对应的目标程序(即机器语言程序),机器才能运行。把具有这种翻译作用的程序称为解释程序或编译程序,如图5.1所示。 图5.1 编译程序的功能示意图 由于高级语言程序是在未考虑机器的结构特点的条件
4、下编写的,因而它就不能充分利用某种具体CPU所具有的某些特性,而通过编译或解释程序生成的目标程序往往比较冗长,占有较多的内存空间,执行时间也比较长,这就限制了它在某些场合下的运用。 例如,实时的数据采集、检测和在线的实时控制等,往往要求程序的目标代码尽可能少占内存并有尽可能快的执行速度,在这些场合下,使用高级语言编写的程序常常不能满足要求。 3汇编语言(Assembly Language) 人们为了摆脱机器语言编程中原始而低级的状态,就设法采用一组字母、数字或字符来代替机器指令,这样就产生了汇编语言的概念和方法。 汇编语言是一种采用助记符表示的程序设计语言,即用助记符来表示指令的操作码和操作数
5、,用标号或符号代表地址、常量或变量。助记符一般都是英文字的缩写,以方便人们书写、阅读和检查。实际上,用汇编语言编写的汇编语言源程序就是机器语言程序的符号表示,汇编语言源程序与其经过汇编所产生的目标代码程序之间有明显的一一对应关系,故也称汇编语言为符号语言。 用汇编语言编写程序能够直接利用硬件系统的特性(如寄存器、标志、中断系统等)直接对位、字节、字寄存器或存储单元、I/O端口进行处理,同时也能直接使用CPU 指令系统和指令系统提供的各种寻址方式,编制出高质量的程序,这样的程序不但占用内存空间少,而且执行速度快。当然,由于源程序和所要解决的问题的数学模型之间的关系不够直观,使得汇编语言程序设计需
6、要较多的软件开发时间,也增加了程序设计过程中出错的可能性。 用汇编语言编写的源程序也需要翻译成目标程序才能被机器执行。这个翻译过程称为汇编,完成汇编任务的程序称为汇编程序,如图5.2所示。 图5.2 汇编程序的功能示意图 由于这种符号化的语言使用了用英文字母缩写表示的助记符,因此便于识别与记忆。 汇编程序是最早也是最成熟的一种系统软件。它除了能够将汇编语言源程序翻译成机器语言程序这一主要功能外,还能够根据用户的要求自动分配存储区域(包括程序区、数据区、暂存区等);自动地把各种进位制数转换成二进制数,把字符转换成ASCII码,计算表达式的值等;自动对源程序进行检查,给出错误信息(如非法格式,未定
7、义的助记符、标号,漏掉操作数等)等。具有这些功能的汇编程序又称为基本汇编(或小汇编ASM)。 在基本汇编的基础上,进一步允许在源程序中把一个指令序列定义为一条宏指令的汇编程序,就叫做宏汇编(MASM)。它包含全部ASM功能,还增加了宏指令、结构、记录等高级汇编语言功能。 问题:有高级语言,为什么还要学习和使用汇编语言? 原因: (1) 汇编语言非常接近机器语言程序,通过编制汇编语言程序,可以更清楚地了解计算机的工作过程。 (2) 现在的微机系统中,底层的一些功能仍然靠汇编语言程序来实现。 (3) 汇编语言程序的效率通常高于高级语言程序。5.2 汇编语言源程序的格式 例5.1 要求将两个5字节十
8、六进制数相加。解: 为实现上述功能,可以编写出以下汇编语言源程序。 DATASEGMENT ;定义数据段 DATA1 DB 0F8H,60H,0ACH,74H,3BH ;被加数 DATA2 DB 0C1H,36H,9EH,0D5H,20H ;加数DATAENDS ;数据段结束CODE SEGMENT ;定义代码段 ASSUME CS:CODE,DS:DATA START:MOV AX,DATAMOV DS,AX ;初始化DS MOV CX,5 ;循环次数送CXMOV SI,0 ;置SI初值为0 CLC ;清CF标志LOOPER:MOV AL,DATA2SI ;取一个字节加数ADC DATA1S
9、I,AL ;与被加数相加 INC SI ;SI加1 DEC CX ;CX减1JNZ LOOPER ;若不等于0,转LOOPERMOV AH,4CH INT 21H;返回DOSCODE ENDS ;代码段结束 END START ;源程序结束 程序结构 程序由数条语句构成,每条语句占一行。 指令性语句(指令语句) 指示性语句(伪指令语句) 分段结构 程序按段编写, 与8086内存分段编址相对应。 每段由伪操作SEGMENT开始、由ENDS结束。 程序最后为END结束语句,后跟启动地址。 启动地址指示程序开始执行的第一条语句。 程序中设有返回DOS的功能。 使程序执行完后返回DOS系统的命令接受状
10、态。 程序中用到内存操作数时,应按操作数的 寻址方式,给相应的段寄存器赋值汇编语言程序结构: movs.asmaa SEGMENT ;数据段1str1 DB Hello! aa ENDSbb SEGMENT ;数据段2str2 DB 6 dup (?) bb ENDScc SEGMENT ;代码段 ASSUME CS:cc, DS:aa, ES:bb start: CLD MOV AX , aa MOV DS , AX LEA SI , str1 MOV AX , SEG str2 MOV ES , AX MOV DI ,OFFSET str2 MOV CX , 6 REP MOVSB MOV
11、 AH , 4CH INT 21H ;返回DOScc ENDS END start ;指示程序结束5.2.1 分段结构 由例5.1可以看出,汇编语言源程序的结构是分段结构形式,一个汇编语言源程序由若干段(SEGMENT)组成,每个段以SEGMENT语句开始,以ENDS语句结束。整个源程序的结尾是END语句。 这里所说的汇编语言源程序中的段与前面讨论的CPU管理的存储器的段,既有联系,又在概念上有所区别。我们已经知道,微处理器对存储器的管理是分段的,因此,在汇编语言程序中也要求分段组织指令、数据和堆栈,以便将源程序汇编成为目标程序后,可以分别装入存储器的相应段中。 但是,以8086/8088 C
12、PU为例,它有四个段寄存器(CS,ES,SS和DS),因此CPU对存储器按照四个物理段进行管理,即数据段、附加段、堆栈段和代码段。任何时侯CPU只能访问四个物理段。而在汇编语言源程序中,设置段的自由度比较大。例如,一个源程序中可以有多个数据段或多个代码段等等。一般来说,汇编语言源程序中段的数目可以根据实际需要而设定。为了和CPU管理的存储器物理段相区别,我们将汇编语言程序中的段称为逻辑段。在不致发生混淆的地方,有时简称为段。 在例5.1的简单源程序中只有两个逻辑段,一个逻辑段的名字是DATA,其中存放着与程序有关的数据,称为逻辑数据段;另一个逻辑段的名字是CODE,其中包含着程序的指令,称为逻
13、辑代码段。每个段内均有若干行语句(STATEMENT),因此,可以说一个汇编源程序是由一行一行的语句组成的。下面我们来讨论汇编语言语句的类型和组成。 5.2.2 汇编语言语句的类型和格式 1语句的类型 汇编语言源程序中的语句可以分为两种类型:指令语句和伪指令语句。 (1) 指令语句:它是能产生目标代码,CPU 可以执行的能完成特定功能的语句。 (2) 伪指令语句:它是一种不产生目标代码的语句,它仅仅在汇编过程中告诉汇编程序应如何汇编。例如,告诉汇编程序已写出的汇编语言源程序有几个段,段的名字是什么;定义变量,定义过程,给变量分配存储单元,给数字或表达式命名等。显然,伪指令语句是汇编程序在汇编时
14、使用的。 2. 语句的格式 指令语句与伪指令语句的格式是类似的。一般情况下,汇编语言的语句可以由部分构成: 名字 助记符 操作数 ;注释 其中带方括号的部分表示任选项,可以有,也可以没有。例5.1中有如下语句:LOOPER:MOV AL,DATA2SI ;取一个字节加数 这是一条指令语句,其中:“LOOPER:”是名字,“MOV”是指令助记符,“AL,DATA2SI”是操作数,“;”后面是注释部分。 例. DATA1 DB 0F8H,60H,0ACH,74H,3BH ;定义被加数 这是一条伪指令语句,其中:“DATA1”是名字,“DB”是伪指令定义符,“0F8H,60H,0ACH,74H,3B
15、H”是操作数,“;”后面是注释部分。 下面,对汇编语言中的各个组成部分进行讨论。 语句结构 data SEGMENT ; 数据段var DB ? data ENDScode SEGMENT ; 代码段 ASSUME CS:code,DS:datastart: MOV AX, data MOV DS , AX MOV var, CL MOV AH , 4CH INT 21H ; 返回DOScode ENDS END start例: 1) 名字 汇编语言语句的第一个组成部分是名字(Name)。 在指令语句中,这个名字是一个标号。指令语句中的标号实质上是指令的符号地址。并非每条指令语句必须有标号,但
16、如果一条指令前面有一标号,则程序中其他地方就可以引用这个标号。在例5.1中,START、LOOPER就是标号。标号后面通常有一个冒号。 标号有三种属性:段、偏移量和类型。 标号的段属性是定义标号在程序段的段地址。当程序中引用一个标号时,该标号的段值应在CS寄存器中。 标号的偏移量属性表示标号所在段的起始地址到定义该标号的地址之间的字节数。偏移量是一个16位无符号数。 标号的类型属性有两种:NEAR和FAR。 NEAR标号可以在段内被引用,地址指针为2字节; FAR标号可以在其他段被引用,地址指针为4字节。如果定义一个标号时后面跟着冒号,则汇编程序确认其类型为NEAR。 伪指令语句中的名字可以是
17、变量名、段名、过程名。与指令语句中的标号不同,这些伪指令语句中的名字并不总是任选的,有些伪指令规定前面必须有名字,有些则不允许有名字,也有一些伪指令的名字是任选的。即不同的伪指令对于是否有名字有不同的规定。伪指令语句的名字后面通常不跟冒号,这是它和标号的一个明显区别。 很多情况下伪指令语句中的名字是变量名。变量名代表存储器中一个数据区的名字。 例如,例5.1中的DATA1、DATA2就是变量名。 名字项用一个符号表示。 对符号的规定: 由字符A-Z ,a-z ,0-9及符号、$、下划线_ 等组成,最长31个字符,超出部分忽略。 不能用数字打头,以免与十六进制数相混。 不使用汇编程序中的保留字
18、(如指令的助记符等)。 对定义的符号不区分大小写。 变量也有三种属性:段、偏移量和类型。 变量的段属性是变量所代表的数据区所在段的段地址。由于数据区一般在存储器的数据段中,因此变量的段地址常常在DS和ES寄存器中。 变量的偏移量属性是该变量所在段的起始地址与变量的地址之间的字节数。 变量的类型属性有BYTE(字节)、WORD(字)、 DWORD (双字)、 QWORD (四字)、TBYTE(十字)等,表示数据区中存取操作对象的大小。 2) 助记符 汇编语言语句中的第二个组成部分是助记符(Memonic)。 在指令语句中的第二部分是CPU指令系统中指令的助记符,如MOV、ADC等。助记符约有90
19、多种,在第4章指令系统中已经进行了讨论。 在伪指令语句中的第二部分是伪指令的定义符,如DB、SEGMENT、ENDS、END等。它们在程序中的作用是定义变量的类型、定义段以及告诉汇编程序结束汇编等。 关于伪指令的作用和使用方法,将在5.3节中讨论。 助记符可以是指令、伪操作中的助记符。 对于指令,汇编程序将其翻译成机器语言指令。MOV AX, 100 B8 00 01对于伪操作,汇编程序根据其要求的功能进行处理。 data SEGMENT data与一个段值相对应string DB USTB string与一个内存地址相对应。 3) 操作数 汇编语言语句中的第三个组成部分是操作数。 操作数项
20、在指令语句中是指令的操作数,可能有单操作数或双操作数,也可能无操作数; 操作数给出参与操作的数或数所在的地方。 在伪指令中可能有更多个操作数。操作数多于一个时,用逗号分开。 操作数可以是常数、寄存器、存储器操作数、标号名、过程名或表达式等。 (1) 常数。常数就是指令中出现的那些固定值,可以分为数值常数和字符串常数两类。例如,立即数寻址时所有的立即数、直接寻址时所有的地址、ASCII字符串等都是常数。常数是除了自身的值以外,没有其他属性的数值。在源程序中,数值常数按其基数的不同,可有二进制数、八进制数、十进制数、十六进制数等几种不同表示形式。汇编语言用不同的后缀加以区别(如B,H等)。 常数:
21、给出具体的数据。可以是数字常量或字符常量。 数字默认十进制,也可加D表示十进制数。如 1234D, 1234 数字后加B表示二进制数。 如 1010B 数字后加H表示十六进制数。 如 1234H 字符常量,用单引号表示。 如 1234 汇编时,用字符对应的ASCII表示。如 31H, 32H, 33H, 34H例 data1 DB 12, 34, 56 ;十进制 data2 DB 12H, 34H, 56H ;十六进制 MOV AL, G ;字符 string DB 1234 ;字符串 A、B、C、D、E、F开头的十六进制数前面加0, 与H结尾的标识符区别。如 寄存器名AH、BH、CH、DH
22、变量名 abcdH 等例 mov AL, 0AH mov AL, AH mov BX, 0abcdH 汇编语言中的数值常数的第一位必须是数字,否则汇编时将被看成是标识符,如常数B7H应写成0B7H,FFH应写成0FFH。 字符串常数是由单引号括起来的一串字符。例. ABCDEFG和179。单引号内的字符在汇编时都以ASCII的代码形式存放在存储单元中。如上述两字符串的ASCII代码为41H,42H,43H,44H,48H和31H,37H,39H。 字符串最长允许有255个字符。 (2) 寄存器。8086/8088CPU的寄存器可以作为指令的操作数。 (3) 标号。由于标号代表一条指令的符号地址
23、,因此可以作为转移(无条件转移或条件转移)、过程调用CALL以及循环控制LOOP指令的操作数。 (4) 变量。因为变量是存储器中某个数据区的名字,所以在指令中可以作为存储器操作数。 (5) 表达式。汇编语言语句中的表达式,按其性质可分为两种:数值表达式和地址表达式。 数值表达式产生一个数值结果,只有大小,没有属性。 地址表达式的结果不是一个单纯的数值,而是一个表示存储器地址的变量或标号,它有三种属性:段、偏移量和类型。 表达式中常用的运算符有以下几种: 算术运算符。常用的算术运算符有:+(加),(减),*(乘),/(除)和MOD(模除,即两个整数相除后取余数)等。 以上算术运算符可用于数值表达
24、式,运算结果是一个数值。在地址表达式中通常只使用其中的和(加和减)两种运算符。 逻辑运算符。逻辑运算符有:AND(逻辑“与”),OR(逻辑“或”),XOR(逻辑“异或”)和NOT(逻辑“非”)。 逻辑运算符只用于数值表达式中对数值进行按位逻辑运算,并得到一个数值结果。对地址进行逻辑运算是没有意义的。 关系运算符。关系运算符有:EQ(等于),NE(不等),LT(小于),GT(大于),LE(小于或等于),GE(大于或等于)等。 参与关系运算的必须是两个数值或同一段中的两个存储单元地址,但运算结果只可能是两个特定的数值之一:当关系不成立(假)时,结果为0(全0);当关系成立(真)时,结果为0FFFF
25、H(全1)。例如: MOV AX,4 EQ 3 ;关系不成立,故(AX)0 MOV AX,4 NE 3 ;关系成立,故(AX)0FFFFH 分析运算符 分析运算符用于分析一个存储器操作数的属性,如段值、偏移量和类型等,或取得它所定义的存储空间的大小。分析运算符有SEG、OFFSET、TYPE、SIZE和LENGTH等。 SEG运算符。 利用SEG运算符可以得到一个标号或变量所在段的段地址。例如,下面两条指令将变量ARRAY的段地址送DS寄存器。 MOV AX,SEG ARRAY MOV DS,AX OFFSET运算符 利用OFFSET运算符可以得到一个标号或变量的偏移地址。例如: MOV DI
26、,OFFSET DATA1 指令执行时,将DATA1的偏移地址送到DI寄存器 TYPE运算符 TYPE运算符的运算结果是一个数值,这个数值与存储器操作数类型属性的对应关系见表5.1。 下面是使用TYPE运算符的例子: VAR DW ?;变量VAR的类型为字ARRAY DD 10 DUP(?) ;变量ARRAY的类型为双字STR DB THIS IS TEST;变量STR的类型为字节 MOVAX,TYPE VAR ;(AX)2 MOV BX,TYPE ARRAY ;(BX)4 MOV CX,TYPE STR ;(CX)1 LENGTH运算符 如果一个变量已用重复操作符DUP说明其变量的个数,则利
27、用LENGTH 运算符可得到这个变量的个数。如果未用DUP说明,则得到的结果总是1。例如,上面的例子中已经用“10 DUP(?)”说明变量ARRAY的个数,则LENGTH ARRAY的结果为10。 SIZE运算符 如果一个变量已用重复操作符DUP说明,则利用SIZE 运算符可得到分配给该变量的字节总数。如果未用DUP说明,则得到的结果是TYPE运算的结果。例如,上面的例子中变量ARRAY的个数为10,类型为DWORD(双字),因此,SIZE ARRAY的结果为10440。由此可知,SIZE的运算结果等于LENGTH的运算结果乘以TYPE 的运算结果。 合成运算符。合成运算符可以用来建立或临时改
28、变变量或标号的类型或存储器操作数的存储单元类型。合成运算符有PTR、THIS、SHORT等。 PTR运算符。PTR运算符可以指定或修改存储器操作数的类型,例如:INCBYTE PTRBXSI 指令中利用PTR运算符明确规定了存储器操作数的类型是BYTE(字节),因此, 本指令将一个字节型存储器操作数加1。 利用PTR运算符可以建立一个新的存储器操作数,它与原来的同名操作数具有相同的段和偏移量,但可以有不同的类型。不过这个新类型只在当前语句中有效。例如: STUFF DD ? ;定义STUFF为双字类型变量 MOV BX,WORD PTR STUFF ;从STUFF中取一个字到BX THIS运算
29、符。THIS运算符也可指定存储器操作数的类型。使用THIS运算符可以使标号或变量更具灵活性。例如,要求对同一个数据区既可以字节为单位,又可以字为单位进行存取,则可用以下语句:TAB1 EQU THIS WORDTAB2 DB 100 DUP(?) 上面TAB1和TAB2实际上代表同一个数据区,其中共有100个字节,但TAB1的类型为WORD(字类型),而TAB2的类型为BYTE(字节类型)。 SHORT运算符。SHORT运算符指定一个标号的类型为SHORT(短标号),即标号到引用该标号指令之间的距离在128+127个字节的范围内。短标号可以被用于无条件转移指令中。使用短标号的指令比使用缺省的近
30、标号的指令少一个字节。 其他运算符。 段超越运算符“:”。运算符“:”(冒号)跟在段寄存器名(DS,ES,SS和CS)之后,表示段超越,用以给一个存储器操作数指定一个段属性,而不管其原来隐含的段是什么。例如: MOV AX,ES:DI 字节分离运算符LOW和HIGH。运算符LOW和HIGH分别得到一个数值或地址表达式的低位和高位字节。例如:STUFF EQU 0ABCDHMOVAH,HIGH STUFF ;(AH)0ABH MOV AL,LOW STUFF ;(AL)0CDH 以上介绍了表达式中使用的各种运算符,如果一个表达式同时具有多个运算符,则按以下规则运算: 优先级高的先运算,优先级低的
31、后运算。 优先级相同时按表达式中从左到右的顺序运算。 括号可以提高运算的优先级,括号内的运算总是在相邻的运算之前进行。 表5.2 运算符的优先级 4) 注释 汇编语言语句的最后一个组成部分是注释。对于一个汇编语言语句来说,注释部分并不是必要的,但是加上适当的注释以后,可以增加源程序的可读性。一个较长的实用程序,如果从头到尾没有任何注释,可能很难读懂。因此,最好在重要的程序段前面以及关键处加上简明扼要的注释。 注释前面要求加上分号(;)。如果注释的内容较多,超过一行,则换行以后前面还要加上分号。注释也可以从一行的最前面开始,以表示对一个程序段的说明。 汇编程序对于注释不予理会,即注释对汇编后产生
32、的目标程序没有任何影响。 5.3 伪 指 令 语 句 伪指令无论表示形式或其在语句中所处的位置,都与指令相似。但二者之间有着重要的区别。首先,指令是给CPU的命令,在运行时由CPU执行,每条指令对应CPU的一种特定的操作,例如传送、加法等;而伪指令是给汇编程序的命令,在汇编过程中由汇编程序进行处理,例如定义数据、分配存储区、定义段以及定义过程等。其次,汇编以后,每条指令产生一一对应的目标代码;而伪指令则不产生与之相应的目标代码。 宏汇编程序MASM提供了几十种伪指令,其中有一些伪指令小汇编ASM不能支持,如宏处理其等。根据其功能,伪指令大致可以分为以下几类: 数据定义伪指令 符号定义伪指令 段
33、定义伪指令 过程定义伪指令 宏处理伪指令 模块定义与连接伪指令 处理器选择伪指令 条件伪指令 列表伪指令 其他伪指令 5.3.1 数据定义伪指令 数据定义伪指令的用途是定义一个变量的类型,给变量赋初值,或者仅仅给变量分配存储单元,而不赋予特定的值。数据定义伪指令有DB,DW,DD,DF,DQ,DT等,而常用的是前三种。 数据定义伪指令的一般格式为:变量名 伪指令定义符 操作数,操作数其中方括号中的变量名为任选项,可以有,也可以没有。变量名后面不跟冒号。伪指令定义符后面的操作数可以不止一个。如有多个操作数,相互之间应该用逗号分开。 1. DB (Define Byte) 定义变量的类型为字节(B
34、YTE),给变量分配字节或字节串。 DB伪指令定义符后面的操作数每个占有1个字节。 2DW (Define Word) 定义变量的类型为字(WORD)。DW伪指令定义符后面的操作数每个占有1个字,即2个字节。在内存中存放时,低位字在前,高位字在后。 3DD (Define Double word) 定义变量的类型为双字(DWORD)。DD后面的操作数每个占有2个字,即4个字节。在内存中存放时,低位字在前,高位字在后。 数据定义伪指令定义符后面的操作数可以是常数、表达式或字符串,但每项操作数的值不能超过由伪指令定义符所定义的数据类型限定的范围。例如,DB伪指令定义数据的类型为字节,则其范围为无符
35、号数:0255;带符号数:128+127,等等。字符串必须放在单引号中。另外,超过两个字符的字符串只能用DB伪指令定义。请看下列语句: DATADB 101,0F0H ;存入65H,F0H EXPRDB 2*8+7 ;存入17H STR DB WELCOME! ;存入8个字符的ASCII码值AB DB AB ;存入41H,42HBADW AB ;存入42H,41HABDD DD AB ;存入42H,41H,00,00OFFAB DW AB ;存入变量AB的偏移地址ADRS DW STR,STR3,STR5 ;存入3个偏移地址 TOTAL DD DATA ;先存DATA的偏移地址,再存段地址 以
36、上第一和第二句中,分别将常数和表达式的值赋予一个变量。 第三句的操作数是包含8个字符的字符串(只有DB伪指令才能用)。在第四、五、六句,注意伪指令DB、DW和 DD的区别,虽然操作数均为 AB 两个字符,但存入变量的内容各不相同。第七句的操作数是变量AB,而不是字符串,此句将AB的16位偏移地址存入变量OFFAB。 第八句存入三个等距的偏移地址,共占6字节。第九句中的 DD 伪指令定义符将 DATA 的偏移地址和段地址顺序存入变量TOTAL,共占2个字。 除了常数、表达式和字符串外,问号“?”也可以作为数据定义伪指令的操作数,此时仅给变量保留相应的存储单元,而不赋予变量某个确定的初值。 当同样
37、的操作数重复多次时,可用重复操作符“DUP”表示,其形式为:n DUP(初值 ,初值,)其中圆括号中为重复的内容,n为重复次数。如果用“n DUP(?) ”作为数据定义伪指令定义符的惟一操作数,则汇编程序产生一个相应的数据区,但不赋任何初值。重复操作符“DUP”可以嵌套。下面是用问号或“DUP”表示操作数的几个例子: FILLERDB ?SUM DW ? DB ?,?,?BUFFERDB 10 DUP(?)ZERO DW 30 DUP(0)MASKDB 5 DUP(OK!)ARRAYDB 100 DUP(3 DUP(8),6) 其中第一、第二句分别给字节变量FILLER和字变量SUM分配存储单
38、元,但不赋予特定的值。第三句给一个没有名称的字节变量赋予3个不确定的值。第四句给变量BUFFER分配10个字节的存储空间,但不赋任何初值。第五句给变量ZERO分配一个数据区,共30个字(即60字节),每个字的内容均为零。第六句定义一个数据区,其中有5个重复的字符串OK!,共占15字节。最后一句将变量ARRAY定义为一个数据区,其中包含重复100次的内容:8,8,8,6,共占400个字节。 通常把用DUP作为惟一操作数而定义的变量称为数组。 下面是几个错误的数据定义伪指令语句:ERROR1: DW 99 ;变量名后有冒号ERROR2 DB 25*90 ;DB的操作数超过255ERROR3 DD
39、1234 ;DD的操作数是超过2个字符的字符串 5.3.2 符号定义伪指令 符号定义伪指令的用途是给一个符号重新命名,或定义新的类型属性等。符号包括汇编语言的变量名、标号名、过程名、寄存器名以及指令助记符等。 常用的符号定义伪指令有EQU、(等号)和LABLE。 1EQU 格式: 名字 EQU 表达式 EQU伪指令将表达式的值赋予一个名字。以后可用这个名字来代替上述表达式。 格式中的表达式可以是一个常数、符号、数值表达式或地址表达式等。例如: CR EQU 0DH;常数LF EQU 0AH A EQU ASCII_TABLE ;变量STR EQU 64*1024 ;数值表达式 ADR EQU
40、ES:BP+DI+5 ;地址表达式CBD EQU AAM ;指令助记符 利用EQU伪指令,可以用一个名字代表一个数值,或用一个较简短的名字来代替一个较长的名字。 如果源程序中需要多次引用某一表达式,则可以利用EQU伪指令定义符给其赋一个名字,以代替程序中的表达式,从而使程序更加简洁,便于阅读。将来如果改变表达式的值,也只需修改一处,使程序易于维护。需要注意一个问题:EQU伪指令不允许对同一符号重复定义。 2=(等号) 格式: 名字=表达式 = (等号)伪指令的功能与EQU伪指令基本相同,主要区别在于它可以对同一个名字重复定义。例如: COUNT=100 MOV CX,COUNT ;(CX)10
41、0 COUNT=COUNT10 MOV BX,COUNT ;(BX)90 3LABLE 格式: 名字 LABLE 类型 LABLE伪指令的用途是定义标号或变量的类型。变量的类型可以是BYTE、WORD、DWORD等;标号的类型可以是NEAR或FAR。 利用LABEL伪指令可以使同一个数据区兼有BYTE和WORD两种属性,这样,在以后的程序中可根据不同的需要分别以字节或字为单位存取其中的数据。例如: AREAW LABEL WORD ;变量AREAW的类型为WORDAREAB DB 100 DUP(?) ;变量AREAB的类型为BYTE MOV AREAW,AX ;AX送第1和第2字节中 MOV
42、 AREAB49,AL ;AL送第50字节中 LABEL伪指令也可以将一个属性已经定义为NEAR或者后面跟有冒号 (隐含属性为NEAR)的标号再定义为FAR。例如:AGAINF LABEL FAR;定义标号AGAINF的属性为FAR AGAIN: PUSH AX ;定义标号AGAIN的属性为NEAR 上面的过程既可以利用标号AGAIN在本段内被调用,也可以利用标号AGAINF被其他段调用。 5.3.3 段定义伪指令 段定义伪指令的用途是在汇编语言源程序中定义逻辑段。常用的段定义伪指令有SEGMENT/ENDS和ASSUME等 。1SEGMENT/ENDS 格式: 段名 SEGMENT 定位类型
43、 组合类型 类别 段名 ENDS SEGMENT 伪指令用于定义一个逻辑段,给逻辑段赋予一个段名,并以后面的任选项(定位类型、组合类型、类别)规定该逻辑段的其他特性。 SEGMENT 伪指令位于一个逻辑段的开始部分,而ENDS伪指令则表示一个逻辑段的结束。在汇编语言源程序中,这两个伪指令定义符总是成对出现的,二者前面的段名必须一致。 两个语句之间的部分即是该逻辑段的内容。例:对于代码段,其中主要有指令及其他伪指令; 对于数据段和附加段,主要有定义数据区的伪指令等等。 一个源程序中不同逻辑段的段名可以各不相同。 SEGMENT伪指令后面还有三个任选项:定位类型、组合类型和类别。在上面的格式中,它
44、们都放在方括号内,表示可有可无。如果有,三者的顺序必须符合格式中的规定。 SEGMENT伪指令后面的这些任选项是给汇编程序(MASM)和连接程序(LINK)的命令。任选项告诉汇编程序和连接程序,如何确定段的边界,以及如何组合几个不同的段等。 下面分别进行讨论。 1) 定位 (Align) 类型 定位类型任选项告诉汇编程序如何确定逻辑段的边界在存储器中的位置。定位类型共有以下四种:BYTE(边界起始地址= B) 该类型表示逻辑段从一个字节的边界开始,即可以从任何地址开始。此时本段的起始地址可紧接在前一个段的后面。 WORD(边界起始地址= 0B) 该类型表示逻辑段从字的边界开始。2字节为1个字,
45、此时本段的起始地址必须是偶数。例:边界起始地址的十六进制表示可以是 0 H 或 2 H 或 4 H 或 8 H PARA(边界起始地址= 0 0 0 0B) 该类型表示逻辑段从一个节(Paragraph)的边界开始(一节等于16个字节),也即段的起始地址能被16整除,故本段的起始地址(十六进制)应为 0 H。 如果省略定位类型任选项,则默认其为PARA。 PAGE(边界起始地址= 0 0 0 0 0 0 0 0B) 该类型表示逻辑段从页边界开始(一页等于256个字节),也即段的起始地址能被256整除,故本段的起始地址(十六进制)应为 0 0 H。 $(地址计数器伪指令) 在汇编语言程序内,为了
46、指示下一个数据或指令在相应段中的偏移量,汇编程序使用了一个当前位置计数器$。例. STR1 DWAB STR2 DB 16 DUP(?) CNT EQU $-STR1 MOV CX , CNT 指令执行后, CNT=$-STR1=2+16=18=12H,所以(CX)=12H例5.2 SEGMENT伪指令定义符的定位类型应用举例。STACK SEGMENT STACK ;STACK段,定位类型缺省 DB 100 DUP(?) ;长度为100字节STACK ENDS ;STACK段结束DATA1 SEGMENT BYTE ;DATA1段,定位类型BYTE STRING DB This is an
47、example! ;长度为19字节DATA1 ENDS ;DTAT1段结束DATA2 SEGMENT WORD ;DATA2段,定位类型WORD BUFFER DW 40 DUP(0) ;长度为40个字(80字节)DATA2 ENDS ;DATA2段结束CODE1 SEGMENT PAGE ;CODE1段,定位类型PAGE ;假设CODE2段长度为13字节CODE1 ENDS ;CODE1段结束CODE2 SEGMENT ;CODE2段,定位类型缺省 START:MOV AX,STACK ;建立堆栈段 MOV SS,AX ;假设CODE2段长度为52字节CODE2 ENDS ;CODE2段结束
48、 END START ;源程序结束 本例的源程序中共有五个逻辑段,它们的段名、定位类型和已知条件分别如下:STACK段 PARA STACK段的长度为100字节(64H)DATA1段 BYTE DATA1段的长度为19字节(13H)DATA2段 WORD DATA2段的长度为40个字CODE1段 PAGE CODE1段占用13字节(0DH)CODE2段 PARA CODE2段占用52字节(34H) 已经知道其中STACK段的长度为100字节(64H),DATA1段的长度为19字节(13H),DATA2段的长度为40个字,即80字节(50H)。假设CODE1段占用13字节(0DH),CODE2段
49、占用52字节(34H)。 如果将以上逻辑段进行汇编和连接,然后再来观察各逻辑段的目标代码或数据装入存储器的情况,如表5.3。表5.3 例5.2各逻辑段的起始地址和结束地址 段 名定位类型字节数起始地址结束地址STACKPARA100(64H)00000H00063HDATA1BYTE19(13H)00064H00076HDATA2WORD80(50H)00078H000C7HCODE1PAGE13(0DH)00100H0010CHCODE2PARA52(34H)00110H00143H 由表可清楚地看出,当SEGMENT伪指令的定位类型不同时,对段起始边界的规定也不相同。 aa SEGMENT
50、 ;数据段1 str1 DB Hello! aa ENDSbb SEGMENT ;数据段2 str2 DB 6 dup (?) bb ENDScc SEGMENT ;代码段 ASSUME CS:ccASSUME DS:aa, ES:bb start: CLD MOV AX , aa MOV DS , AX LEA SI , str1 MOV AX , bb MOV ES , AX LEA DI , str2 MOV CX , 6 REP MOVSB MOV AH , 4CH INT 21H cc ENDS END start D:masmDEBUG hello2.exe-U :查看代码段12A
51、0:0000 FC CLD12A0:0001 B89E12 MOV AX , 129E12A0:0004 8ED8 MOV DS , AX12A0:0006 8D360000 LEA SI , 000012A0:000A B89F12 MOV AX , 129F12A0:000D 8EC0 MOV ES , AX12A0:000F 8D3E0000 LEA DI , 000012A0:0013 B90600 MOV CX , 000612A0:0016 F3 REPZ12A0:0017 A4 MOVSB12A0:0018 B44C MOV AH,4C12A0:001A CD21 INT 21、
52、-D 129E:0 L10 ;查看数据段1的内容129E:0000 48 65 6C 6C 6F 21 00 00-00 00 00 00 00 00 00 00 Hello!-D 129F:0 L10 ;查看数据段2的内容129F:0000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 -数据传送源程序: 程序经汇编、连接后,装入内存的情况如下: 2) 组合(Combine)类型 SEGMENT伪指令的第二个任选项是组合类型,它告诉汇编程序当装入存储器时各个逻辑段如何进行组合。组合类型共有以下六种。 (1) 不组合 如果SEGMENT伪指令的
53、组合类型任选项缺省,则汇编程序认为这个逻辑段是不组合的。也就是说,不同程序中的逻辑段,即使具有相同的段名,也分别作为不同的逻辑段装入内存,不进行组合。 但是,对于组合类型任选项缺省的同名逻辑段,如果属于同一个程序模块,则被集中成为一个逻辑段。 (2) PUBLIC 连接时,对于不同程序模块中的逻辑段,只要具有相同的段名,就把这些段集中成为一个逻辑段装入内存。 (3) STACK 组合类型为STACK时,其含意与PUBLIC基本一样,即不同程序中的逻辑段,如果段名相同,则集中成为一个逻辑段。不过组合类型STACK仅限于作为堆栈区域的逻辑段使用。注意:在执行程序(.EXE)中,堆栈指针SP设置在这
54、个集中以后的堆栈段的(最终地址1)处。 (4) COMMON 连接时,对于不同程序中的逻辑段,如果具有相同的段名,则都从同一个地址开始装入,因而各个逻辑段将发生重叠。最后,连接以后段的长度等于原来最长的逻辑段的长度,重叠部分的内容是最后一个逻辑段的内容。 (5) MEMORY 该类型表示当几个逻辑段连接时,本逻辑段定位在地址最高的地方。如果被连接的逻辑段中有多个段的组合类型都是MEMORY,则汇编程序只将首先遇到的段作为MEMORY段,而其余的段均当作COMMON段处理。 (6) AT表达式 这种组合类型表示本逻辑段根据表达式的值定位段地址。例如,AT 8A00H,表示本段的段地址为8A00H
55、,则本段从存储器的物理地址8A000H开始装入。 3) 类别(Class) SEGMENT伪指令的第三个任选项是类别,类别必须放在单引号内。类别的作用是在连接时决定各逻辑段的装入顺序。 当几个程序模块进行连接时,其中具有相同类别名的逻辑段被装入连续的内存区,类别名相同的逻辑段,按出现的先后顺序排列。没有类别名的逻辑段,与其他无类别名的逻辑段一起连续装入内存。例如,设一个主程序中有五个逻辑段,段名和类别名分别为:STK1段 STACKCODE1段 无DATA1段 BUFFER DATA2段 TABLE DATA3段 BUFFER 还有一个子程序,包括四个逻辑段,段名和类别名分别为: DATA4段
56、 TABLE DATA5段 BUFFER STK2段 STACK CODE2段 无 当将上述主程序和子程序进行连接时,两个程序模块中各逻辑段装入内存的顺序见图5.3。图5.3 逻辑段按类别装入内存的示意图 2. ASSUME格式:ASSUME 段寄存器名:段名,段寄存器名:段名, ASSUME伪指令告诉汇编程序,将某一个段寄存器设置为存放某一个逻辑段的段地址,即明确指出源程序中的逻辑段与物理段之间的关系。当汇编程序汇编一个逻辑段时,即可利用相应的段寄存器寻址该逻辑段中的指令或数据。 在一个源程序中,ASSUME伪指令定义符应该放在可执行程序开始位置的前面。注意:ASSUME伪指令只是通知汇编程
57、序有关段寄存器与逻辑段的关系,并没有给段寄存器赋予实际的初值。例如: CODE SEGMENTASSUME CS:CODE,DS:DATA1,SS:STACKMOVAX,DATA1MOV DS,AX ;给DS赋值MOV AX,STACKMOV SS,AX ;给SS赋值 CODE ENDS ASSUME伪操作的作用:指示汇编程序指令中用到的标号、过程及变量所在的段。其中:对标号、过程必须用 CS 段寄存器指示 对变量可用 CS、DS、ES、SS 段寄存器指示 若未用ASSUME语句指示指令中用到的标号、过程和变量所在的段, 汇编程序将给出错误信息。 ASSUME语句只起指示作用,并无实际的操作。
58、 在程序中引用定义的变量做内存操作数时,需按寻址方式用传送指令(如MOV)给相应的段寄存器赋值。例 用程序实现 1234H + 5678H data SEGMENT value DW 1234H, 5678H result DW ? data ENDS code SEGMENT ASSUME CS:code, DS:data start: MOV AX, data ;给DS赋值 MOV DS, AX MOV AX, value ;取数 ADD AX, value+2 ;两数相加 MOV result, AX ;保存结果 MOV AH, 4CH ;返回DOS INT 21H code ENDS
59、END start注释掉ASSUME语句,其汇编结果: data SEGMENT value DW 1234H, 5678H result DW ? data ENDS code SEGMENT; ASSUME CS:code, DS:data start: MOV AX, data MOV DS, AX MOV AX, value ADD AX, value+2 MOV result, AX MOV AH, 4CH INT 21H code ENDS END startD:MASMMASM assume;Microsoft (R) Macro Assembler Version 5.10Co
60、pyright (C) Microsoft Corp 1981, 1988. All rights reserved.assume.ASM(8): Missing or unreachable CSassume.ASM(10): Cannot address with segment registerassume.ASM(11): Cannot address with segment registerassume.ASM(12): Cannot address with segment register 49872 + 421341 Bytes symbol space free 0 War
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 关节脱位的药物治疗
- 人工气管护理中的文献综述
- 高中主题班会 厚植家国情怀勇担时代使命教学设计 高一上学期爱国主义教育主题班会
- 低血压症状护理中的循证实践
- 高中主题班会 把努力变成有效努力教案-高中主题班会
- 中职护理护理职业规划建议
- 低分子肝素的副作用及处理
- 介入护理在康复护理中的应用
- 研究物质的实验方法-课件
- 2025-2026学年校园礼仪教案
- 2024年9月28日江西省南昌市五方面人员面试真题及答案解析
- 医院收银岗位年终总结
- 水利水电工程自动化技术试题及答案
- 初二年级下学期地理实践教学计划
- 学校内部控制制度培训
- 便利店食品安全管理制度
- 放射医学辐射安全培训
- 《普通动物学绪论》课件
- 全套电子课件:数控机床电气装调与维修
- 民航技能大赛(ARJ机型)理论考试题库(含答案)
- 医院药品集中采购实施方案
评论
0/150
提交评论