版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
(三)汇编语言的伪指令语句一、符号定义伪指令语句为一个表达式或指令助记符赋予一个符号名。在后继程序文本中,可以使用该符号名来替代这个表达式或指令助记符。(1)等值语句EQU
格式: 符号名 EQU 表达式/指令助记符例如:PORT1 EQU312 ;为数值常量312赋予符号名PORT1PORT2 EQUPORT1+1;为数值表达式赋予符号名PORT2ADDR EQUES:[SI+4];为地址表达式定义一个名字STRING EQU‘COMPUTER’;为字符串常量定义一个名字COUNT EQUCX ;为寄存器CX定义新的符号名LD EQUMOV ;为助记符MOV定义新的符号名LD(三)汇编语言的伪指令语句1说明:①在EQU语句的表达式中,如果有标号名或变量名,则该语句必须放在它们的定义语句之后。例如 ABEQUDATA+2必须放在标识符DATA的定义之后,否则汇编程序将指示以下错误:
Symbolnotdefined:DATA②后面的EQU伪操作可以利用前面的EQU伪操作已经定义的符号名。例如: ALPHAEQU7;给数值7赋以符号名ALPHA BETAEQUALPHA-2;给7-2=5赋以符号名BETA ADDREQUVAR+BETA;给VAR+5赋以符号名ADDR说明:2③使用EQU伪操作定义过的符号名不允许重复定义。例如: EMPEQU0;给数值7赋以符号名ALPHA EMPEQUEMP+1;汇编该语句时,汇编程序将指示出错。(2)等号语句=
格式: 符号名=表达式/指令助记符该语句的功能与EQU完全相同,唯一的区别是:该语句可以对符号名进行重复定义。例如: EMP=0;定义符号名EMP为0 EMP=EMP+1;重新定义符号名EMP为1,完全合法。③使用EQU伪操作定义过的符号名不允许重复定义。3二、数据定义伪指令语句数据定义语句用于定义变量,该语句指定变量的名称和变量的类型,并为该变量分配存储单元。二、数据定义伪指令语句4(1)数据定义语句的格式[变量名]数据定义符操作数[,操作数]…[,操作数]其中,①变量名:可选项。②操作数:赋给变量的初值,多个相同类型的变量可在一条语句中定义。③数据定义符常用数据定义符有以下三种。
•DB:定义字节变量,每个变量占有1个字节的存储单元。
•DW:定义字变量,每个变量占有2个字节的存储单元。
•DD:定义双字变量,每个变量占有4个字节的存储单元。此外,还有DQ、DF和DT等类型。对于多字节变量,其变量值的内存存放规则是,低位字节占低地址单元,高位字节占高地址单元。(1)数据定义语句的格式5说明:经过定义的变量必然具有以下三个属性。•数据类型字节、字、双字等等。•偏移地址分配给该变量的存储单元的偏移地址。•段基址
分配给该变量的存储单元的段基址,也就是定义该变量的逻辑段的段基址。说明:6(2)数据定义语句的具体形式和功能
根据操作数的不同表达形式,常见的数据定义语句有以下几种具体形式。①操作数是一个数值常量例如:XDB25H;定义一个名为X、初值为25H的字节变量YDW4142H;定义一个名为Y、初值为4142H的字变量ZDD12345678H;定义一个名为Z、初值为12345678H的双字变量X┇25HY42H41HZ78H56H34H12H┇汇编时,汇编程序将完成以下工作:①首先,定义名为X的字节变量,并为其分配一个字节单元,然后再把初值25H装入该单元中。②随后,定义名为Y的字变量,并为其分配一个字单元,然后再把初值4142H装入该单元中。③最后,定义名为Z的双字变量,并为其分配一个双字单元,然后再把初值12345678H装入该单元中。(2)数据定义语句的具体形式和功能X┇25HY42H47②操作数是一个数值表达式例如:PORT EQU80HOUT_PORTDWPORT+1汇编程序将定义一个名为OUT_PORT的字类型变量,并为其分配一个字单元,然后计算数值表达式(PORT+1)的数值,并把计算结果0081H装入该单元中。┇OUT_PORT81H00H┇②操作数是一个数值表达式┇OUT_PORT81H08
③操作数部分使用问号?例如: ADB?;定义字节变量A,并为其分配一个字节单元 BDW?;定义字变量B,并为其分配一个字单元汇编程序只为变量分配存储单元,并不赋予其具体的初值,该变量的初值不确定。A┇B┇③操作数部分使用问号?A┇B┇9④操作数部分是用逗号分隔的若干个操作数例如: TABLEDW1,2,3TABLE┇01H00H02H00H03H00H┇汇编程序首先定义一个名为TABLE的字类型变量,并为该变量分配一个字单元,再将变量初始值0001H装入其中。然后,再为一个无名字变量分配一个字单元,并将变量初始值0002H装入其中。最后,再为一个无名字变量分配一个字单元,并将变量初始值0003H装入其中。④操作数部分是用逗号分隔的若干个操作数TABLE┇10这个数据定义语句定义了三个变量,第一变量的变量名为TABLE,其它两个变量没有变量名。但是由于这三个变量的存储单元依次排列,具有线性存储特性,因此我们可以将这种数据定义语句看成是数组变量的定义语句,并将第一个变量的变量名TABLE看成是数组变量名,将这三个变量看成是该数组的数组元素。于是各数组元素的访问地址可以用下式来确定。
数组元素地址=数组变量名+数组元素下标值*数组元素字节大小TABLE┇01H00H02H00H03H00H┇MOVAX,TABLE;(AX)=0001HMOVAX,TABLE+1*2;(AX)=0002HMOVAX,TABLE+2*2;(AX)=0003H这个数据定义语句定义了三个变量,第一变量的变量名为T11在定义数组变量时,可以使用重复操作符DUP来定义各个数组元素,其定义格式如下。
重复次数DUP(操作数1,…,操作数N)这个表达形式的含义是,将括号中的N个操作数,以指定的次序,重复指定次数。其中,重复次数字段是值为正整数的数值表达式。例如:TABLEDB2DUP(0,1),2<=>TABLEDB0,1,0,1,2注意:DUP重复操作符可以嵌套使用,例如以下两式是等价的。TABLEDB2DUP(2DUP(1,2),3)TABLEDB1,2,1,2,3,1,2,1,2,3在定义数组变量时,可以使用重复操作符DUP来定义各12CDAB⑤操作数是一个字符串常量例如: STRING DB‘ABCDEF’该语句定义了一个字符数组变量STRING。汇编程序将为这个数组变量分配一个数据区,并将字符串中每一个字符的ASCII码依次装入到数据区的各个字节单元中。STRING┇41H42H43H44HEF45H46H┇CDAB⑤操作数是一个字符串常量STRING┇4113STRING2注意:①当字符串长度超过两个字符时,伪指令定义符只能使用DB。②当字符串长度不超过两个字符时,伪指令定义符DB、DW、DD、DQ等都可以使用,但它们的意义有所不同。例如: STRING1DB‘AB’ STRING2DW‘AB’BAABSTRING1┇41H42H42H41H┇MOVAL,STRING1;(AL)=41HMOVAL,STRING1+1;(AL)=42HMOVAX,STRING2;(AX)=4142HSTRING2注意:BAABSTRING1┇41H414XADDR2⑥操作数是一个存储器地址(标号、过程名或变量名)例: X DB 10H ADDR1 DW X ADDR2 DD X┇ADDR1变量X的偏移地址的低字节变量X的偏移地址的高字节变量X的偏移地址的低字节变量X的偏移地址的高字节变量X的段基址的低字节变量X的段基址的高字节┇10H当操作数是一个存储器地址时,数据定义符只能使用DW或DD。此时汇编程序将使用这个存储器地址的偏移地址(DW)或全地址(DD)来初始化变量。全地址的存放格式是,16位偏移地址放在低地址单元,16位段地址放在高地址单元。XADDR2⑥操作数是一个存储器地址(标号、过程名15⑦操作数是如下形式的地址表达式标号或变量名±结果为整数的数值表达式这个地址表达式的运算结果仍然表示一个标号或变量,其类型属性和段基址属性与原来的标号或变量相同,只有其偏移量属性产生相应的增减。因此,汇编程序对这个表达式的处理完全等同于处理一个存储器地址。数据定义符只能使用DW或DD,汇编程序将使用这个新存储器地址(地址表达式的运算结果)的偏移地址(DW)或全地址(DD)来初始化变量。⑦操作数是如下形式的地址表达式16例如:X DB 10H ADDR1 DW X+1 ADDR2 DD X+1汇编第2条语句时,汇编程序将存储器地址X+1的偏移地址装入到分配给变量ADDR1的双字节存储单元内。汇编第3条语句时,汇编程序将存储器地址X+1的全地址装入到分配给变量ADDR2的双字存储单元内。其中16位偏移地址被存放在低字单元内,16位段地址被存放在高字单元内。例如:17⑧操作数是如下形式的数值表达式变量名1-变量名2
或者
标号1-标号2其中,变量名1和变量名2:同一逻辑段内定义的两个变量名。标号1和标号2:同一代码段内定义的两个标号。同一逻辑段内的两个标号或变量名的相减结果是一个数值,它表示两者之间相距的字节数。⑧操作数是如下形式的数值表达式18TABLE2LENGTH1LENGTH2TABLE1┇01H02H03H04H┇05H06H04H02H例如:TABLE1 DB1,2,3,4TABLE2 DB5,6LENGTH1DBTABLE2-TABLE1LENGTH2DBLENGTH1-TABLE2TABLE2LENGTH1LENGTH2TABLE1┇01H19说明:数据定义语句定义了变量的数据类型,汇编程序可以利用这种隐含的类型属性来确定某些指令是字指令、还是字节指令。例如: OPER1DB?,? OPER2DW?,? ┇ MOVOPER1+1,0;字节指令 MOVOPER2+2,0;字指令 MOVOPER1+1,AL;字节指令 MOVOPER2+1,AX;字指令说明:20(3)分析运算符(SEG、OFFSET、TYPE、SIZE、LENGTH)分析运算符作用于变量或标号,运算结果为变量或标号的属性值,其使用格式为:
运算符 变量/标号①SEG和OFFSET运算符SEG和OFFSET运算分别返回变量或标号的段地址和偏移地址。例如: ARRAYDB100DUP(0);定义字节数组变量ARRAY ┇ MOVAX,SEGARRAY;变量ARRAY的段地址→(AX) MOVDX,AX MOVBX,OFFSETARRAY;变量ARRAY的偏移地址→(BX) MOVAL,[BX](3)分析运算符(SEG、OFFSET、TYPE、SIZE、21②TYPE、LENGTH和SIZE操作符TYPE操作符返回一个表示变量类型或标号类型的数值。变量的类型值是变量的字节长度值;标号的类型值只起区别作用,没有实际物理意义。类型代码类型值字节变量BYTE1字变量WORD2双字变量DWORD4标号NEAR-1(0FFH)标号FAR-2(0FEH)②TYPE、LENGTH和SIZE操作符类型代22在数组变量定义语句中,如果第一个操作数项使用DUP运算符定义,则该数组变量的LENGTH运算结果是此DUP运算符前面的重复次数,其它一切情况下,返回1。
SIZE运算符的运算结果为TYPE运算结果和LENGTH运算结果的乘积,表示分配给数组变量的字节总数。例如: BUFFER1DB100DUP(0) BUFFER2DW200DUP(20H) BUFFER3DD100DUP(13)则有:TYPEBUFFER1=1LENGTHBUFFER1=100SIZEBUFFER1=100TYPEBUFFER2=2LENGTHBUFFER2=200SIZEBUFFER2=400TYPEBUFFER3=4LENGTHBUFFER3=100SIZEBUFFER3=400在数组变量定义语句中,如果第一个操作数项使用DUP运23(4)合成运算符(PTR、THIS)
合成运算符作用于变量或标号,对原变量或标号的类型属性进行修改,从而建立起一个新的变量或标号。①PTR运算符该运算符采用原变量或标号的段属性和偏移地址属性,指定一个新的类型属性,从而建立起一个新的变量或标号,而原变量或标号的类型属性不变。例1: ARRAY1DB0,1,2,3;定义字节数组变量ARRAY1ARRAY2DW4,5,6,1234H;定义字数组变量ARRAY2MOVBX,WORDPTRARRAY1;0100H→(BX)MOVCL,BYTEPTR(ARRAY2+3*2);34H→(CL)MOVWORDPTR[SI],4;0004H→SI所指向的字单元(4)合成运算符(PTR、THIS)24配合EQU伪指令,我们可以定义新的变量名。例如:ARRAY1DB0,1,2,3;定义字节数组变量ARRAY1ARRAY2DW4,5,6,1234H;定义字数组变量ARRAY2 ┇ W EQU WORDPTRARRAY1 B EQU BYTEPTRARRAY2新变量W和B的段地址和偏移地址分别与ARRAY1和ARRAY2相同,只是它们的类型已经发生变化。在后面的程序中,可以直接使用这两个新定义的变量。 MOV BX,W+3 ;0403H→(BX) MOV CL,B+6 ;34H→(CL)配合EQU伪指令,我们可以定义新的变量名。25②THIS操作符THIS操作符为当前存储单元(当前地址计数器所指向的存储单元)设定一个指定类型,并与EQU伪操作配合使用,建立起一个新的变量或标号。其使用格式如下。 变量或标号名EQUTHIS类型代码例: B EQU THISBYTE ARRAYDW 100DUP(?)
100个字的字数组ARRAY也可以按200个字节的字节数组B来使用。②THIS操作符26③LABEL伪操作LABEL伪操作为当前存储单元(当前地址计数器所指向的存储单元)定义一个指定类型的变量或标号。该操作符常用于设定一个数据块的属性,使其具有多重名字和属性,其使用格式如下。 标号或变量名LABEL类型代码例:ARRAY1LABELWORD;定义一个名为ARRAY1的字数组变量ARRAY2DB1,2,3,4;定义一个名为ARRAY2的字节数组变量 MOVAL,ARRAY2;01H→(AL) MOVAX,ARRAY1;0201H→(AX)
ARRAY1和ARRAY这两个变量都指向同一个数据块,具有相同的段属性和偏移量属性,但是它们的类型属性不同。程序员可以根据需要按不同类型去操作数据块中的数据。③LABEL伪操作27三、地址计数器与对准伪操作(1)地址计数器地址计数器是一种指针部件,其内容是当前逻辑段内某个存储单元的段内偏移地址。当汇编程序处理一个数据项或一条指令时,汇编程序将把该数据项或该指令的目标代码存放到地址计数器所指示的存储单元内。当汇编程序处理一个数据项或一条指令时,地址计数器的内容就是存放该数据项或该指令目标代码的存储单元的偏移地址。三、地址计数器与对准伪操作28地址计数器的工作过程如下。①每当开始汇编一个逻辑段时,地址计数器的内容就被初始化为零,表示段内数据或指令目标代码将从段内偏移地址为零的位置处开始存放。②当汇编程序把一条指令的目标代码存放到地址计数器所指向的存储单元后,地址计数器的内容就增加一个大小为该指令字节数的数值,指向下一条指令将要被存放的位置。③当汇编程序把一个数据项存放到地址计数器所指向的存储单元后,地址计数器的内容增加一个大小为该数据项字节数的数值,指向下一个数据项将要被存放的位置。地址计数器的工作过程如下。29在汇编过程中,汇编程序所进行的指令代码存放、变量存储单元分配、变量初值装入等工作,正是在地址计数器的引导下来完成的。在汇编语言源程序中,用户可以使用符号$来表示地址计数器的当前值,表示存放当前数据项或当前指令目标代码的存储单元的偏移地址。在汇编过程中,汇编程序所进行的指令代码存放、变量存储30例1: JNE$+6地址计数器的当前值$为存放该指令的存储单元的偏移地址,因此有 指令转向地址=指令的首地址+6由于该指令是2字节指令,因此处理该指令时的IP当前值为IP当前值=指令的首地址+2于是有位移量=转向地址–IP当前值=4该指令的机器代码为:7504例1:31例2:假设汇编处理时,变量ARRAY被分配的偏移地址为0074H,求该语句的汇编结果。 ARRAYDW1,2,$+4,3,4,$+4解:当汇编程序处理第三个数据项($+4)时地址计数器值的当前值$=0074H+2*2=0078H,于是有 $+4=0078H+4=007CH当汇编程序处理第六个数据项($+4)时,地址计数器值的当前值$=0074H+2*5=007EH,于是有 $+4=007EH+4=0082H因此,原来的语句等效于 ARRAYDW1,2,7CH,3,4,82H例2:假设汇编处理时,变量ARRAY被分配的偏移地址32(2)对准伪操作对准伪操作都是针对地址计数器的各种操作。1)指定地址伪指令(ORG)强行指定地址计数器的当前值,以改变该指令之后的代码或数据块在段内存放的偏移地址。格式1: ORG表达式功能:直接将表达式的运算结果(0~65535)送入地址计数器。(2)对准伪操作33格式2: ORG$+表达式功能:将汇编该语句时的地址计数器当前值$加上表达式的数值,然后将最终结果送入地址计数器。说明:通过执行ORG伪指令,汇编程序将以(表达式)或($+表达式)的运算结果为起点,来存放ORG语句之后定义的代码或数据。格式2: ORG$+表达式34例: DATA SEGMENT
ORG 10H ;① X DB 20H,30H
ORG $+5 ;② Y DB 40H,50H DATA ENDS说明:①将地址计数器的内容设置为10H,即从DATA数据段内偏移地址为10H的存储单元开始,存放后继数据20H和30H。②处理该语句时,地址计数器的内容为12H,$+5=12H+5=17H,于是该语句将地址计数器的内容设置为17H,即从DATA数据段内偏移地址为17H的存储单元开始,存放后继数据40H和50H。例:352)EVEN伪操作
格式:EVEN功能:将地址计数器的内容设置为大于或等于当前值的最小偶数值,以使后继语句所定义的变量或指令开始于偶数地址。说明:
字数据的地址最好是偶数。为保证字数组从偶地址开始,可以在其前使用EVEN伪操作。2)EVEN伪操作36
3)ALIGN伪操作
格式:
ALIGN数值表达式(运算结果必须是2的幂,即2、4、8等等)功能:将地址计数器的内容设置为大于或等于当前值的最小的数值表达式运算结果的整数倍值,以使后继语句所定义的变量或指令开始于字边界、双字边界、4字边界等等。说明:该伪操作可用于定位双字数组、4字数组等等操作。
3)ALIGN伪操作37四、程序分段伪指令语句程序分段伪指令语句用于指示汇编程序和链接程序如何以逻辑段为基本单位来组织程序和分配存储器。四、程序分段伪指令语句38(1)段定义伪指令(SEGMENT/ENDS)段定义伪指令SEGMENT/ENDS用于定义一个逻辑段,指出该逻辑段的段名、段属性以及段的开始和结束位置。格式: 段名SEGMENT[定位类型][组合类型][‘类别名’] 段体 段名ENDS其中,段名:逻辑段的标识符。在汇编语言源程序中,表示链接程序分配给该逻辑段的段基址。段体:逻辑段内的汇编语句序列。定位类型、组合类型和类别名:逻辑段的三个属性。(1)段定义伪指令(SEGMENT/ENDS)391)定位类型当编制完成汇编语言源程序后,我们需要继续进行以下处理。首先使用汇编程序对汇编语言源程序进行汇编处理,得到目标代码文件(.OBJ);其次使用链接程序对目标代码文件进行链接处理,得到可执行文件(.EXE)。这个可执行文件就是可以在操作系统中运行的可执行程序。在目标代码文件(.OBJ)中,汇编程序只是对各个逻辑段内的汇编语句进行了初步处理,并没有确定各个逻辑段的存储位置,因此对于标号、变量名和过程名,其段地址还没有确定,其段内偏移地址也只是初步确定下来,需要在随后的链接处理中再进一步修正。链接处理时,链接程序将在起始地址为00000H的地址空间中,确定所有逻辑段的存储位置,即把所有的逻辑段链接起来。链接处理后,所有标号、变量名和过程名的段内偏移地址都被确定下来了,而这些名字的段地址则只是一个初步数值,只有在加载运行该程序时,再由操作系统进一步确定这些名字的实际段地址。逻辑段定义语句所指定的三个段属性就是告诉链接程序如何确定本逻辑段的存储位置。1)定位类型40参数项段起始地址段起始偏移地址PARA(默认项)小段边界(16的倍数):XXXX0H从0开始PAGE页边界(256的倍数):XXX00H从0开始WORD字边界(2的倍数)可能不为0DWORD双字边界(4的倍数)可能不为0BYTE任意地址可能不为0定位类型参数指示链接程序将本逻辑段定位在指定的地址边界上。该参数共有下表所示的五种。参数项段起始地址段起始偏移地址PARA小段边界(16的倍数)41STACK SEGMENTSTACK DB10DUP(0)STACK ENDSdata1 segmentarray1 db1,2,3data1 endsdata2 segmentarray2 dw1,2,3data2 endscode1 segment assumecs:code1,ds:data1start: movax,data1 movds,ax moval,array1code1 endscode2 segment assumecs:code2,ds:data2 movax,data2 movds,ax movax,array2code2 ends endstartSTACK SEGMENTSTACKcode1 segme42┇00009H00012H00010H00011HSTACK段00000H0┇0data1段01H02H03H00025Hdata2段00020H01H00H┇03H00H┇00037H00030HCode1段┇00047H00040HCode2段┇┇┇┇┇STACK段段地址=0000Hdata1段段地址=0001H变量array1的段地址=0001H变量array1的偏移地址=0000Hdata2段段地址=0002H变量array2的段地址=0002H变量array2的偏移地址=0000Hcode1段段段地址=0003H标号start的段地址=0002H标号start的偏移地址=0000H┇00009H00012H00010H00011HS43STACK SEGMENTSTACK DB10DUP(0)STACK ENDSdata1 segmentbytearray1 db1,2,3data1 endsdata2 segmentbytearray2 dw1,2,3data2 endscode1 segmentbyte assumecs:code1,ds:data1start: movax,data1 movds,ax moval,array1code1 endscode2 segmentbyte assumecs:code2,ds:data2 movax,data2 movds,ax movax,array2code2 ends endstartSTACK SEGMENTSTACKcode1 segme44┇00009H0000CH0000AH0000BHSTACK段00000H00┇0data1段01H02H03H00012Hdata2段0000DH01H00H02H00H03H00H┇0001AHcode1段00013H┇┇00022Hcode2段0001BH┇┇STACK段段地址=0000Hdata1段段地址=0000H变量array1的段地址=0000H变量array1的偏移地址=000AHdata2段段地址=0000H变量array2的段地址=0000H变量array2的偏移地址=000DHcode1段段段地址=0001H标号start的段地址=0001H标号start的偏移地址=0003H┇00009H0000CH0000AH0000BHS452)组合类型一个汇编语言源程序可能包含了若干个程序模块,而不同的程序模块又有可能包含了相同名字的逻辑段。组合类型参数指定了同名逻辑段的合并方法,也就是说,当链接各个程序模块.OBJ时,链接程序将按照组合类型参数所指定的方法来合并各个程序模块中的同名逻辑段。参数项合并方法(连接次序由连接命令指定)PRIVATE(私有段,默认项)本逻辑段与其它模块中的同名逻辑段不合并,并拥有自己的段起始地址。PUBLIC(公共段)①本逻辑段与其它模块中说明为PUBLIC的同名逻辑段相互邻接合并在一起,共用一个段地址而形成一个大段。②如果各分段的定位类型不同,则所有分段按照最大类型定位,各分段之间可能存在此最大类型定位的定位间隙。2)组合类型参数项合并方法PRIVATE本逻辑段与其46程序文件1STACK SEGMENTSTACK DB10DUP(0)STACK ENDSdata segment bytearray1 db1,2,3data endscode segmentbyte assumecs:code,ds:datastart: movax,data movds,ax moval,array1code ends endstart程序文件2STACK SEGMENTSTACK DB10DUP(0)STACK ENDSdata segmentarray2 dw1,2,3data endscode segment assumecs:code,ds:data movax,data movds,ax movax,array2code ends end程序文件1程序文件247┇00013H00016H00014H00015HSTACK段00000H0┇0data段01H02H03H00025Hdata段00020H01H00H02H00H03H00H┇0001EH00017H文件1Code段┇00037H00030H文件2Code段┇┇STACK段段地址=0000H文件1data段段地址=0001H变量array1的段地址=0001H变量array1的偏移地址=0004H文件2data段段地址=0002H变量array2的段地址=0002H变量array2的偏移地址=000DH文件1code段段地址=0001H标号start的段地址=0001H标号start的偏移地址=0007H文件2code段段地址=0003H┇00013H00016H00014H00015HS48程序文件1STACK SEGMENTSTACK DB10DUP(0)STACK ENDSdata segment bytepublicarray1 db1,2,3data endscode segmentbytepublic assumecs:code,ds:datastart: mov ax,data mov ds,ax mov al,array1code ends endstart程序文件2STACK SEGMENTSTACK DB10DUP(0)STACK ENDSdata segmentpublicarray2 dw1,2,3data endscode segmentpublic assumecs:code,ds:data mov ax,data mov ds,ax mov ax,array2code ends end程序文件1程序文件249┇00013H00022H00020H00021HSTACK段00000H0┇0data段01H02H03H00035HCode段00030H01H00H02H00H03H00H┇00047H00040H文件1Code段┇┇┇┇┇00057H00050H文件2Code段┇STACK段段地址=0000Hdata段段地址=0002H变量array1的段地址=0002H变量array1的偏移地址=0000H变量array2的段地址=0002H变量array2的偏移地址=0010Hcode段段地址=0004H标号start的段地址=0004H标号start的偏移地址=0000H┇00013H00022H00020H00021HS50参数项合并方法(连接次序由连接命令指定)COMMON(公有段)①各个模块中说明为COMMON的同名逻辑段之间从相同的段起始地址开始,相互重叠覆盖而形成一个段。②合并段的长度取决于最长COMMON分段的长度。③合并段中重叠部分的内容就是最后分段的内容,未重叠部分的内容是最长分段留下的内容。④在各分段内定义的变量依然保持自己的位置,但其内容未必是本段定义的内容,取决于最后重叠覆盖完成后的情况。此时在不同分段中定义的不同变量,可能同时标识了公有段内的同一个存储单元。AT表达式将本段定位在表达式的16位整型结果所指定的段地址位置上。①这种组合类型可以为变量赋予绝对地址,以便程序能够以变量的形式访问这些存储单元。②该组合方式不能用来指定代码段。MEMORY①链接程序把本段放在被链接在一起的所有其他段的最后;②若有多个MEMORY段,汇编程序认为第一个为MEMORY,其余为COMMON。参数项合并方法COMMON①各个模块中说明为COM51参数项合并方法(连接次序由连接命令指定)STACK(堆栈段)①各个模块中说明为STACK的同名逻辑段之间相互邻接合并在一起,共用一个段地址而形成一个大的堆栈段。将该程序加载到内存后,系统将把堆栈段寄存器SS的内容自动设置为这个总堆栈段的段地址。②总堆栈段的长度为各个分段长度的总和。将该程序加载到内存后,系统将把堆栈指针SP(ESP)的内容自动设置为总堆栈段的字节长度值,指向总堆栈段的栈底。③无论各个分段被设置成什么样的定位类型(比如BYTE),各个分段之间没有间隙。总堆栈段总是被定位在小段边界上,既堆栈段的初始偏移地址必为零。说明:①如果不同模块定义了名字不同的堆栈段,连接时只有最后一个模块所定义的堆栈段有效,其他模块定义的堆栈段无效。因此在设计各个模块的堆栈段时,应该取相同的堆栈名。②如果在定义堆栈段时没有将其说明为STACK组合类型,那么就需要在程序中使用指令来设置SS和SP。此时LINK程序将会给出一个警告信息。参数项合并方法STACK①各个模块中说明为STAC523)类别名类别名是用单引号括起来的字符串,它将在链接时决定各逻辑段的装入顺序。链接时,同类别的逻辑段将按照出现的先后顺序,被装入到连续的内存区中(但并不合并)。典型的类别名为‘STACK’、‘DATA’和‘CODE’,汇编程序也允许用户定义其他类别名。3)类别名53(2)段寄存器说明伪指令(ASSUME)格式1:
ASSUME段寄存器:段名[,段寄存器:段名,…]
作用:指示汇编程序通过哪个段寄存器去寻址指定的逻辑段,它设定特定的段寄存器指向特定的逻辑段。说明:①当汇编一条指令性语句时,汇编程序将通过ASSUME指令所指定的段寄存器去生成寻址存储器操作数的目标代码。没有AUUME指令所设定的指定关系,汇编程序将无法生成目标代码。②ASSUME伪指令一般放在代码段中SEGMENT伪指令的后面。③ASSUME指令只是通知汇编程序各个段寄存器与各个逻辑段之间的指定关系,并没有给段寄存器赋予实际的段地址,因此用户程序必须包含一段代码来完成这项工作。(2)段寄存器说明伪指令(ASSUME)54格式2:
ASSUME段寄存器:NOTHING[,段寄存器:NOTHING,…]
作用:取消前面的ASSUME伪指令所设定的对段寄存器的指定关系。格式2:55(3)段组定义伪指令(GROUP)格式:
组名GROUP段名,段名,…,段名组名--段组的标识符,表示段组的起始地址。段名--用SEGMENT语句定义的逻辑段名或用SEG操作符得到的段名功能:将不同段名的若干逻辑段集合成一个段组,并把这个段组存放到一个64KB的物理段中。于是段组内不同类型的逻辑段可以共用一个段寄存器,即可以使用同一个段寄存器来访问组内不同逻辑段中的变量,组内各段之间的跳转也都可以看成是段内跳转。(3)段组定义伪指令(GROUP)56说明:①如果ASSUME语句说明了段寄存器与段组之间的指定关系,则连接程序把段组内各段之中的所有标号和变量的偏移地址调整为相对于段组的起始地址。但是属性值表达式OFFSET标号(变量名)没有调整,它仍然还是相对于各自逻辑段的偏移量。当我们需要相对于段组起始地址的偏移量时,可使用以下表达式OFFSET组名:标号(变量名)在此,组名相当于段前缀。②定义一个段组后,组内各逻辑段并没有合并,它们仍然存在,因此用户仍然可以使用原来的方法对各段进行访问。说明:57DGROUP GROUP DATA1,DATA3DATA1 SEGMENTX DW ?DATA1 ENDSDATA3 SEGMENTZ DW ?DATA3 ENDSCODE SEGMENT ASSUME CS:CODE,DS:DGROUPSTART:MOVAX,DGROUP;组名是表示段组基地址的符号地址 MOVDS,AX MOVAX,X;MOVAX,[0000H] MOVAX,Z;MOVAX,[0010H] MOVBX,OFFSETZ;MOVBX,0000H
MOVBX,OFFSETDGROUP:Z;MOVBX,0010HCODE ENDS ENDSTARTDGROUP GROUP DATA1,DATA358五、过程的定义及其调用和返回
子程序结构是模块化程序设计思想的基础。在汇编语言中,子程序结构被设计为一个过程。(一)过程的定义过程定义伪操作的基本格式如下。 过程名 PROC [NEAR/FAR] ┇ [RET] ┇ RET 过程名 ENDP五、过程的定义及其调用和返回59(1)过程名过程标识符。在汇编语言源程序中,表示该过程存放在内存中的起始地址,即过程入口的符号地址。在汇编语言源程序中,过程名经常被用作子程序调用指令CALL的操作数。(2)NEAR/FAR
过程的两种类型属性。
①NEAR定义为NEAR属性的过程(近过程),只能被定义该过程的逻辑段内的CALL指令所调用(段内调用)。缺省时过程的类型默认为NEAR。
②FAR定义为FAR属性的过程(远过程),可以被任何逻辑段内的CALL指令所调用(段间调用)。(3)返回指令RET该指令是过程的出口,但不一定是过程的最后一条指令。一个过程可以有多条RET指令,但只能且至少要执行到一条RET指令。(1)过程名60说明:(1)如果一个过程被定义为NEAR类型/FAR类型,则当汇编到调用该过程的CALL语句时,汇编程序将自动将此CALL指令翻译为段内调用/段间调用的目标代码;而当汇编到该过程中的RET指令时,也会自动将这个RET指令翻译为段内返回/段间返回的目标代码。(2)过程类型属性的确定原则如下。如果被调用过程与CALL指令在同一个代码段内,则使用NEAR属性。如果被调用过程与CALL指令不在同一个代码段内,则使用FAR属性。说明:61(3)DOS入口主过程可以看作是DOS操作系统调用的一个子过程。此时,DOS入口主过程在用户定义的代码逻辑段中,而调用此过程的CALL指令则在DOS操作系统中,它们显然不在同一个代码段中,因此DOS入口主过程应该被定义为FAR类型。(4)对于CALL指令所在的逻辑段和被调用过程所在的逻辑段,如果它们的段名相同,段组合属性都是PUBLIC,则在链接时,这两个逻辑段将被合并为一个物理段,于是CALL指令和被调用过程就处在一个段中了。在这种情况下,被调用过程可以使用NEAR属性。(3)DOS入口主过程可以看作是DOS操作系统调用的一个子过62例1: CODE SEGMENT P1 PROCNEAR ADDCX,1 RET ;该指令被汇编为段内返回 P1 ENDP MAIN PROCFAR ┇ CALLP1;该指令被汇编为段内调用 ┇ RET ;该指令被汇编为段间返回 MAIN ENDP CODE ENDS ENDMAIN例1:63例2: CODE1 SEGMENT P1 PROCFAR ADDCX,1
RET
;该指令被汇编为段间返回 P1 ENDP CODE1 ENDS CODE2 SEGMENT MAIN PROCFAR ┇ CALLP1 ;该指令被汇编为段间调用 ┇ RET ;该指令被汇编为段间返回 MAIN ENDP CODE2 ENDS ENDMAIN例2:64(二)过程调用过程调用指令分为段内调用和段间调用两种类型。(1)段内调用
1)段内直接调用格式:
CALLDST其中DST表示转移目标地址,一般是被调用过程的过程名。操作:①PUSH(IP)把IP当前值压入堆栈。这个IP当前值就是下一条指令的偏移地址,即返回地址的偏移量部分。②(IP)←(IP)+D16修改指令指针寄存器IP,转移到目标地址。(二)过程调用65说明:①CALL指令的下一条指令的地址称为返回地址。当CPU执行CALL指令时,IP指向下一条指令,因此IP的当前值就是返回地址的偏移量部分,CALL指令的PUSH操作其实就是将返回地址的偏移量部分压入堆栈保存。②CALL指令的机器代码使用16位位移量D16来表示转向地址,因此这是一种相对转移方式,D16是转向地址与返回地址之间的差值。综上所述,该指令的功能就是首先将返回地址的偏移量部分压入堆栈,然后转移到目标地址DST处调用子过程。说明:662)段内间接调用格式:CALLREG16 ;REG16是16位通用寄存器操作数 CALLMEM16 ;MEM16是16位存储器操作数操作:①PUSH(IP)把IP当前值压入堆栈。这个IP当前值就是下一条指令的偏移地址,即返回地址的偏移量部分。②(IP)←(REG16)/(MEM16)修改指令指针寄存器IP,转移到目标地址2)段内间接调用67说明:①CALL指令的下一条指令的地址称为返回地址。当CPU执行CALL指令时,IP指向下一条指令,因此IP的当前值就是返回地址的偏移量部分,CALL指令的PUSH操作其实就是将返回地址的偏移量部分压入堆栈保存。②转向目标地址存放在指定的寄存器或存储单元中。使用寄存器寻址方式或任何一种存储器寻址方式即可寻址到转向目标地址。综上所述,该指令的功能就是首先将返回地址的偏移量部分压入堆栈,然后转移到目标地址(REG16)/(MEM16)处调用子过程。说明:68(2)段间调用指令1)段间直接调用格式:
CALLDST其中DST表示转移目标地址,一般是被调用过程的过程名。操作: PUSH(CS);将返回地址的全地址(CS):(IP)压入堆栈 PUSH(IP) (IP)←DST的偏移地址 (CS)←DST的段地址(2)段间调用指令69说明:CALL指令的下一条指令的地址称为返回地址。当CPU执行CALL指令时,IP指向下一条指令,CS指向当前代码段,因此IP的当前值就是返回地址的偏移量部分,CS的当前值就是返回地址的段基址部分,这条指令的两个PUSH操作实质上就是将返回地址的全地址压入堆栈中保存。因此简单地说,该指令的功能就是将返回地址的段基址和偏移量依次压入堆栈中保存,然后直接转移到目标地址DST处调用子过程。说明:702)段间间接调用格式:
CALLMEM32 ;MEM32是32位存储器操作数操作: PUSH(CS);将返回地址的全地址(CS):(IP)压入堆栈 PUSH(IP)(IP)←(MEM32)(CS)←(MEM32+2)2)段间间接调用71说明:①CALL指令的下一条指令的地址称为返回地址。当CPU执行CALL指令时,IP指向下一条指令,CS指向当前代码段,因此IP的当前值就是返回地址的偏移量部分,CS的当前值就是返回地址的段基址部分,这条指令的两个PUSH操作实质上就是将返回地址的全地址压入堆栈中保存。
②转向目标地址存放在指定的存储单元中,使用任何一种存储器寻址方式即可寻址到转向目标地址。因此简单地说,该指令的功能就是将返回地址的段基址和偏移量依次压入堆栈中保存,然后转移到目标地址(MEM32)处调用子过程。说明:72(三)过程返回子过程返回指令分为段内返回和段间返回两种类型。(1)段内返回
①段内普通返回格式:RET功能:转移到返回地址处,继续执行原来的程序。操作: POPIP;将堆栈栈顶内容弹出,存放到IP寄存器中, ;从而转移到返回地址处,继续执行原来的程序。(三)过程返回73②段内带立即数返回格式:RET整型数值表达式功能:转移到返回地址处继续执行原来的程序,同时修改SP指针。操作:POPIP(SP)←(SP)+表达式数值将堆栈栈顶内容弹出,存放到IP寄存器中,然后再修改堆栈指针SP。②段内带立即数返回74(2)段间返回指令
①段间普通返回格式:RET功能:转移到返回地址处,继续执行原来的程序。操作: POPIP POPCS将堆栈栈顶内容依次弹出,分别存放到IP和CS寄存器中,从而转移到返回地址处,继续执行原来的程序。(2)段间返回指令75②段间带立即数返回格式:RET整型数值表达式
功能:转移到返回地址处继续执行原来的程序,同时修改SP指针。操作: POPIP POPCS (SP)←(SP)+表达式数值将堆栈栈顶内容依次弹出,分别存放到IP和CS寄存器中,然后再修改堆栈指针SP。CALL指令和RET指令都不影响条件标志位。②段间带立即数返回76六、模块的定义与通信一个汇编语言源程序由若干个程序模块组成,而每个程序模块对应于一个.ASM源程序文件,是一个独立的汇编单位。当所有的程序模块单独汇编完毕后,它们必须通过LINK程序链接成一个完整的.EXE可执行程序文件。(1)模块定义伪指令(NAME/END)
格式: NAME模块名 ┇ END[标号]功能:定义一个可以独立编写及汇编的程序模块。六、模块的定义与通信77说明:(1)模块命名语句NAME可以省略,此时有以下两种情况。如果源程序中有TITLE语句,则模块名取TITLE语句中标题的前6个字符。如果源程序中没有TITLE语句,则模块所在的源程序文件名即为模块名。(2)模块结束语句END告诉汇编程序本模块到此结束。如果该模块是可执行程序的主模块,则END后必须紧跟标号或主过程名,告诉汇编程序此为本程序的启动地址。说明:78(2)模块通信伪指令本类指令解决各个程序模块之间的数据与过程的互访和共享问题。格式: PUBLIC名字,名字,┅,名字 EXTRN名字:类型,名字:类型,┅,名字:类型①名字
标号、变量名、过程名或由EQU/=伪指令定义的符号名。②类型各种类型代码,包括BYTE、WORD、DWORD、NEAR、FAR、ABS等等,其中ABS是用EQU伪指令定义的常量的属性。(2)模块通信伪指令79功能:(1)PUBLIC语句将指定的名字定义全局名字,允许应用程序中的其他程序模块直接引用。(2)EXTRN语句说明这些名字已经在其他程序模块中被定义为指定的类型,并被PUBLIC语句定义为全局名字。说明:PUBLIC语句与EXTRN语句通常要配对使用。功能:80七、宏指令语句
宏是源程序中具有独立功能的一段程序指令。(1)宏定义宏定义伪指令的格式如下: 宏指令名 MACRO [哑元,哑元,┅] ┇ ;宏体 ENDM其中,①宏指令名:代表宏体部分的内容,可看成是宏体部分的名字。②宏体:具有独立功能的一段指令。③哑元:宏定义的形式参数,每个哑元之间用逗号隔开。七、宏指令语句81例1: ;BL中的两位十进制数与CL中的两位十进制数相加,和放入BL中 ;CF反映进位情况。
ADD_DEC1 MACRO
MOV AL,BL ADD AL,CL DAA MOVBL,AL ENDM例2: ;X单元中的两位十进制数与Y单元中的两位十进制数相加, ;和放入X单元中,CF反映进位情况。
ADD_DEC2 MACRO X,Y
MOV AL,X ADD AL,Y DAA MOV X,AL ENDM例1: ;BL中的两位十进制数与CL中的两位十进制数相加,和82(2)宏调用
宏指令被定义后,用户就可以在源程序中调用这个宏指令。调用宏指令的操作称为宏调用,宏调用的格式如下。
宏指令名 [实元,实元,…]例1: ADD_DEC1例2: ADD_DEC2[SI],[DI](2)宏调用83(3)宏展开在汇编过程中,汇编程序将对每个宏调用进行宏展开。宏展开操作如下。①用宏体来替换源程序中的宏指令名;
②用实元(实际参数)来替换宏体中的哑元(形式参数)。替换方法:用第一个实元替换第一个哑元,用第二个实元替换第二个哑元,┅,依次类推。宏展开后得到的所有语句都应该是有效的,否则汇编程序将指示出错。一般来说,实元个数应该和哑元个数相等,但汇编程序并不要求它们必须相等。
•如果实元个数大于哑元个数,则多余的实元不予考虑;
•如果实元个数小于哑元个数,则多余的哑元作“空”处理。(3)宏展开84宏展开后例1: MOVBL,34HMOVCL,56H
ADD_DEC1MOV BL,34HMOV CL,56H
MOV AL,BL ADD AL,CL DAA MOVBL,AL宏展开后例2: MOVBYTEPTR[SI],34HMOVBYTEPTR[DI],56HADD_DEC2[SI],[DI]MOVBYTEPTR[SI],34HMOVBYTEPTR[DI],56HMOVAL,[SI]ADDAL,[DI]DAAMOV[SI],AL宏展开后例1: MOV BL,34H宏展开后85(4)宏定义中的参数
①分隔操作符&
在宏定义体中,分隔操作符&可用作哑元与其他符号之间的分隔符。宏展开时,汇编程序将把&前后的两个符号合并成一个符号,这个符号可以是操作码、操作数、或是一个字符串。例3:宏定义: MSG MACRONUM,NAME MSG&NUM DB ‘HELLOMR.&NAME’ ENDM宏调用: MSG1,TAYLOR宏展开: MSG1 DB ‘HELLOMR.TAYLOR’(4)宏定义中的参数
86②%操作符格式:%表达式功能:该表达式用在宏调用语句中,充当实元。在宏展开时,汇编程序将计算%之后的表达式的值,并将之转换为当前基数下的数,然后用这个数值充当实元来取代哑元。②%操作符87例:宏定义: MSG MACRO COUNT,STRING MSG&COUNT DB STRING ENDM ERRMSGMACROTEXT CNTR=CNTR+1 MSG%CNTR,TEXT ENDM宏调用: CNTR=0 ERRMSG‘SYNTAXERROR’ ERRMSG‘INVALIDOPERAND’宏展开: MSG1 DB ‘SYNTAXERROR’ MSG2 DB ‘INVALIDOPERAND’例:88注意:①宏展开时的“实元替代哑元”完全是一种符号替代,即用实元符号替代哑元符号。即使实元符号是一个用EQU(=)伪操作定义的符号,当进行宏展开替换时,替代哑元的是这个实元符号,而不是它所代表的表达式。注意:89宏展开宏展开例: messgen macro x message db‘&x’ db x endm op equ 10messgen opmessage db‘op’ dbopmessgen %opmessage db‘10' db10汇编message┇‘o’ASCII码‘p’ASCII码0AH┇汇编message┇31H30H0AH┇宏展开宏展开例: messgen macro xmessge90②无论在宏定义体还是在宏调用表达式中,“空格”是各种符号(包括实元符号)之间的分隔符。例如: add_dec macro x,y push ax mov al,byteptrx add al,byteptry daa mov x,al pop ax endm宏展开add_dec [si][di]PushaxMoval,byteptr[si]Addal,byteptr[di]daaMovx,alPopax②无论在宏定义体还是在宏调用表达式中,“空格”是91(5)LOCAL伪指令
如果在宏定义体内定义了一个标号,并且在源程序中该宏被多次调用,那么在宏展开后,将会出现该标号的多重定义。宏定义:ABSOL MACRO X CMP X,0 JGE NEXT NEG XNEXT: ENDM宏调用:ABSOL AX
ABSOL BX
ADD AX,BX
宏展开: CMP AX,0 JGE NEXT NEG AXNEXT:
CMP BX,0 JGE NEXT NEG BXNEXT:
ADD AX,BX汇编程序不允许标号重复定义,因此当汇编程序汇编到第二个NEXT标号时,将会发出错误提示。为避免出现这种情况,可使用LOCAL伪操作。(5)LOCAL伪指令
宏定义:宏展开:汇编程92LOCAL伪操作格式:
LOCAL局部标号,局部标号,┅功能:汇编程序为每一个局部标号建立一个新的符号(??0000~??FFFF),以代替宏展开中的每一个局部标号。宏定义:ABSOL MACROX LOCALNEXT CMPX,0 JGENEXT NEGXNEXT: ENDM宏调用:ABSOL AX
ABSOLBXADDAX,BX宏展开: CMPAX,0 JGENEXT NEGAX??0000:
CMPBX,0 JGENEXT NEGBX??0001: ADDAX,BXLOCAL伪操作格式:宏定义:宏展开:93LOCAL伪操作只能用在宏定义体内,而且它必须是MACRO伪操作后的第一个语句,在MACRO和LOCAL伪操作之间,不允许有注释和分号标志。(6)取消宏指令名伪指令(PURGE)
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- GB/T 48246-2026飞机静止变流器
- T/ZSA 159-2023卫星遥感监测规范 城市管理事件线索
- T/JSJTQX 71-2025毫米级域激光法沥青路面摊铺施工技术规程
- T/CNSC 001-2024荒漠地区(沙漠、沙地和戈壁)光伏工程生态影响监测与评价
- T/CCASC 0055-2025工业氯化石蜡
- T/CSEA 45-2025热浸镀锌钢板无铬钝化剂
- GB/T 34255-2026聚丁二酸-己二酸丁二酯(PBSA)树脂
- AI在口腔护理行业的智能刷牙指导
- 2026年《护理文书书写规范》培训考试题及答案
- PG岗位新人面试题及详细参考答案(零基础适配版)
- 2026小学生科普常识知识竞赛题及答案
- 2026年名著长征试题(附答案)
- 抗美援朝纪念日致敬英雄课件
- 2026年交管12123科目一考试真题及详细答案解析
- 2026中国零碳产业园能源系统设计与投资回报分析报告
- 优必选机器人介绍主题课件
- CSCO神经内分泌肿瘤诊疗指南(2026版)
- 2026年保密教育线上培训考试试题(附完整答案)
- 2026年高考广东卷化学高考真题(含答案)
- 2026年永州职业技术学院单招职业技能考试题库及答案
- 科特迪瓦可可产业投资前景与产业链深度研究
评论
0/150
提交评论