源程序框架(MASM 6.x)

TOC

  1. 1. 程序的储存模型
  2. 2. 逻辑段的简化定义
  3. 3. 程序执行的开始
  4. 4. 程序执行的终止
  5. 5. 源程序的汇编结束

以下内容可能仅适用于MASM 6.x+版本的汇编器和部分MSVC汇编器。

对应存储空间的分段管理,用汇编语言编程时也常将源程序分成代码段、数据段或堆栈段。需要独立运行的程序必须包含一个代码段,并指示程序执行的起始位置。需要执行的可执行性语句必须位于某一个代码段内。说明性语句通常安排在数据段,或根据需要位于其他段。

随着MS-DOS和MASM的发展,MASM各版本支持多种汇编语言源程序格式,本书介绍一个最简单的程序格式,使用 MASM 6.x 版本的简化段定义源程序格式,程序模板如下:

            ;example.asm in DOS
.model small;定义程序的存储模型(smal表示小型模型)
.stack ;定义堆栈段(默认是1KB空间)
.data ;定义数据段
...... ;数据定义(数据待填)
.code ;定义代码段
.startup ;程序执行起始,同时设置数据段寄存器DS指向程序的数据段
...... ;主程序(指令待填)
.exit 0 ;程序执行结束,返回DOS
...... ;子程序(指令待填)
end ;汇编结束

在简化段定义(Simplied Segment Definition)的源程序格式中,以圆点(即英文小数点、句号)开始的伪指令说明程序的结构,必须具有存储模式伪指令.MODEL。随后.STACK,.DATA和.CODE依次定义堆栈段、数据段和代码段,一个段的开始自动结束上一个段。代码段中,通过.STARTUP语句说明程序从该处开始执行,并含有给DS赋值、使其指向该程序的数据段功能,便于后续指令访问数据段中的数据。程序最后利用,EXIT指令说明本程序执行结束、返回DOS操作系统。

程序的储存模型

存储模型(Memory Model)决定一个程序的规模,也确定进行子程序调用、指令转移和数据访问的默认属性。当使用简化段定义的源程序格式时,必须有存储模型.MODEL语句,且位于所有简化段定义语句之前。其格式为:
.model存储模型,语言类型
.MODEL语句确定了程序采用的存储模型,MASM有7种可以选择,如下表所示。

存储模型

存储模型 特点
TINY(微型模型) 创建COM类型程序,只有一个小于64KB的逻辑段(MASM 6.x支持)
SMALL(小型模型) 创建小应用程序,只有一个代码段和一个数据段,每个段不大于64KB
COMPACT(紧凑模型) 创建代码少、数据多的程序,只有一个代码段(不大于64KB),但可有多个数据段
MEDIUM(中型模型) 创建代码多、数据少的程序,可有多个代码段,但只有一个数据段(不大于64KB)
LARGE(大型模型) 创建大应用程序,可有多个代码段和多个数据段(静态数据小于64KB)
HUGE(巨型模型) 创建更大的应用程序,可有多个代码段和数据段,对静态数据没有限制
FLAT(平展模型) 创建一个32位的程序,运行在IA-32微处理器的32位Windows操作系统

创建运行于DOS操作系统下的应用程序,可根据需要选择前6种模型,一般的小型程 序(例如学习中的小程序)可以选用SMALL模型,大型程序选择LARGE模型。要创建 COM 程序只能用TINY模型,其他模型产生EXE程序。FLAT 模型只能用于32位Windows应用 程序中,不能在DOS环境执行。

DOS环境的COM类型程序要求将程序的代码、数据和堆栈都安排在一个逻辑段中,大小 不超过64KB,是一种比较紧凑的程序格式。在上述程序模板中只要将,.STACK 和.DATA语句 去掉,并将数据定义填到子程序之后(END之前)就形成了一个COM类型程序的模板文件。

逻辑段的简化定义

堆栈段定义伪指令,STACK创建一个堆栈段,段名是:STACK。保留字后可书写一个数值型参数指定堆栈段所占存储空间的字节数,默认是1KB(即1024B=400日字节)。堆栈段
名可用@STACK预定义操作符表示。

数据段定义伪指令,DATA创建一个数据段,段名是:_DATA。数据段名可用@DATA预定义操作符表示。

代码段定义伪指令CODE创建一个代码段,后可选一个标识符型参数指定该代码段的段名。如果没有给出段名,则采用默认段名,例如在TINY、SMALL、COMPACT和FLAT模式下,默认的代码段名是:_TEXT。代码段名可用@CODE预定义操作符表示。

程序执行的开始

MASM6.0引入的.STARTUP指令指明了本程序开始执行的位置,并同时使数据段寄存器DS等于用.DATA伪指令定义的数据段的段基地址。

MASM汇编程序在对源程序的汇编、连接过程中,会根据程序起始位置正确地设置代码段的CS和IP值,根据堆栈大小设置堆栈段的SS和SP值,但并不设置DS和ES值。这样,程序如果使用数据段,就必须在代码段中明确给DS等寄存器赋值。由于大多数程序需要在数据段定义变量,所以通常应该赋值给DS;使用到附加段就一定设置ES。

如果不使用.STARTUP指令,通常可以用如下两条语句代替:

start:  mov ax,@data    ;@DATA表示数据段的段地址,先传送给AX寄存器
mov ds,ax ;设置DS等于AX,即数据段的段地址

其中标号start也可以使用其他标识符,此处需要利用它在最后的汇编结束END指令作为参数,用于指明程序开始执行的位置。

程序执行的终止

应用程序执行结束,应该将控制权交还给操作系统,EXIT指令就实现了此功能。它实际上是利用了DOS功能调用的4CH号功能实现的,所以可以用如下两条语句代替:

mov ah,4ch
int 21h

DOS功能调用是MS-DOS操作系统提供给程序员的一些子程序库,主要以第21H号中断的形式使用(即指令“INT21H”)。

源程序的汇编结束

汇编结束表示汇编程序到此结束将源程序翻译成目标模块代码的过程,它不是指程序终止执行。源程序的最后必须有一条END伪指令,END指令之后的任何内容将不会被汇编程序所理会。

END伪指令后面可以有一个“标号”性质的参数,用于指定程序开始执行于该标号所指示的指令。汇编程序将据此设置CS和IP值。如果没有.STARTUP指令说明程序开始执行的位置,就需要利用这种方法指明。例如,对应前面我们使用的START标号,这时就需要用如下语句代替原“END”语句:

end start