1、第4章 80X86汇编语言程序设计,本章的内容有: MASM宏汇编语句结构以及开发过程 MASM汇编语言表达式、运算符 程序段的定义和属性 复杂数据结构 宏汇编 基本汇编语言程序设计 子程序设计 高级汇编语言程序设计,4.1 MASM宏汇编语句结构以及开发过程,4.1.1 汇编语言程序的语句类型和格式 1语句的类型 硬指令语句(指令性语句)是指能产生目标代码,CPU可以执行的,能完成特定功能的语句,它主要由CPU指令组成。 伪指令语句(指示性语句)是一种不产生目标代码的语句,它仅仅在汇编过程中告诉汇编程序应如何汇编。 定义变量,定义过程,给变量分配存储单元,给数字或表达式命名等。所以伪指令语句
2、是汇编程序在汇编时用的,不产生机器码。 宏指令语句 它是一个指令序列,汇编时凡有宏指令语句的地方都将用相应的指令序列的目标代码插入。,指令性语句是计算机可执行的,而伪指令不能执行,用来定义变量,分配存储单元,指示程序开始和结束等。这两种语句的差别:在形式上:带不带冒号,是否可转向它.在本质上:汇编时能否形成对应的机器码.,2语句的格式 汇编语言源程序由语句序列构成。 汇编语言源程序中的每条语句一般占一行,每行不超过132个字符(MASM 6.0开始可以是512个字符), 执行性语句(硬指令、代码段) 标号:硬指令助记符 操作数,操作数;注释 说明性语句 名字 伪指令助记符 参数,参数 ;注释,
3、4.1.2 汇编语言的程序格式,在实地址模式和虚拟8086模式下,按照逻辑段组织程序,具有代码段、数据段、附加段和堆栈段。 一个汇编语言源程序可以包含若干个代码段、数据段、堆栈段或附加段,段与段之间的顺序可随意排列。 需独立运行的程序必须包含一个代码段,并指示程序执行的起始位置,一个程序只有一个起始位置。 所有的可执行性语句必须位于某一个代码段内,说明性语句可根据需要位于任一段内,两种格式书写 第一种格式是从MASM 5.0开始支持的简化段定义格式(但其中的两个指令 .STARTUP和 .EXIT是6.0版本才引入的)。 第二种格式是MASM 5.0以前版本就具有的完整段定义格式。,例4.1
4、简化段定义的源程序格式 MODEL SMALL ;定义程序的存储模式,小型程序一般采用小模式SMALLSTACK ;定义堆栈段DATA ;定义数据段STRING DB Hello,Everybody !,0DH,0AH,$;在数据段定义要显示的字符串CODE ;定义代码段STARTUP ;说明程序起始位置,并建立DS、SS内容(注1)MOV DX,OFFSET STRING ;指定字符串在数据段的偏移地址MOV AH,9INT 21H ;利用DOS功能调用显示信息EXIT 0 ;程序结束点,返回DOS(注2)END ;汇编结束(注3),例4.2 完整段定义的源程序格式STACK SEGMENT
5、 STACK ;定义堆栈段STACKDW 512 DUP(?) ;堆栈段的大小是1024字节(512字)空间STACK ENDS ;堆栈段结束DATA SEGMENT ;定义数据段DATA STRING DB Hello,Everybody !,0DH,0AH,$ ;在数据段定义要显示的字符串DATA ENDS ;数据段结束CODE SEGMENT CODE ;定义代码段CODE ASSUME CS:CODE,DS:DATA,SS:STACK;确定CS、DS、SS指向的逻辑段START:MOV AX,DATA ;设置数据段的段地址DSMOV DS,AX,MOV DX,OFFSET STRING
6、 ;利用功能调用显示信息 MOV AH,9 INT 21H MOV AX,4C00H ;利用系统功能调用返回DOS INT 21H CODE ENDS ;代码段结束 END START;汇编结束,同时表明程序起始位置为标号START处,4.1.3 汇编语言程序的开发过程,ML.EXE 汇编程序 ML.ERR 汇编错误信息文件 DOSXNT.EXE MS-DOS扩展文件 LINK.EXE 连接程序 LIB.EXE 子程序库管理文件 MASM5.1以下: MASM.EXE,4.2 MASM汇编语言表达式、运算符,4.2.1常量、运算符及表达式1.常量 (1)数字常量二进制常量,以B结尾十进制常量,
7、以D结尾或省略(汇编语言中默认无标记数为十进制数)十六进制常量,以H结尾,如0A8C6H.,MASM提供基数控制,.RADIX伪指令可以改变默认进制。 伪指令格式: .RADIX n 要求:n为216范围内任何数值。 功能:把n表示的数值作为默认基数。例如指令“.RADIX 16”,将缺省基数改为16,(2)字符串常量用单引号引起来的字符或字符串也代表常数。例:A,BCDE,汇编时被翻译成对应的ASCII码41H和42H,43H,44H,45H。字符串最大长度为255个字符,(3)符号常量利用一个标识符表达的一个数值。常数若使用有意义的符号名来表示,可以提高程序的可读性,同时更具有通用性。MA
8、SM提供等价机制,用来为常量定义符号名,符号定义伪指令有“EQU”和“”,2运算符MASM 6.x支持多种运算符,如表4.1所示。 (1)算术运算符实现加、减、乘、除、取余的算术运算。其中MOD也称为取模,它产生除法之后的余数,如19 MOD 75。MOV AX,3 * 4+5 ;等价于MOV AX,17 加“”和减“”运算符还可以用于地址表达式。除加、减外,其它运算符的参数必须是整数。 (2) 逻辑运算符 实现按位相与、相或、异或、求反的逻辑运算。例如: OR AL,03H AND 45H ;等价于OR AL,01H,(3) 移位运算符 实现对数值的左移、右移的逻辑操作,移入低位或高位的是0
9、。 其格式为:SHL/SHR移位次数。例如:MOV AL,0101B SHL(2*2) ;等价于MOV AL,01010000B 逻辑和移位运算符与指令助记符相同,并有类似的运算功能。汇编程序能够根据上下文判断它们是指令还是运算符,前者进行代码翻译,后者汇编时计算其数值。,(4) 关系运算符 用于比较和测试符号数值,MASM用FFFFH(补码 1)表示条件为真,用0000H表示条件为假。例如:MOV BX,(PORT LT 5) AND 20) OR (PORT GE 5) AND 30);当PORT5时汇编结果为MOV BX,20;否则,汇编结果为MOV BX,30 (5) 高低分离符 取数
10、值的高半部分或低半部分。HIGH、LOW从一个字数值或符号常量中得到高、低字节,例如: MOV AH,HIGH 8765H ;等价于MOV AH,87HMASM 6.0引入的HIGHWORD,LOWWORD取一个符号常量(不是一般的常量)的高字或低字部分,例如:DD_VALUE EQU 0FFFF1234H;定义一个符号常量MOV AX,LOWWORD DD_VALUE ;等价于MOV AX,1234H,表4.1运算符,3、运算符的优先级,关于优先级问题,不同的运算符,有不同的优先级,由于运算符多,优先级层次多,编程时通常用圆括号规定优先级,TYPE运算符用来取存储器的单元类型,各单元类型对应
11、值如下:存储器单元类型 对应值DB(字节) 1DW(字) 2DD(双字) 4NEAR -1FAR -2若BUFFER1存储区是用如下伪指令定义的:BUFFER1 DB 100 DUP(?) 则 TYPE BUFFER1等于1,LENGTH运算符用来计算一个存储区的单元(单元可以是字节,字或双字)的数目。注意:LENGTH返回的存储区必须用复制操作符DUP( )来定义,否则返回值为1。 例: 若FEES被定义为:FEES DW 4,5,6则 MOV CX,LENGTH FEES汇编后,MOV CX,1,SIZE运算符用来计算一个存储区的字节总数。 例:若BUFFER2存储区是用如下伪指令定义的:
12、 BUFFER2 DW 200 DUP(0)则:TYPE BUFFER2 等于2LENGTH BUFFER2 等于200SIZE BUFFER2 等于400,(5)合成运算符 用来建立或临时改变变量或标号的类型或存储器操作的存储单元类型。包括:PTR、THIS、SHORT。PTR运算符 用来指定或修改存储器操作数的类型,通常和伪指令BYTE、 WORD等连起来使用。 例:MOV BYTE PTRDI,0MOV WORD PTRDI,0而 MOV DI,0 ;类型不定,例:STRI1 DW ? ;定义为字类型可用如下语句:PP EQU BYTE PTR STRI1QQ EQU BYTE PTR
13、STRI1+1通过PP,QQ把STRI1和STRI1+1又规定为字节类型。MOV STRI1,AX 是合法的MOV AL,STRI1 是非法的只能用: MOV AL,PP或 MOV AL,BYTE PTR STRI1,THIS运算符可以指定存储器操作数的类型。使用THIS运算符可以使标号或变量具有灵活性。 例:AREAW EQU THIS WORDAREAB DB 100 DUP(?)SHORT运算符可以指定一个标号的类型为SHORT(短标号),即标号到引用该标号之间的距离在127127个字节范围内。短标号可以用于转移指令中,使用短标号的指令比使用近程标号的指令少一个字节。,(5) 其它运算符
14、 1)方括号 指令中用方括号表示存储器操作数,方括号里的内容表示操作数的偏移地址。例如: MOV AX,BX ;将(BX)和(BX+1)指向的存储器两个单元的内容送AX 2)段超越运算符“:” 运算符“:”(冒号)跟在某个段寄存器名(DS、ES、SS或CS)之后表示段超越,用来指定一个存储器操作数的段属性,而不管其原来隐含的段是什么。例如:M0V AX,ES:DI;把ES段中由DI指向的字操作数送(AX),4.表达式表达式是常量、寄存器、标号、变量与一些运算符组合的序列,分数字表达式和地址表达式两种。汇编时按一定的优先规则对表达式进行计算后可得到一个数值或一个地址。,1数字表达式(number
15、 expression) 数值表达式一般是指由运算符(MASM统称为操作符Operator)连接的各种常量所构成的表达式。汇编程序在汇编过程中计算表达式,最终得到一个数值。由于在程序运行之前,就已经计算出了表达式,所以,程序运行速度没有变慢,然而程序的可读性却增强了。例如:MOV DX ,(6*A-B)/2指令的源操作数(6*A-B)/2是一个表达式。若设变量A的值为1,变量B的值为2,则此表达式的值为(6*1-2)/22,是一个数字结果,此表达式是数字表达式。,2地址表达式(address expressions) 地址表达式的结果是一个存储单元的地址。当这个地址中存放的是数据时,称为变量;
16、当这个地址中存放的是指令时,则称为标号。 当在指令的操作数部分用到地址表达式时,应注意其物理意义。例如,两个地址相乘或相除是无意义的,两个不同段的地址相加减也是无意义的。经常使用的是地址加减数字量。例如,SUM+1是指向SUM字节单元的下一个单元的地址。 又如:MOV AX, ES: BX+SI+1000HBX+SI+1000H为地址表达式,结果是一个存储单元的地址。,4.2.2变量及其属性1变量定义伪指令变量是存储器中某个数据区的名字,在指令中可以作为存储器操作数。 变量定义(Define)伪指令可为变量申请固定长度的存储空间,并可以同时将相应的存储单元初始化。该类伪指令是最经常使用的伪指令
17、。 伪指令格式: 变量名 伪指令 初值表,说明: 变量名是用户自定义标识符,表示初值表首元素的逻辑地址,即用这个符号表示地址,常称为符号地址。变量名可以没有,这种情况,汇编程序将直接为初值表分配空间,无符号地址。设置变量名是为了方便存取它指示的存储单元。 初值表是用逗号分隔的参数,主要由数值常量,表达式或 ?、DUP组成。其中?表示初值不确定,即未赋初值;重复初值可以用DUP进行定义。DUP的格式为:重复次数 DUP(重复参数,被重复的数据列表) 变量定义伪指令有DB/DW/DD/DF/DQ/DT,它们根据申请的主存空间单位分类,,(1)定义字节单元伪指令DB 功能:定义变量的类型为BYTE,
18、给变量分配字节或字节串。 要求:初值表中每个数据一定是字节量(Byte),可以是0255的无符号数或是 128+127带符号数,也可以是字符串常量。例如:DATA SEGMENT ;数据段X DB a, 5DB 2 DUP(100),?Y DB ABCDATA ENDS 存储器中的分配情况如图4.1(A),数据定义的存储形式,针对上述的DATA定义,在执行下述汇编指令后,可以看到所定义的DATA中的数据发生了变化。MOV AL,X ;此处X表示它的第1个数据,故ALaDEC X+1 ;对X为起始的第2个数据减1,故成为 6 MOV Y,AL ;现在Y这个字符串成为ABC,汇编程序的地址计数器,
19、每进入一个新段,地址计数器清零,每分配一个的单元,地址计数器自动加一,指向下一个待分配的单元;$表示当前值。,(2)定义字单元伪指令DW 功能:定义变量的类型为WORD,给变量分配一个或多个字单元,并可以将它们初始化为指定值。 要求:初值表中每个数据一定是字 (Word),一个字单元可用于存放任何16位数据,如一个段地址、一个偏移地址、两个字符、065535之间的无符号数或者是 32768+32767之间的带符号数。例如: DATA SEGM;数据段COUNT DW 8000H ,?,ABMAXINT EQU 64HNUMBER DW MAXINTARRAY DW MAXINT DUP(0)
20、DATA ENDS 数据在存储器的分配情况如图4.1(B)所示,(3)定义双字单元伪指令DD 功能:定义变量的类型为DWORD,用于分配一个或多个双字单元,并将它们初始化为指定值。 要求:初值表中每个数据是一个32位的双字 (Double Word),可以是有符号或无符号的32位整数,也可以用来表达16位段地址(高位字)和16位的偏移地址(低位字)的远指针。例如:VARDD DD 0,?,12345678HFARPOINT DD 00400078HLDS SI,FARPOINT 注意:在内存中存放时,低位字在前,高位字在后。,(4)其它数据定义伪指令 定义3字伪指令DF 功能:用于为一个或多个
21、6字节变量分配空间及初始化。 用途:6字节常用在 32位CPU中表示一个48位远指针(16位段选择器:32位偏移地址)。 定义4字伪指令DQ 功能:用于为一个或多个8字节变量分配空间及初始化。 用途:8字节变量可以表达一个64位整数。 定义10字节伪指令DT 功能:用于为一个或多个10字节变量分配空间及初始化。,(5)定位伪指令 用数据定义伪指令分配的数据是按顺序一个接着一个存放在数据段中的。但有时,我们希望能够控制数据的偏移地址。例如使数据对齐可以加快数据的存取速度。MASM提供了这样的伪指令,这些伪指令我们称为定位伪指令。,ORG伪指令 伪指令格式:ORG参数 功能:ORG伪指令是将当前偏
22、移地址指针指向参数表达的偏移地址。例如:ORG 100h ;从100h处安排数据或程序ORG $+10 ;偏移地址加10,即跳过10个字节空间 汇编语言程序中,符号“$”表示当前偏移地址值。例如,在偏移地址100H单元开始定义“DW 1,2,$+4,$+4”,那么在104H单元的值为108H,106H单元的值为10AH。又如:ARRAY DB 12,34,56LEN EQU $ ARRAY 那么,LEN的值就是ARRAY变量所占的字节数。,EVEN伪指令 伪指令格式:EVEN 功能:EVEN伪指令使当前偏移地址指针指向偶数地址,即若原地址指针已指向偶地址,则不作调整;否则将地址指针加1,使地址
23、指针偶数化。 用途:EVEN可以对齐字数据。 ALIGN伪指令 伪指令格式:ALIGN n 功能:ALIGN伪指令是将当前偏移地址指针指向n(n是2的乘方)的整数倍的地址,即若原地址指针已指向n的整数倍地址,则不作调整;否则将指针加以1n1中的一个数,使地址指针指向下一个n的整数倍地址。,例如:DATA SEGMENT ;完整段定义DATA01 DB 1,2,3 ;DATA01的偏移地址为 ;0000H,$=0003hEVEN ;$=0004h,等价于ALIGN 2DATA02 DW 5 ;DATA02的偏移地址为; ;0004H,$=0006hALIGN 4 ;最接近6,可被4整除的是8DA
24、TA03 DD 6 ;DATA03的偏移地址为0008H,$=000chORG $+10H;000ch+10h=001ch,; $=001chDATA04 DB ABC ;DATA04的偏移地址为001CH,$=001fhDATA ENDS,2变量和标号的属性 变量、标号、段名及过程名都表示的是地址,那么,这些标号和名字一经定义便具有以下三种属性: 段值:段属性,标号和名字对应存储单元所在段的段地址。 偏移值:偏移属性,标号和名字对应存储单元所在段的段内偏移地址。 类型属性:标号、子程序名的类型可以是NEAR(近)和FAR(远),分别表示段内或段间;变量名的类型可以是BYTE(字节),WORD
25、(字)和DWORD(双字)等。,(1)地址操作符 地址操作符可获得名字或标号的段地址和偏移地址两个属性值。 中括号 表示将括起的表达式作为存储器地址指针; 符号 $ 表示当前偏移地址; 段前缀的冒号:也是一种地址操作符,它表示采用指定的段地址寄存器。 另外,还有两个经常应用的地址操作符OFFSET和SEG。,OFFSET操作符 使用格式:OFFSET名字/标号 功能:返回名字或标号的偏移地址 SEG操作符 使用格式:SEG名字/标号 功能:返回名字或标号的段地址例如把字节变量ARRAY的段地址和偏移地址送入DS和BX就可用下列指令序列实现。MOV AX,SEG ARRAYMOV DS,AXMO
26、V BX,OFFSET ARRAY;等价于LEA BX,ARRAY 加、减运算符同样可以用于地址表达式,例如:MOV CL,ARRAY+4 ;等效于MOV CL,ARRAY4,这里的”4”表示4个字节单元,(2)类型操作符 类型操作符对名字或标号的类型属性进行有关设置。该类操作符有PTR、THIS、SHORT和TYPE。 PTR操作符 使用格式:类型名 PTR 名字/标号 要求:PTR操作符中的“类型名”可以是BYTE/WORD/DWORD/FWORD/QWORD /TBYTE,或者是NEAR/FAR,还可以是由STRUCT,RECORD,UNION以及TYPEDEF定义的类型。 功能:使名字
27、或标号具有指定的类型,例: MOV AL,BYTE PTR W_VAR ;W_VAR是一个字变量,BYTE PTR使其作为一个字节变量 JMP FAR PTR N_LABEL ;N_LABEL是一个标号,FAR PTR使其作 ;为段间转移使用PTR操作符,可以临时改变名字或标号的类型。,SHORT操作符,只用于JMP指令 使用格式:SHORT标号 要求:转移范围为 128+127字节内。 功能:设定标号为短转移标号。SHORT指定标号作为128+127字节范围内的短转移。例如: JMP SHORT N_JUMP,表4.3 类型的返回数值,操作符SIZEOF和LENGTHOF具有类似TYPE的功
28、能,分别返回整个变量占用的字节数和整个变量的数据项数(即元素数)。实际上:SIZEOF返回值LENGTHOF返回值 TYPE返回值 请注意,在MASM 5.x仅支持SIZE和LENGTH操作符。LENGTH对于变量定义使用 DUP的情况,返回分配给该变量的单元数,其它情况为1。SIZE返回LENGTH与TYPE的乘积。,例4.3 下面程序的功能为:在屏幕上显示字符串“1357?”.MODEL SMALL.STACK.DATA V_BYTE EQU THIS BYTE;V_BYTE是字节类型的变量,但与变;量V_WORD地址相同V_WORD DW 3332H,3735H ;V_WORD是字类型的
29、变量TARGET DW 5 DUP (20H) ;分配数据空间2 510个字节CRLF DB 0DH,0AH,$FLAG DB 0N_POINT DW OFFSET S_LABEL ;取得标号S_LABEL的偏移地址.CODE.STARTUP MOV AL,BYTE PTR V_WORD ;用PTR改变V_ WORD的;类型,否则与AL寄存器类型不匹配,指令行后(AL)=32H,DEC AL MOV V_BYTE,AL ;对V_WORD的第一个字节操作,原 ;来是32H,现在是31H N_LABEL: CMP FLAG,1 JZ S_LABEL ;FLAG单元为1,则转移INC FLAGJMP
30、 SHORT N_LABEL ;短转移 S_ LABEL: CMP FLAG,2 JZ NEXT ;FLAG单元为2转移 INC FLAG JMP N_POI;段内的存储器间接寻址,转 ;移到标号S_LABEL处,等同于JMP S-LABLENEXT:MOV AX,TYPE V_WORD ;汇编结果为MOV AX,2MOV CX,LENGTH TARGET ;汇编结果为MOV CX,5MOV SI,OFFSET TARGET,W_AGAIN: MOV SI,AX ;对字单元操作INC SI ;SI指针加2INC SILOOP W_AGAIN ;循环MOV CX,SIZE TARGET ;汇编结
31、果为MOV CX,0AHMOV AL,?MOV DI,OFFSET TARGETB_AGAIN: MOV DI,AL ;对字节单元操作INC DI ;DI指针加1LOOP B_AGAIN ;循环MOV DX,OFFSET V_WORD ;显示结果:1357?MOV AH,9INT 21H.EXIT 0 END,4.3 程序段的定义和属性,4.3.1 DOS的程序结构 1.EXE程序 2.COM程序,4.3.2 简化段定义的格式,.MODEL SMALL ;定义程序的存储模式(一般采用SMALL).STACK ;定义堆栈段.DATA ;定义数据段 ;数据定义 .CODE ;定义代码段 .STAR
32、TUP ;程序起始点,并建立DS,SS内容(注1) ;程序代码 .EXIT 0 ;程序结束点,返回DOS(注2) ;子程序代码 END ;汇编结束(注3),1.存储模式伪指令,伪指令格式:MODEL存储模式,语言类型,操作系统类型,堆栈选项(混合编程使用) 使用简化段定义格式时必须使用 必须位于所有段定义语句之前 MASM有7种不同的存储模式 TINY(微型模式):专用于创建COM程序 SMALL(小型模式):只能有一个代码段和数据段,每段不大于64KB。数据段为附加段、堆栈段和数据段的总和,共用同一个段地址,即DS、ES和SS三个段寄存器相同。 指令准一、程序调用及数据访问都是近属性。是最常
33、用的模式,COMPACT(紧凑模式) MEDIUM(中型模式) LARGE(大型模式) HUGE(巨型模式) FLAT(平展模式),2简化段定义伪指令,(1) .STACK堆栈段伪指令 (2) .DATA数据段伪指令 (3) .CODE 代码段伪指令,4.3.3 完整段定义的格式,STACK SEGMENT ;定义堆栈段STACK ;分配堆栈段的大小STACK ENDS ;堆栈段结束DATA SEGMENT ;定义数据段DATA ;定义数据DATA ENDS ;数据段结束CODE SEGMENT CODE ;定义代码段CODE ASSUME CS:CODE,DS:DATA,SS:STACK ;
34、确定CS/DS/SS指向;的逻辑段START: MOV AX,DATA ;设置数据段的段地址DSMOV DS,AX ;程序代码MOV AX,4C00H ;返回DOSINT 21H ;子程序代码CODE ENDS ;代码段结束 END START ;汇编结束,程序起始位置为START,例4.4 设计一个COM程序,实现按任意键后响铃的功能。.MODEL TINY ;采用微型模式.CODE ;只有一个段,没有数据段和堆栈段.STARTUP ;等效于ORG 100H,汇编程序自动产生MOV DX,OFFSET STRING ;显示信息MOV AH,9INT 21HMOV AH,01H ;等待按键IN
35、T 21HMOV AH,02H ;响铃MOV DL,07HINT 21H.EXIT 0 STRING DB PRESS ANY KEY TO CONTINUE !$;数据安排在不与代码冲突的地方 END,4.3.3 完整段定义的格式对于一个典型的MASM程序,完整段可用下述格式定义。STACK SEGMENT STACK ;定义堆栈段STACK ;分配堆栈段的大小STACK ENDS ;堆栈段结束DATA SEGMENT ;定义数据段DATA ;定义数据DATA ENDS ;数据段结束CODE SEGMENT CODE ;定义代码段CODE ASSUME CS:CODE,DS:DATA,SS:
36、STACK ;确定CS/DS/SS指向的逻辑段,START: MOV AX,DATA ;设置数据段的段地址DSMOV DS,AX ;程序代码MOV AX,4C00H ;返回DOSINT 21H ;子程序代码CODE ENDS ;代码段结束 END START ;汇编结束,程序起始位置为START,1完整段定义伪指令,完整段定义由SEGMENT和ENDS这一对伪指令实现。 伪指令格式: 段名 SEGMENT 定位 组合 段字 类别 ;语句序列 段名 ENDS 功能:SEGMENT伪指令定义一个逻辑段的开始,ENDS伪指令表示一个段的结束。,(1).段定位(Align)属性 指定逻辑段在主存储器中
37、的边界,该关键字可表示为: BYTE:段开始地址为字节地址(xxxx xxxxB),属性值为1; WORD:段开始地址为字地址 (xxxx xxx0B),属性值为2; DWORD:段开始地址为4的倍数 (xxxx xx00B),属性值为4 PARA:段开始地址为16的倍数(xxxx 0000B),即节地址,属性值为16 PAGE:表示段开始地址256的倍数(0000 0000B),即页地址,属性值为256,(2) 段组合(Combine)属性 指定多个逻辑段之间的关系。组合的关键字有: PRIVATE: PUBLIC: STACK: COMMON:,(3) 段字(Use)属性 这是为支持32位
38、段而设置的属性。 (4) 段类别(Class)属性 当连接程序组织段时,将所有的同类别段相邻分配。 段类别可以是任意名称,但必须位于单引号中; 大多数MASM程序使用CODE,DATA和STACK来分别指名代码段、数据段和堆栈段,以保持所有代码和数据的连续。,2指定段寄存器伪指令,伪指令格式:ASSUME 段寄存器:段名,段寄存器名:段名, 功能:ASSUME伪指令通知MASM用指定的段寄存器来寻址对应的逻辑段,即建立段寄存器与段的缺省关系。 CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACK,ES:DATAMOV AX,DATAMOV DS,AXMOV
39、ES,AXMOV AX,STACKMOV SS,AX CODE ENDS,3GROUP段组伪指令,伪指令格式: 组名 GROUP 段名,段名, 功能:伪指令GROUP把多个同类段合并为一个64KB物理段,并用一个组名统一存取它。 例如:DATA1 SEGMENT WORD PUBLIC CONST;常量数据段CONST1 DW 100DATA1 ENDSDATA2 SEGMENT WORD PUBLIC VARS ;变量数据段VAR1 DW ?DATA2 ENDSDATAGROUP GROUP DATA1,DATA2;进行组合,4段顺序伪指令,段在主存中的实际顺序是可以设置的. (1)SEG段
40、顺序伪指令 伪指令格式: .SEG 功能:按照源程序的各段顺序排序。 (2)DOSSEG段顺序伪指令 伪指令格式:.DOSSEG 功能:其它微软的程序设计语言按照标准DOS规定进行排序,即代码段、数据段、堆栈段。 (3)ALPHA段顺序伪指令 伪指令格式: .ALPHA 功能:按照段名的字母顺序排序。,5. 定位伪指令,(1)ORG伪指令ORG 100h ;从100h处安排数据或程序ORG $+10 ;使偏移地址加10,即跳过10个字节空间(2)EVEN伪指令 EVEN伪指令使当前偏移地址指针指向偶数地址,即若原地址指针已指向偶地址,则不作调整;否则将地址指针加1,使地址指针偶数化。 用途:E
41、VEN可以对齐字数据。(3)ALIGN伪指令 将当前偏移地址指针指向n(n是2的乘方)的整数倍的地址,即若原地址指针已指向n的整数倍地址,则不作调整;,4.4 复杂数据结构,4.4.1结构 4.4.2记录,4.4.1 结构 1结构类型的说明,伪指令格式: 结构名 STRUCT ;数据定义语句结构名 ENDS例如:下述语句段说明了学生成绩结构。STUDENT STRUCTSID DW ?SNAME DB ABCDEFGHMATH DB 0ENGLISH DB 0STUDENT ENDS,2结构变量的定义,变量名 结构名 STU1 STUDENT STU2 STUDENT STUDENT 100
42、DUP() ;预留100个结构变量空间,3结构变量及其字段的引用,结构变量名.结构字段名 MOV STU1.MATH,95 ;执行指令后,将对MATH域;的值更新为95。,4.4.2 记录,1记录类型的说明记录名RECORD位段,位段记录中位段的格式定义如下:位段名:位数表达式 例如: PERSON RECORD YEAR:4, SEX:1=0, MARRIAGE:1=1,2记录变量的定义,记录变量定义的格式为:记录变量名 记录名 例如:ZHANG PERSON ;该字节值为:00100010B=22HWANG PERSON ;该字节值为:00100100B= 24H,3记录变量的引用和记录操
43、作符,记录变量通过它的变量名直接引用,表示它的字节或字值,4.5 宏汇编,宏是具有宏名的一段汇编语句序列。 经过定义的宏,只要写出宏名,就可以在源程序中调用它。,4.5.1 宏的定义和调用,1宏定义 宏定义由一对宏汇编伪指令MACRO/ENDM来完成。格式:宏名 MACRO形参表宏定义体ENDM 例如: MAINBEGIN MACRO ;定义名为MAINBEGIN的宏,无参数MOV AX,DATA ;宏定义体MOV DS,AX ENDM ;宏定义结束,2宏调用,宏定义之后就可以使用它,即宏调用。宏调用遵循先定义后调用的原则。宏调用格式为:伪指令格式:宏名实参表 (1)宏定义中可以有宏调用,只要
44、遵循先定义后调用的原则。 例如:DOSINT21 MACRO FUNCTION ;宏定义 MOV AH,FUNCTIONINT 21HENDMDISPMSG MACRO MESSAGE ;含有宏调用的宏定义MOV DX,OFFSET MESSAGEDOSINT21 9 ;宏调用ENDM,上述宏定义汇编后的列表文件如下。DISPMSG MSG ;宏调用MOV DX,OFFSET MSG ;宏展开(第一层)DOSINT21 9MOV AH,9 ;宏展开(第二层)INT 21H (2) 宏定义允许嵌套 即宏定义体内可以有宏定义,对这样的宏进行调用时需要多次分层展开。宏定义内也允许递归调用,这种情况需
45、要用到后面将介绍的条件汇编指令给出递归出口条件。,4.5.2 宏的参数,例4.12 具有多个参数的宏定义。使用8086的移位指令有时感到不便,因为当移位次数大于1时,必须利用CL寄存器。现在用宏指令SHLEXT扩展逻辑左移SHL的功能。例如:SHLEXT MACRO SHLOPRAND,SHLNUMPUSH CXMOV CL,SHLNUM ;SHLNUM表示移位次数SHL SHLOPRAND,CL ;SHLOPRAND表示被;移位的操作数POP CXENDM,当我们要将AX左移6位时,可以采用如下宏指令:SHLEXT AX,6汇编后,宏展开为:PUSH CXMOV CL,06SHL AX,CX
46、POP CX,宏操作符: & 替换操作符,用于将参数与其它字符分开。字符串传递操作符。用于括起字符串。 ! 转义操作符。用于指示其后的一个字符作为一般字符,而不含特殊意义。 表达式操作符。用在宏调用中,表示将随后的一个表达式的值作为实参,而不是将表达式本身作为参数。例如,已经有宏定义DSTRING(见下一页),那么:DSTRING (1024 1) ;宏调用DB 1023,0DH,0AH,$ ;宏展开 ; 宏注释符。用于表示在宏定义中的注释。采用这个符号的注释,在宏展开时不出现。 另外,宏定义中还可以用“:REQ”说明设定不可缺参数,用“:默认值”设定参数默认值。,例4.14 用于字符串的宏定
47、义参数 DSTRING MACRO STRINGDB & STRING&,0DH,0AH,$ENDM例如,要定义字符串THIS IS A EXAMPLE,可以采用如下宏调用。DSTRING 它产生的宏展开为:DB THIS IS A EXAMPLE,0DH,0AH,$,4.5.3 与宏有关的伪指令,1局部标号伪指令LOCAL 问题提出: 宏定义可被多次调用,当宏定义中使用了标号,同一源程序对它的多次调用就会造成标号的重复定义,汇编将出现语法错误。 解决:如果宏定义体采用了标号,可以使用局部标号伪指令LOCAL加以说明。 伪指令格式为:LOCAL 标号列表 每次宏展开时汇编程序将对其中的标号自动
48、产生一个唯一的标识符(其形式为“?0000”到“?FFFF”),避免宏展开后的标号重复 注意:LOCAL伪指令只能在宏定义体内使用,而且是宏定义MACRO语句之后的第一条语句,两者间也不允许有注释和分号。,ABSOL MACRO OPRDLOCAL NEXTCMP OPRD,0JGE NEXTNEG OPRD NEXT:ENDM ;这个伪指;令要独占一行,采用例4.15宏定义的宏调用形式为:ABSOL WORD PTR BXABSOL BX上述宏调用下的宏展开为:CMP WORD PTR BX,0JGE ?0000NEG WORD PTR BX? 0000:CMP BX,0JGE ? 0001NEG BX? 0001:,2宏定义删除伪指令PURGE,当我们不需要某个宏定义时,可以把它删除,删除宏定义伪指令的格式为:PURGE 宏名表 允许宏名与其它指令包括伪指令同名,此时宏名优先级最高。当不再使用这个宏定义时,及时用PURGE删除即恢复原指令功能。,