目录
一、段定义伪指令
1. 段名
2. 定位类型
3. 组合类型
4. 类别名
二、设定段寄存器伪指令
1. 设定段寄存器伪指令
2. 段寄存器的初始化方法
三、过程定义伪指令
一、段定义伪指令
伪指令 SEGMENT 和 ENDS 用于定义一个逻辑段。
使用时必须配对,分别表示定义的开始与结束。
格式:
[ ] 内的是可选参数,设有默认值。各个参数之间用空格分隔,参数之间的顺序不能改变。
1. 段名
① 段名由用户自己任意选定,但要符合标识符定义规则
② 最好选用与该逻辑段用途相关的名称。如:第一个数据段为 DATA1,第二个数据段为 DATA2 等。
③ 一对 SEGMENT 和 ENDS 前的段名必须一致。
④ 段名代表段地址。
段地址 = 段基地址 = 段基址
2. 定位类型
定位类型决定了当前段起始数据边界,即第一个可存放数据的存储单元的位置,再由起始数据边界决定当前段地址。定位类型可以有4种取值:PAGE、PARA、WORD、BYTE 。
(1)PAGE:表示该段从一个页面的边界开始存放数据。
由于一个页面为 256 个字节且页面编号从 0 开始,因此 PAGE 定位类型的段起始地址的最后 8 位二进制数一定为 0,即以 00H 结尾的地址。
(2)PARA:表示该段从一个小节的边界开始存放数据。
由于一个小节为 16 个字节且页面编号从 0 开始,因此 PARA 定位类型的段起始地址的最后 4 位二进制数一定为 0,即以 0H 结尾的地址。
在省略情况下,定位类型默认为 PARA 。
(3)WORD:表示该段从一个偶数字节地址开始存放数据。
WORD 定位类型的段起始地址的最后一位二进制数一定为 0,即以 0B 结尾的地址。
(4)BYTE:表示该段起始数据单元地址可以是任一地址值。
3. 组合类型
指定段与段之间的连接关系和定位。
它有六种取值选择:NONE、PUBLIC、STACK、COMMON、MEMORY、AT 。
(1)NONE
表示本段与其它逻辑段无连接关系,不同的程序模块中,即使具有相同的段名,也分别装入内存。默认情况下,组合类型是 NONE 。
(2)PUBLIC
表示对于不同程序模块中用 PUBLIC 说明的具有相同段名的逻辑段,汇编时将它们连接在一起,构成一个大的逻辑段。
(3)STACK
① 把不同程序模块中所有同名的堆栈段连接成一个连续堆栈段。
② 系统自动对 SS 段寄存器初始化为该连续段的段地址,并初始化堆栈指针 SP 。
(4)COMMON
对不同程序模块中用 COMMON 说明的同名逻辑段,连接时从同一个地址开始装入,即所有逻辑段重叠在一起,连接之后的长度等于最长的逻辑段。
(5)MEMORY
表示本段在存储器中应定位在所有其它段之后的最高地址上。如果有多个用 MEMORY 说明的段,则只处理第一个用 MEMORY 说明的段,其余的被视为 COMMON 。
不是在整个内存的最高地址上,只是在我们这个程序的最高地址上。
(6)AT
根据表达式的值定位段地址。如:AT 8000H,则段地址为 8000H,即本段的起始物理地址为 80000H 。
4. 类别名
类别名为某一个段或几个相同类型段设定类型名称。
类别名必须用单引号引起来。所用字符串可任意选定,但它不能使用程序中的标号、变量名或其它定义的符号。
系统进行连接处理时,把不同程序模块类别名相同的段存放在相邻的存储区,但段的划分与使用仍按原来的设定。优先级:组合类型 > 类别名。
举例
分配空间:
如果在段定义中选用了 PARA 定位类型说明,则在一个段的结尾与另一个段的开始之间可能存在一些空白,图中以蓝色框表示。CODE 段的组合类型为 MEMORY,因此被装入在其它段之后。
加载到内存:
① 当定位类型为 PAGE 和 PARA 时,段基物理地址直接选用段起始数据地址,即它们是重合的。
② 当定位类型为 WORD 和 BYTE 时,段基物理地址与段起始数据地址可能不同,即第一个存储单元的偏移地址不一定为0。
二、设定段寄存器伪指令
1. 设定段寄存器伪指令
(1)定义
ASSUME 的作用是告诉汇编程序,在处理源程序时,定义的逻辑段与哪个段寄存器关联。即对应的标号、变量等对应的段地址用哪个段寄存器来表示,可以在程序中多次设定。
ASSUME 并不设置各个段寄存器的具体内容,段寄存器的值是在程序运行时设定的。
(2)格式
格式:ASSUME 段寄存器名:段名,段寄存器名:段名,…
其中,段寄存器名可以为CS、DS、ES 和 SS,段名是用 SEGMENT/ENDS 伪指令定义的段名。
(3)举例
2. 段寄存器的初始化方法
(1)DS 和 ES 的装入
(2)SS 的装入
SS 的装入有两种方法。
① 在段定义伪指令的组合类型项中,使用 STACK 参数,并在段寻址伪指令 ASSUME 语句中把该段与 SS 段寄存器关联。
SS 将被系统自动装入 STACK 段的段地址,且 (SP) = 40H,即堆栈的长度。
② 如果在段定义伪指令的组合类型中,未使用 STACK 参数,或者是在程序中要调换到另一个堆栈,这时可以使用类似于 DS 和 ES 的装入方法。
MOV AX,STACK1 等价于 MOV AX,SEG STACK1 。
(3)CS 的装入
CPU 在执行指令之前根据 CS 和 IP 的内容来从内存中提取指令,即必须在程序执行之前装入 CS 和 IP 的值。因此,CS 和 IP 的初始值就不能用可执行语句来装入。
装入 CS 和 IP 一般有以下两种情况。
① 汇编时系统软件按照结束伪指令指定的地址装入初始的 CS 和 IP 。
任何一个源程序都必须以 END 伪指令来结束,即:END 起始地址。其中,起始地址可以是一个标号或表达式,它与程序中第一条指令语句前所加的标号必须一致。
- END 伪指令用来指示源程序结束和指定程序运行时的起始地址。
- 当程序被装入内存时,系统软件根据起始地址的段地址和偏移量分别被装入 CS 和 IP 中。
START 即为程序入点,标号名字可以随便取,但是一定要配对:
② 在程序运行期间,当执行某些指令时,CPU 自动修改 CS 和 IP,使它们指向新的代码段。
-
执行段间过程调用 CALL 和段间返回指令 RET
-
执行段间无条件转移指令 JMP
-
响应中断及中断返回指令
-
执行硬件复位操作
三、过程定义伪指令
在程序设计过程中,常常将具有一定功能的程序段设计成一个子程序。在 MASM 宏汇编程序中,用过程来构造子程序。格式如下:
(1)过程名
过程名是子程序的名称,它被用作过程调用指令 CALL 的目的操作数。
过程名类同一个标号的作用,具有段、偏移量和类型三个属性。而类型属性使用 NEAR 和 FAR 来指定,若没有指定,则隐含为 NEAR 。
- NEAR:过程只能被本段指令调用。
- FAR:过程可以供其它段的指令调用。
(2)RET 返回指令
每一个过程中必须包含有返回指令 RET,其作用是控制 CPU 从该过程中返回到调用过程的主程序。