收藏 分享(赏)

9--汇编语言的伪指令语句.ppt

上传人:scg750829 文档编号:7268833 上传时间:2019-05-12 格式:PPT 页数:104 大小:351.50KB
下载 相关 举报
9--汇编语言的伪指令语句.ppt_第1页
第1页 / 共104页
9--汇编语言的伪指令语句.ppt_第2页
第2页 / 共104页
9--汇编语言的伪指令语句.ppt_第3页
第3页 / 共104页
9--汇编语言的伪指令语句.ppt_第4页
第4页 / 共104页
9--汇编语言的伪指令语句.ppt_第5页
第5页 / 共104页
点击查看更多>>
资源描述

1、(三)汇编语言的伪指令语句一、符号定义伪指令语句为一个表达式或指令助记符赋予一个符号名。在后继程序文本中,可以使用该符号名来替代这个表达式或指令助记符。(1)等值语句 EQU格式:符号名 EQU 表达式/指令助记符 例如:PORT1 EQU 312 ;为数值常量312赋予符号名PORT1PORT2 EQU PORT1+1 ;为数值表达式赋予符号名PORT2ADDR EQU ES:SI+4 ;为地址表达式定义一个名字STRING EQU COMPUTER ;为字符串常量定义一个名字COUNT EQU CX ;为寄存器CX定义新的符号名LD EQU MOV ;为助记符MOV定义新的符号名LD,说明

2、: 在EQU语句的表达式中,如果有标号名或变量名,则该语句必须放在它们的定义语句之后。例如AB EQU DATA+2 必须放在标识符DATA的定义之后,否则汇编程序将指示以下错误:Symbol not defined: DATA 后面的EQU伪操作可以利用前面的EQU伪操作已经定义的符号名。 例如: ALPHA EQU 7 ;给数值7 赋以符号名ALPHABETA EQU ALPHA-2 ;给7-2=5赋以符号名BETAADDR EQU VAR + BETA ;给VAR+5赋以符号名ADDR, 使用EQU伪操作定义过的符号名不允许重复定义。例如:EMP EQU 0 ;给数值7赋以符号名ALPH

3、AEMP EQU EMP+1 ;汇编该语句时,汇编程序将指示出错。(2)等号语句 =格式:符号名 = 表达式/指令助记符该语句的功能与EQU完全相同,唯一的区别是:该语句可以对符号名进行重复定义。例如:EMP = 0 ;定义符号名EMP为0EMP = EMP+1 ;重新定义符号名EMP为1,完全合法。,二、数据定义伪指令语句数据定义语句用于定义变量,该语句指定变量的名称和变量的类型,并为该变量分配存储单元。,(1)数据定义语句的格式变量名 数据定义符 操作数 ,操作数 ,操作数 其中, 变量名:可选项。 操作数:赋给变量的初值,多个相同类型的变量可在一条语句中定义。 数据定义符常用数据定义符有

4、以下三种。 DB :定义字节变量,每个变量占有1个字节的存储单元。 DW :定义字变量,每个变量占有2个字节的存储单元。 DD :定义双字变量,每个变量占有4个字节的存储单元。此外,还有DQ、DF和DT等类型。对于多字节变量,其变量值的内存存放规则是,低位字节占低地址单元,高位字节占高地址单元。,说明:经过定义的变量必然具有以下三个属性。 数据类型字节、字、双字等等。 偏移地址分配给该变量的存储单元的偏移地址。 段基址分配给该变量的存储单元的段基址,也就是定义该变量的逻辑段的段基址。,(2)数据定义语句的具体形式和功能根据操作数的不同表达形式 ,常见的数据定义语句有以下几种具体形式。 操作数是

5、一个数值常量例如:X DB 25H ;定义一个名为 X、初值为25H的字节变量Y DW 4142H ;定义一个名为 Y、初值为4142H的字变量Z DD 12345678H ;定义一个名为 Z、初值为12345678H的双字变量,X,25H,Y,42H,41H,Z,78H,56H,34H,12H,汇编时,汇编程序将完成以下工作: 首先,定义名为 X 的字节变量,并为其分配一个字节单元,然后再把初值25H装入该单元中。 随后,定义名为 Y 的字变量,并为其分配一个字单元,然后再把初值4142H装入该单元中。 最后,定义名为 Z 的双字变量,并为其分配一个双字单元,然后再把初值12345678H装

6、入该单元中。, 操作数是一个数值表达式例如:PORT EQU 80HOUT_PORT DW PORT +1汇编程序将定义一个名为OUT_PORT的字类型变量,并为其分配一个字单元,然后计算数值表达式(PORT+1)的数值,并把计算结果0081H装入该单元中。,OUT_PORT,81H,00H, 操作数部分使用问号 ?例如:A DB ? ;定义字节变量A,并为其分配一个字节单元B DW ? ;定义字变量B,并为其分配一个字单元汇编程序只为变量分配存储单元,并不赋予其具体的初值,该变量的初值不确定。,A,B, 操作数部分是用逗号分隔的若干个操作数例如:TABLE DW 1,2,3,TABLE,01

7、H,00H,02H,00H,03H,00H,汇编程序首先定义一个名为TABLE的字类型变量,并为该变量分配一个字单元,再将变量初始值0001H装入其中。然后,再为一个无名字变量分配一个字单元,并将变量初始值0002H装入其中。最后,再为一个无名字变量分配一个字单元,并将变量初始值0003H装入其中。,这个数据定义语句定义了三个变量,第一变量的变量名为TABLE,其它两个变量没有变量名。但是由于这三个变量的存储单元依次排列,具有线性存储特性,因此我们可以将这种数据定义语句看成是数组变量的定义语句,并将第一个变量的变量名TABLE看成是数组变量名,将这三个变量看成是该数组的数组元素。于是各数组元素

8、的访问地址可以用下式来确定。数组元素地址 = 数组变量名 + 数组元素下标值 * 数组元素字节大小,TABLE,01H,00H,02H,00H,03H,00H,MOV AX,TABLE ;(AX)=0001H MOV AX,TABLE+1*2 ;(AX)=0002H MOV AX,TABLE+2*2 ;(AX)=0003H,在定义数组变量时,可以使用重复操作符DUP 来定义各个数组元素,其定义格式如下。重复次数 DUP(操作数1,操作数N)这个表达形式的含义是,将括号中的N个操作数,以指定的次序,重复指定次数。其中,重复次数字段是值为正整数的数值表达式 。 例如:TABLE DB 2 DUP(

9、0,1),2 TABLE DB 0,1,0,1,2注意:DUP重复操作符可以嵌套使用,例如以下两式是等价的。TABLE DB 2 DUP(2 DUP(1,2),3)TABLE DB 1,2,1,2,3,1,2,1,2,3,C,D,A,B, 操作数是一个字符串常量例如: STRING DB ABCDEF该语句定义了一个字符数组变量STRING 。汇编程序将为这个数组变量分配一个数据区,并将字符串中每一个字符的ASCII码依次装入到数据区的各个字节单元中。,STRING,41H,42H,43H,44H,E,F,45H,46H,STRING2,注意: 当字符串长度超过两个字符时,伪指令定义符只能使用

10、 DB 。 当字符串长度不超过两个字符时,伪指令定义符 DB、DW、DD、DQ 等都可以使用,但它们的意义有所不同。例如: STRING1 DB ABSTRING2 DW AB,B,A,A,B,STRING1,41H,42H,42H,41H,MOV AL,STRING1 ;(AL)= 41H MOV AL,STRING1 + 1 ;(AL)= 42H MOV AX,STRING2 ;(AX)= 4142H,X,ADDR2, 操作数是一个存储器地址(标号、过程名或变量名)例:X DB 10HADDR1 DW XADDR2 DD X,ADDR1,变量X的偏移地址的低字节,变量X的偏移地址的高字节,

11、变量X的偏移地址的低字节,变量X的偏移地址的高字节,变量X的段基址的低字节,变量X的段基址的高字节,10H,当操作数是一个存储器地址时,数据定义符只能使用 DW 或 DD。此时汇编程序将使用这个存储器地址的偏移地址(DW)或全地址(DD)来初始化变量。全地址的存放格式是,16位偏移地址放在低地址单元,16位段地址放在高地址单元。, 操作数是如下形式的地址表达式标号或变量名 结果为整数的数值表达式这个地址表达式的运算结果仍然表示一个标号或变量,其类型属性和段基址属性与原来的标号或变量相同,只有其偏移量属性产生相应的增减。因此,汇编程序对这个表达式的处理完全等同于处理一个存储器地址。数据定义符只能

12、使用 DW 或 DD,汇编程序将使用这个新存储器地址(地址表达式的运算结果)的偏移地址(DW)或 全地址(DD)来初始化变量。,例如:X DB 10HADDR1 DW X+1ADDR2 DD X+1汇编第2条语句时,汇编程序将存储器地址X+1的偏移地址装入到分配给变量ADDR1的双字节存储单元内。汇编第3条语句时,汇编程序将存储器地址X+1的全地址装入到分配给变量ADDR2的双字存储单元内。其中16位偏移地址被存放在低字单元内,16位段地址被存放在高字单元内。, 操作数是如下形式的数值表达式变量名1 - 变量名2 或者标号1 - 标号2 其中,变量名1和变量名2:同一逻辑段内定义的两个变量名。

13、标号1和标号2:同一代码段内定义的两个标号。同一逻辑段内的两个标号或变量名的相减结果是一个数值,它表示两者之间相距的字节数。,TABLE2,LENGTH1,LENGTH2,TABLE1,01H,02H,03H,04H,05H,06H,04H,02H,例如:TABLE1 DB 1,2,3,4TABLE2 DB 5,6LENGTH1 DB TABLE2 - TABLE1LENGTH2 DB LENGTH1 - TABLE2,说明:数据定义语句定义了变量的数据类型,汇编程序可以利用这种隐含的类型属性来确定某些指令是字指令、还是字节指令。例如:OPER1 DB ?,?OPER2 DW ?,?MOV O

14、PER1 + 1,0 ;字节指令MOV OPER2 + 2,0 ;字指令MOV OPER1 + 1,AL ;字节指令MOV OPER2 + 1,AX ;字指令,(3)分析运算符(SEG、OFFSET、TYPE、SIZE、LENGTH)分析运算符作用于变量或标号,运算结果为变量或标号的属性值,其使用格式为:运算符 变量/标号 SEG和OFFSET运算符SEG和OFFSET运算分别返回变量或标号的段地址和偏移地址。例如:ARRAY DB 100 DUP(0) ;定义字节数组变量ARRAYMOV AX,SEG ARRAY ;变量ARRAY的段地址(AX)MOV DX,AXMOV BX,OFFSET

15、ARRAY ;变量ARRAY的偏移地址(BX)MOV AL,BX, TYPE、 LENGTH 和SIZE操作符TYPE操作符返回一个表示变量类型或标号类型的数值。变量的类型值是变量的字节长度值;标号的类型值只起区别作用,没有实际物理意义。,在数组变量定义语句中,如果第一个操作数项使用DUP运算符定义,则该数组变量的LENGTH运算结果是此DUP运算符前面的重复次数,其它一切情况下,返回1。SIZE运算符的运算结果为TYPE运算结果和LENGTH运算结果的乘积,表示分配给数组变量的字节总数。例如:BUFFER1 DB 100 DUP(0)BUFFER2 DW 200 DUP(20H)BUFFER

16、3 DD 100 DUP(13) 则有:TYPE BUFFER1=1 LENGTH BUFFER1= 100 SIZE BUFFER1=100TYPE BUFFER2=2 LENGTH BUFFER2= 200 SIZE BUFFER2=400TYPE BUFFER3=4 LENGTH BUFFER3= 100 SIZE BUFFER3=400,(4)合成运算符( PTR、THIS )合成运算符作用于变量或标号,对原变量或标号的类型属性进行修改,从而建立起一个新的变量或标号。 PTR 运算符该运算符采用原变量或标号的段属性和偏移地址属性,指定一个新的类型属性,从而建立起一个新的变量或标号,而原

17、变量或标号的类型属性不变。例1: ARRAY1 DB 0,1,2,3 ;定义字节数组变量ARRAY1ARRAY2 DW 4,5,6,1234H ;定义字数组变量ARRAY2MOV BX,WORD PTR ARRAY1 ;0100H (BX)MOV CL,BYTE PTR (ARRAY2 + 3*2) ;34H (CL)MOV WORD PTR SI,4 ;0004H SI所指向的字单元,配合EQU伪指令,我们可以定义新的变量名。 例如:ARRAY1 DB 0,1,2,3 ;定义字节数组变量ARRAY1ARRAY2 DW 4,5,6,1234H ;定义字数组变量ARRAY2 W EQU WORD

18、 PTR ARRAY1B EQU BYTE PTR ARRAY2新变量W和B的段地址和偏移地址分别与ARRAY1和ARRAY2相同,只是它们的类型已经发生变化。在后面的程序中,可以直接使用这两个新定义的变量。MOV BX,W + 3 ;0403H (BX)MOV CL,B + 6 ;34H (CL), THIS 操作符THIS操作符为当前存储单元(当前地址计数器所指向的存储单元)设定一个指定类型,并与EQU伪操作配合使用,建立起一个新的变量或标号。其使用格式如下。变量或标号名 EQU THIS 类型代码 例:B EQU THIS BYTEARRAY DW 100 DUP(?)100个字的字数组

19、ARRAY也可以按200个字节的字节数组B来使用。, LABEL 伪操作LABEL伪操作为当前存储单元(当前地址计数器所指向的存储单元)定义一个指定类型的变量或标号。该操作符常用于设定一个数据块的属性,使其具有多重名字和属性,其使用格式如下。标号或变量名 LABEL 类型代码例:ARRAY1 LABEL WORD ;定义一个名为ARRAY1的字数组变量ARRAY2 DB 1,2,3,4 ;定义一个名为ARRAY2的字节数组变量MOV AL,ARRAY2 ;01H (AL)MOV AX,ARRAY1 ;0201H (AX)ARRAY1和ARRAY这两个变量都指向同一个数据块,具有相同的段属性和偏

20、移量属性,但是它们的类型属性不同。程序员可以根据需要按不同类型去操作数据块中的数据。,三、地址计数器与对准伪操作 (1)地址计数器地址计数器是一种指针部件,其内容是当前逻辑段内某个存储单元的段内偏移地址。当汇编程序处理一个数据项或一条指令时,汇编程序将把该数据项或该指令的目标代码存放到地址计数器所指示的存储单元内。当汇编程序处理一个数据项或一条指令时,地址计数器的内容就是存放该数据项或该指令目标代码的存储单元的偏移地址。,地址计数器的工作过程如下。 每当开始汇编一个逻辑段时,地址计数器的内容就被初始化为零,表示段内数据或指令目标代码将从段内偏移地址为零的位置处开始存放。 当汇编程序把一条指令的

21、目标代码存放到地址计数器所指向的存储单元后,地址计数器的内容就增加一个大小为该指令字节数的数值,指向下一条指令将要被存放的位置。 当汇编程序把一个数据项存放到地址计数器所指向的存储单元后,地址计数器的内容增加一个大小为该数据项字节数的数值,指向下一个数据项将要被存放的位置。,在汇编过程中,汇编程序所进行的指令代码存放、变量存储单元分配、变量初值装入等工作,正是在地址计数器的引导下来完成的。在汇编语言源程序中,用户可以使用符号$来表示地址计数器的当前值,表示存放当前数据项或当前指令目标代码的存储单元的偏移地址。,例1:JNE $+6地址计数器的当前值$为存放该指令的存储单元的偏移地址,因此有指令

22、转向地址 = 指令的首地址 + 6由于该指令是2字节指令,因此处理该指令时的IP当前值为IP当前值 = 指令的首地址 + 2 于是有位移量 = 转向地址 IP当前值 = 4该指令的机器代码为:75 04,例2:假设汇编处理时,变量ARRAY被分配的偏移地址为0074H,求该语句的汇编结果。ARRAY DW 1,2,$+4,3,4,$+4解:当汇编程序处理第三个数据项($+4)时地址计数器值的当前值$ = 0074H + 2 * 2 = 0078H,于是有$+4 = 0078H + 4 = 007CH当汇编程序处理第六个数据项($+4)时,地址计数器值的当前值$ = 0074H + 2 * 5

23、= 007EH,于是有 $+4 = 007EH + 4 = 0082H因此,原来的语句等效于ARRAY DW 1,2,7CH,3,4,82H,(2)对准伪操作对准伪操作都是针对地址计数器的各种操作。1)指定地址伪指令(ORG)强行指定地址计数器的当前值,以改变该指令之后的代码或数据块在段内存放的偏移地址。格式1: ORG 表达式功能:直接将表达式的运算结果(0 65535)送入地址计数器。,格式2: ORG $ + 表达式功能:将汇编该语句时的地址计数器当前值$加上表达式的数值,然后将最终结果送入地址计数器。说明:通过执行ORG伪指令,汇编程序将以(表达式)或($ + 表达式)的运算结果为起点

24、,来存放ORG语句之后定义的代码或数据。,例:DATA SEGMENT ORG 10H ; X DB 20H,30HORG $ + 5 ;Y DB 40H,50HDATA ENDS说明: 将地址计数器的内容设置为10H,即从DATA数据段内偏移地址为10H的存储单元开始,存放后继数据20H和30H。 处理该语句时,地址计数器的内容为12H,$+5 = 12H + 5 = 17H,于是该语句将地址计数器的内容设置为17H,即从DATA数据段内偏移地址为17H的存储单元开始,存放后继数据40H和50H。,2)EVEN伪操作格式: EVEN功能:将地址计数器的内容设置为大于或等于当前值的最小偶数值,

25、以使后继语句所定义的变量或指令开始于偶数地址。说明:字数据的地址最好是偶数。为保证字数组从偶地址开始,可以在其前使用EVEN伪操作。,3)ALIGN伪操作格式: ALIGN 数值表达式(运算结果必须是2的幂,即2、4、8等等)功能:将地址计数器的内容设置为大于或等于当前值的最小的数值表达式运算结果的整数倍值,以使后继语句所定义的变量或指令开始于字边界、双字边界、4字边界等等。说明:该伪操作可用于定位双字数组、4字数组等等操作。,四、程序分段伪指令语句程序分段伪指令语句用于指示汇编程序和链接程序如何以逻辑段为基本单位来组织程序和分配存储器。,(1)段定义伪指令(SEGMENT/ENDS)段定义伪

26、指令SEGMENT/ENDS用于定义一个逻辑段,指出该逻辑段的段名、段属性以及段的开始和结束位置。格式:段名 SEGMENT 定位类型 组合类型 类别名段体段名 ENDS 其中,段名:逻辑段的标识符。在汇编语言源程序中,表示链接程序分配给该逻辑段的段基址。段体:逻辑段内的汇编语句序列。定位类型、组合类型和类别名:逻辑段的三个属性。,1)定位类型 当编制完成汇编语言源程序后,我们需要继续进行以下处理。 首先使用汇编程序对汇编语言源程序进行汇编处理,得到目标代码文件(.OBJ);其次使用链接程序对目标代码文件进行链接处理,得到可执行文件(.EXE)。这个可执行文件就是可以在操作系统中运行的可执行程

27、序。 在目标代码文件(.OBJ)中,汇编程序只是对各个逻辑段内的汇编语句进行了初步处理,并没有确定各个逻辑段的存储位置,因此对于标号、变量名和过程名,其段地址还没有确定,其段内偏移地址也只是初步确定下来,需要在随后的链接处理中再进一步修正。 链接处理时,链接程序将在起始地址为00000H的地址空间中,确定所有逻辑段的存储位置,即把所有的逻辑段链接起来。 链接处理后,所有标号、变量名和过程名的段内偏移地址都被确定下来了,而这些名字的段地址则只是一个初步数值,只有在加载运行该程序时,再由操作系统进一步确定这些名字的实际段地址。 逻辑段定义语句所指定的三个段属性就是告诉链接程序如何确定本逻辑段的存储

28、位置。,定位类型参数 指示链接程序将本逻辑段定位在指定的地址边界上。 该参数共有下表所示的五种。,STACK SEGMENT STACKDB 10 DUP(0) STACK ENDSdata1 segment array1 db 1, 2, 3 data1 endsdata2 segment array2 dw 1, 2, 3 data2 ends,code1 segmentassume cs:code1,ds:data1 start: mov ax, data1mov ds, axmov al, array1 code1 endscode2 segmentassume cs:code2,ds

29、:data2mov ax, data2mov ds, axmov ax,array2 code2 endsend start,00009 H,00012 H,00010 H,00011 H,STACK段,00000 H,0,0,data1段,01H,02H,03H,00025 H,data2段,00020 H,01H,00H,03H,00H,00037 H,00030 H,Code1 段,00047 H,00040 H,Code2 段,STACK段段地址 = 0000Hdata1段段地址 = 0001H 变量array1的段地址 = 0001H 变量array1的偏移地址 = 0000Hdat

30、a2段段地址 = 0002H 变量array2的段地址 = 0002H 变量array2的偏移地址 = 0000Hcode1段段段地址 = 0003H 标号start的段地址 = 0002H 标号start的偏移地址 = 0000H,STACK SEGMENT STACKDB 10 DUP(0) STACK ENDSdata1 segment byte array1 db 1, 2, 3 data1 endsdata2 segment byte array2 dw 1, 2, 3 data2 ends,code1 segment byteassume cs:code1,ds:data1 sta

31、rt: mov ax, data1mov ds, axmov al, array1 code1 endscode2 segment byteassume cs:code2,ds:data2mov ax, data2mov ds, axmov ax,array2 code2 endsend start,00009 H,0000C H,0000A H,0000B H,STACK段,00000 H,0,0,0,data1段,01H,02H,03H,00012 H,data2段,0000D H,01H,00H,02H,00H,03H,00H,0001A H,code1段,00013 H,00022 H

32、,code2段,0001B H,STACK段段地址 = 0000Hdata1段段地址 = 0000H 变量array1的段地址 = 0000H 变量array1的偏移地址 = 000AHdata2段段地址 = 0000H 变量array2的段地址 = 0000H 变量array2的偏移地址 = 000DHcode1段段段地址 = 0001H 标号start的段地址 = 0001H 标号start的偏移地址 = 0003H,2)组合类型 一个汇编语言源程序可能包含了若干个程序模块,而不同的程序模块又有可能包含了相同名字的逻辑段。 组合类型参数指定了同名逻辑段的合并方法,也就是说,当链接各个程序模

33、块.OBJ时,链接程序将按照组合类型参数所指定的方法来合并各个程序模块中的同名逻辑段。,程序文件1 STACK SEGMENT STACKDB 10 DUP(0) STACK ENDS data segment byte array1 db 1, 2, 3 data ends code segment byteassume cs:code, ds:data start: mov ax, datamov ds, axmov al, array1 code endsend start,程序文件2 STACK SEGMENT STACKDB 10 DUP(0) STACK ENDS data seg

34、ment array2 dw 1, 2, 3 data ends code segmentassume cs:code, ds:datamov ax, datamov ds, axmov ax, array2 code endsend,00013 H,00016 H,00014 H,00015 H,STACK段,00000 H,0,0,data段,01H,02H,03H,00025 H,data段,00020 H,01H,00H,02H,00H,03H,00H,0001E H,00017 H,文件1Code段,00037 H,00030 H,文件2Code段,STACK段段地址 = 0000H

35、文件1data段段地址 = 0001H 变量array1的段地址 = 0001H 变量array1的偏移地址 = 0004H文件2data段段地址 = 0002H 变量array2的段地址 = 0002H 变量array2的偏移地址 = 000DH文件1code段段地址 = 0001H 标号start的段地址 = 0001H 标号start的偏移地址 = 0007H文件2code段段地址 = 0003H,程序文件1 STACK SEGMENT STACKDB 10 DUP(0) STACK ENDS data segment byte public array1 db 1, 2, 3 data

36、 ends code segment byte publicassume cs:code, ds:data start: mov ax, datamov ds, axmov al, array1 code endsend start,程序文件2 STACK SEGMENT STACKDB 10 DUP(0) STACK ENDS data segment public array2 dw 1, 2, 3 data ends code segment publicassume cs:code, ds:datamov ax, datamov ds, axmov ax, array2 code en

37、dsend,00013 H,00022 H,00020 H,00021 H,STACK段,00000 H,0,0,data段,01H,02H,03H,00035 H,Code段,00030 H,01H,00H,02H,00H,03H,00H,00047 H,00040 H,文件1Code 段,00057 H,00050 H,文件2Code 段,STACK段段地址 = 0000Hdata段段地址 = 0002H 变量array1的段地址 = 0002H 变量array1的偏移地址 = 0000H变量array2的段地址 = 0002H 变量array2的偏移地址 = 0010Hcode段段地址

38、= 0004H 标号start的段地址 = 0004H 标号start的偏移地址 = 0000H,3)类别名类别名是用单引号括起来的字符串,它将在链接时决定各逻辑段的装入顺序。链接时,同类别的逻辑段将按照出现的先后顺序,被装入到连续的内存区中(但并不合并)。典型的类别名为STACK、DATA和CODE,汇编程序也允许用户定义其他类别名。,(2)段寄存器说明伪指令(ASSUME)格式1: ASSUME 段寄存器:段名 ,段寄存器:段名, 作用:指示汇编程序通过哪个段寄存器去寻址指定的逻辑段,它设定特定的段寄存器指向特定的逻辑段。说明: 当汇编一条指令性语句时,汇编程序将通过ASSUME指令所指定

39、的段寄存器去生成寻址存储器操作数的目标代码。没有AUUME指令所设定的指定关系,汇编程序将无法生成目标代码。 ASSUME伪指令一般放在代码段中SEGMENT伪指令的后面。 ASSUME指令只是通知汇编程序各个段寄存器与各个逻辑段之间的指定关系,并没有给段寄存器赋予实际的段地址,因此用户程序必须包含一段代码来完成这项工作。,格式2: ASSUME 段寄存器:NOTHING ,段寄存器:NOTHING, 作用:取消前面的ASSUME伪指令所设定的对段寄存器的指定关系。,(3)段组定义伪指令(GROUP)格式: 组名 GROUP 段名,段名, ,段名组名 - 段组的标识符,表示段组的起始地址。段名

40、 - 用SEGMENT语句定义的逻辑段名或用SEG操作符得到的段名功能:将不同段名的若干逻辑段集合成一个段组,并把这个段组存放到一个64KB的物理段中。于是段组内不同类型的逻辑段可以共用一个段寄存器,即可以使用同一个段寄存器来访问组内不同逻辑段中的变量,组内各段之间的跳转也都可以看成是段内跳转。,说明: 如果ASSUME语句说明了段寄存器与段组之间的指定关系,则连接程序把段组内各段之中的所有标号和变量的偏移地址调整为相对于段组的起始地址。但是属性值表达式OFFSET 标号(变量名) 没有调整,它仍然还是相对于各自逻辑段的偏移量。当我们需要相对于段组起始地址的偏移量时,可使用以下表达式OFFSE

41、T 组名:标号(变量名) 在此,组名相当于段前缀。 定义一个段组后,组内各逻辑段并没有合并,它们仍然存在,因此用户仍然可以使用原来的方法对各段进行访问。,DGROUP GROUP DATA1, DATA3 DATA1 SEGMENT X DW ? DATA1 ENDSDATA3 SEGMENT Z DW ? DATA3 ENDSCODE SEGMENTASSUME CS:CODE, DS:DGROUP START: MOV AX, DGROUP ;组名是表示段组基地址的符号地址MOV DS, AXMOV AX, X ; MOV AX, 0000HMOV AX, Z ; MOV AX, 0010

42、HMOV BX, OFFSET Z ; MOV BX, 0000HMOV BX, OFFSET DGROUP:Z ; MOV BX, 0010H CODE ENDSEND START,五、过程的定义及其调用和返回子程序结构是模块化程序设计思想的基础。在汇编语言中,子程序结构被设计为一个过程。(一)过程的定义过程定义伪操作的基本格式如下。过程名 PROC NEAR / FAR RETRET过程名 ENDP,(1)过程名过程标识符。在汇编语言源程序中,表示该过程存放在内存中的起始地址,即过程入口的符号地址。在汇编语言源程序中,过程名经常被用作子程序调用指令CALL的操作数。(2)NEAR / FA

43、R过程的两种类型属性。 NEAR定义为NEAR属性的过程(近过程),只能被定义该过程的逻辑段内的CALL指令所调用(段内调用)。缺省时过程的类型默认为 NEAR 。 FAR定义为FAR属性的过程(远过程),可以被任何逻辑段内的CALL指令所调用(段间调用)。(3)返回指令RET该指令是过程的出口,但不一定是过程的最后一条指令。一个过程可以有多条RET指令,但只能且至少要执行到一条RET指令。,说明: (1)如果一个过程被定义为NEAR类型/FAR类型,则当汇编到调用该过程的CALL语句时,汇编程序将自动将此CALL指令翻译为段内调用/段间调用的目标代码;而当汇编到该过程中的RET指令时,也会自

44、动将这个RET指令翻译为段内返回/段间返回的目标代码。(2)过程类型属性的确定原则如下。 如果被调用过程与CALL指令在同一个代码段内,则使用NEAR属性。 如果被调用过程与CALL指令不在同一个代码段内,则使用FAR属性。,(3)DOS入口主过程可以看作是DOS操作系统调用的一个子过程。此时, DOS入口主过程在用户定义的代码逻辑段中,而调用此过程的CALL指令则在DOS操作系统中,它们显然不在同一个代码段中,因此DOS入口主过程应该被定义为FAR类型。 (4)对于CALL指令所在的逻辑段和被调用过程所在的逻辑段,如果它们的段名相同,段组合属性都是PUBLIC,则在链接时,这两个逻辑段将被合

45、并为一个物理段,于是CALL指令和被调用过程就处在一个段中了。在这种情况下,被调用过程可以使用NEAR属性。,例1:CODE SEGMENTP1 PROC NEARADD CX,1RET ;该指令被汇编为段内返回P1 ENDPMAIN PROC FARCALL P1 ;该指令被汇编为段内调用RET ;该指令被汇编为段间返回MAIN ENDPCODE ENDSEND MAIN,例2:CODE1 SEGMENTP1 PROC FARADD CX,1RET ;该指令被汇编为段间返回P1 ENDPCODE1 ENDSCODE2 SEGMENTMAIN PROC FARCALL P1 ;该指令被汇编为段

46、间调用RET ;该指令被汇编为段间返回MAIN ENDPCODE2 ENDSEND MAIN,(二)过程调用过程调用指令分为段内调用和段间调用两种类型。(1)段内调用1)段内直接调用格式: CALL DST其中DST表示转移目标地址,一般是被调用过程的过程名。操作: PUSH (IP)把IP当前值压入堆栈。这个IP当前值就是下一条指令的偏移地址,即返回地址的偏移量部分。(IP)(IP)+ D16修改指令指针寄存器IP,转移到目标地址。,说明: CALL指令的下一条指令的地址称为返回地址。当CPU执行CALL指令时,IP指向下一条指令,因此IP的当前值就是返回地址的偏移量部分,CALL指令的PU

47、SH操作其实就是将返回地址的偏移量部分压入堆栈保存。 CALL指令的机器代码使用16位位移量D16来表示转向地址,因此这是一种相对转移方式,D16是转向地址与返回地址之间的差值。综上所述,该指令的功能就是首先将返回地址的偏移量部分压入堆栈,然后转移到目标地址DST处调用子过程。,2)段内间接调用格式:CALL REG16 ;REG16是16位通用寄存器操作数CALL MEM16 ;MEM16是16位存储器操作数操作: PUSH (IP)把IP当前值压入堆栈。这个IP当前值就是下一条指令的偏移地址,即返回地址的偏移量部分。(IP)(REG16)/(MEM16)修改指令指针寄存器IP,转移到目标地

48、址,说明: CALL指令的下一条指令的地址称为返回地址。当CPU执行CALL指令时,IP指向下一条指令,因此IP的当前值就是返回地址的偏移量部分,CALL指令的PUSH操作其实就是将返回地址的偏移量部分压入堆栈保存。 转向目标地址存放在指定的寄存器或存储单元中。使用寄存器寻址方式或任何一种存储器寻址方式即可寻址到转向目标地址。综上所述,该指令的功能就是首先将返回地址的偏移量部分压入堆栈,然后转移到目标地址(REG16)/(MEM16)处调用子过程。,(2)段间调用指令1)段间直接调用格式: CALL DST其中DST表示转移目标地址,一般是被调用过程的过程名。操作:PUSH (CS) ;将返回地址的全地址(CS):(IP)压入堆栈PUSH (IP) (IP) DST的偏移地址(CS) DST的段地址,说明:CALL指令的下一条指令的地址称为返回地址。当CPU执行CALL指令时,IP指向下一条指令,CS指向当前代码段,因此IP的当前值就是返回地址的偏移量部分,CS的当前值就是返回地址的段基址部分,这条指令的两个PUSH操作实质上就是将返回地址的全地址压入堆栈中保存。因此简单地说,该指令的功能就是将返回地址的段基址和偏移量依次压入堆栈中保存,然后直接转移到目标地址DST处调用子过程。,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 网络科技 > C/C++资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报