汇编学习笔记49
第八章 模块化程序设计
本章要点:
1. 掌握段的完整定义及简化定义
2. 知道模块间的通信及子程序库
一、段的完整定义
(一) 完整的段定义
段名 SEGMENT [定位类型] [组合类型] [类别]
……
语句
……
段名 ENDS
通知汇编程序和连接程序如何建立和组合段
1. 段名
段名可以是唯一的,也可以与程序中其他的段名相同。在同一个模块中,如果已用相同的段名定义过段,那么当前这个段就被视为前一个同名段的继续,即同一个段。
对一个模块中的同名段而言, 后续同名段的定义伪指令SEGMENT中的可选项取值应该与前一个同名段相同,或者不再指定可选项的值而默认与前一个同名段相同
2. 定位类型
定位类型表示出当前段对起始地址的要求,从而指示连接程序如何衔接相连两段。
一般情况下,缺省的定位类型是PARA,即段起始地址于可用的第一个节(每节16个字节)的边界处
定位类型BYTE使得当前段紧接前一段,前后两段之间没有空间单元,所以是最节约的定位类型。
定位类型WORD使得段从偶地址开始,不仅较为节约,而且有利于数据单元定位在偶地址。
定位类型DWORD常用于8086的32位段。
一页等于256字节,所以定位类型PAGE可能导致最大的段间隔。
例1: 下程序的两个段定位类型均为PARA
DSEG SEGMENT PARA COMMON
MESS DB 'HELLO!', 0DH, 0AH, '$'
DSEG ENDS
CSEG SEGMENT PARA PUBLIC
ASSUME CS: CSEG, DS: DSEG
START: MOV AX, DSEG
MOV DS, AX
MOV DS, OFFSET MESS
MOV AH, 9
INT 21H
MOV AX, 4C00H
INT 21H
CSEG ENDS
END START
3. 组合类型
组合类型就是用于通知连接程序,如何把不同模块间段名相同的段组合在一起。
有如下组合类型:
(1) PUBLIC
表示当前段与其它模块中的组合类型为PUBLIC的同名段组合成一个段,组合的先后顺序取决于启动LINK程序时目标模块名排列的次序
(2) COMMON
表示当前段与其它模块中的同名段重叠,即起始地址相同,最终段的长度等于它们中最长的段的长度。
(3) STACK
组合类型STACK表示当前段是堆栈段,组合情况与PUBLIC相同
(4) MEMORY
组合类型MEMORY与PUBLIC相同
(5) AT表达式
表示当前段应该绝对地址定位,其地址即为表达式之值。LINK程序不对AT段生成任何代码或数据。
(6) PRIVATE
组合类型PRIVATE表示不与其它段组合,宏汇编程序MASM不识别此关键字。
若段定义伪指令SEGMENT语句中没有给出组合类型,就表示不与其它段组合。
例2:
某程序第一个源程序模块为例1, 第二个源程序模块如下所示:
DSEG SEGMENT PARA COMMON
DB 'OK'
DSEG ENDS
CSEG SEGMENT PARA PUBLIC
MOV AH, 4CH
INT 21H
CSEG ENDS
先把这两个源程序模块分别汇编,最后用LINK程序连接,命令如下:
LINK 例1 + 例2
模块2中的DSEG段与模块1中的DSEG段重叠, 模块2中的CSEG段和模块1中的CSEG段合并成一个段。
最后得到了可执行程序的内容如下:
0000: 0000 ; 两个段重叠后的结果为 'OKLLO..$'
0000: 0008 ; CSEG的类型类型是PARA导致的间隔
0001: 0000 ; MOV AX, 26H, 模块1中的CSEG段
4. 类别
类型用于表示段的分类。LINK程序总是使类型相同的段相邻,实际上只有类型相同的同名段才根据组合类型进行组合。
类别是一个由程序员指定的字符串,但必须使用单引号括起来。如果一个段没有给出类型,那么这个段的类别就为空。
例3:
设某个程序的模块甲如下:
; 模块甲(MODULE1)
DSEG SEGMENT PARA PUBLIC 'DATA'
…
DSEG ENDS
CSEG SEGMENT PARA PUBLIC 'CODE'
START:…
CSEG ENDS
END START
模块乙如下:
; 模块乙(MODULE2)
DSEG SEGMENT PARA PUBLIC 'XYZ'
…
DSEG ENDS
ASEG SEGMENT PARA PUBLIC 'CODE'
START: …
ASEG ENDS
END START
模块丙如下:
; 模块丙(MODULE3)
ESEG SEGMENT PARA PUBLIC 'DATA'
START: …
ESEG ENDS
END START
用以下命令把它们连接起来:
LINK MODULE1+MODULE2+MODULE3
在程序中各段的排列顺序如下:
模块甲的DSEG, 模块丙的ESEG, 模块甲的CSEG, 模块乙的ASEG, 模块乙的DSEG
(二) 完整的段定义(堆栈段说明)
一个完整的汇编程序一般应含有一个堆栈段,只有COM程序例外。
在程序的其它模块中也有组合类型为STACK的同名段,那么连接时将以连接的方式组合在一起,这样会构成一个存储空间更大的堆栈。
例4: 增加一个大小为1024字节的堆栈段
SSEG SEGMENT PARA STACK
DB 1024DUP(?)
SSEG ENDS
DSEG SEGMENT PARA COMMON
MESS DB 'HELLO', 0DB, 0AH, $
DSEG ENDS
CSEG SEGMENT PARA PUBLIC
…
CSEG ENDS
END START
LINK 程序会把组合类型为STACK的段的有关信息写入可执行文件中,设置的SS值是组合类型为STACK的段的段值。设置SP值是堆栈段的大小。
(三) 段组的说明和使用
例5: 下面的程序含有两个数据段和一个代码段
DSEG1 SEGMENT PUBLIC
VAR1 DB ?
DSEG1 ENDS
DSEG2 SEGMENT PUBLIC
VAR2 DB ?
DSEG2 ENDS
CSEG SEGMENT PARA PUBLIC
ASSUME CS: CSEG, DS: DSEG1
START: MOV AX, DSEG1
MOV DS, AX
MOV BL, VAR1
……
ASSUME DS: DSEG2
MOV AX, DSEG2
MOV DS, AX
MOV VAR2, BL
MOV AH, 4CH
INT 21H
CSEG ENDS
END START
另一种写法:
DSIS GROUP DSEG1, DSEG2
DSEG1 SEGMENT PUBLIC
VAR1 DB ?
DSEG1 ENDS
DSEG2 SEGMENT PUBLIC
VAR2 DB ?
DSEG2 ENDS
CSEG SEGMENT PARA PUBLIC
ASSUME CS: CSEG, DS: DSIS
START: MOV AX, DSIS
MOV DS, AX
MOV BL, VAR1
……
MOV VAR2, BL
MOV AH, 4CH
INT 21H
CSEG ENDS
END START