汇编语言程序设计(六)

时间:2022-09-18 01:18:03

5 简化的段定义

前面,我们介绍了完整的段定义格式,用完整的段定义格式虽然可以控制段的各种属性,但程序员很少会这样做。现在的汇编程序提供了一种简化的段定义方式,它使定义段更简单、方便。

 

5.1 存储模式定义伪指令

在使用简化的段定义方式之前,必须使用存储模式说明伪指令来描述源程序所采用的存储模式。该伪指令说程序所使用的存储模式,汇编程序将用该存储模式生成相应的ASSUMEGROUP语句,同时也为其它的简化段创建等价的预定义。

 

程序存储模式说明伪指令的格式如下:

 

.MODEL  存储模式[,语言类型] [,操作系统类型] [,堆栈类型]

 

程序可选的存储模式有:TINYSMALLCOMPACTMEDIUMLARGEHUGEFLAT

 

伪指令.MODEL必须写在源程序的首部,且只能出现一次,其前内容只能是注释。

 

如果用伪指令来指定程序所遵循的语言类型,那么,将不允许子程序的嵌套定义。

 

一、存储模式

 

如果要用汇编语言编写被高级语言调用的子程序,那么,该汇编程序的存储模式必须与该高级语言编译(或解释)程序所使用的存储模式相匹配。汇编语言程序所能使用的存储模式、符号及其相关信息如表6.2所列。

 

在程序中,还可伪指令OPTION SEGMENTSEGMENT来指定段的规模。

 

有关存储模式的具体规定如下:

 

1TINY

 

在汇编程序MASM 6.11TASM 4.0,该存储类型是为编写COM文件类型而设置的。程序员还可用汇编命令行选项/AT和连接命令选项/TINY来达到此目的。

 

2SMALL

 

所有的数据变量必须在一个数据段之内,所有的代码也必须在一个代码段之内。在这种模型下,数据段寄存器的内容保持不变,所有转移也都是段内转移。

 

该存储类型是独立汇编语言源程序常用的存储模型。

 

3MEDIUM

 

所有的数据变量必须在一个数据段之内,但代码段可以有多个。在这种模型下,数据段寄存器的内容保持不变,转移可以是段间转移。

 

4COMPACT

 

数据段可以有多个,但代码段只能有一。

 

5LARGE

 

数据段和代码段都可以有多个,但一个数组的字节数不能超过64KB

 

6HUGE

 

数据段和代码段都可以有多个,一个数组的字节数也可以超过64KB

 

7FLAT

 

FLAT存储模式在创建执行文件时,将使该程序仅含一个包括程序数据和代码的32位段,并且只能在80386及其以后的计算机系统中运行。该程序的文件类型为EXE

 

在使用该存储模式之前,必须先用伪指令.386.486或其它伪指令来说明更高性能的CPU类型。也就是说:FLAT模式仅在386及其以后CPU模式下才能使用。

 

在该程序中,所有代码和数据位距的缺省值都是NEAR,子程序的类型也是NEAR,并且标识符@CodeSize@DataSize@Model的值分别为:007

 

FLAT存储模式下,程序将不使用段寄存器FSGS。汇编程序在处理说明语句“.MODEL  FLAT”时,将自动生成下列段寄存器说明语句:

 

ASSUME  CS:FLAT, DS:FLAT, SS:FLAT, ES:FLAT, FS:ERROR, GS:ERROR

 

当然,程序员也可把该段寄存器说明语句写在其指令序列之中。

 

二、语言类型

 

CSYSCALLSTDCALLBasicFortranPascal

 

三、操作系统类型

 

OS_DOS是当前唯一支持的选项值,也是该选项的缺省值。

 

四、堆栈类型

 

堆栈类型的值主要影响伪指令.STARTUP所生成的指令序列。该选项有二个可选值:NEARSTACKFARSTACK。其中:NEARSTACK是该选项的缺省堆栈类型。

 

l         NEARSTACK——堆栈段和数据段是同一段;

l         FARSTACK——堆栈段和数据段是不同的段,且堆栈不在段组DGROUP中。

 

例如:

.MODEL  SMALL, C, OS_DOS, FARSTACK

 

5.2 简化段定义伪指令

简化段定义伪指令在说明一个新段即将开始的同时,也说明了上一个段的结束。在本段定义结束时,也不必用伪指令“ENDS”来标识。

 

具体的伪指令说明形式及其功能描述如下:

 

1、代码段定义

 

.CODE

 

作用:说明其下面的内容是代码段中内容。

 

2、堆栈段定义

 

.STACK  [堆栈字节数]

 

其中,“堆栈字节数”可以不写,其缺省值为1024B

 

3、数据段定义

 

.DATA / .DATA? / .CONST

 

作用:说明其下面的内容是数据段中的变量定义。

 

在一个源程序中,可以有多个伪指令.DATA定义的数据段,这就好象在源程序中定义多个同段名的数据段一样。

 

伪指令.DATA?说明下面是一个未初始化数据段的开始,伪指令.CONST说明下面是一个常数数据段的开始。这二条伪指令很少使用,除非在与高级语言编写的程序相结合时,为了遵守高级语言的某些约定,而需要特殊说明时才使用。

 

汇编程序在处理简化的堆栈段和数据段定义时,它会自动地把伪指令.STACK.DATA.DATA?.CONST所定义的段组合成一个段组。如果想定义一个独立的、不与其它段组合在一起的数据段的话,那么,就可选用下面的数据段定义方式。

 

4、远程数据段定义

 

.FARDATA  [段名] / .FARDATA?  [段名]

 

其中:“段名”是可选项,如果不指定的话,则该段名就取其缺省段名。

 

作用:说明一个独立的数据段。

 

伪指令.FARDATA?说明下面是一个未初始化的、独立数据段的开始。通常情况下,很少使用该伪指令。

 

5.3 简化段段名的引用

当使用简化的段定义时,一般情况下,程序员可以不知道这些段的段名、段地址堆齐类型和组合类型等。但当把简化定义的段和标准定义的段混合使用时,就需要知道简化定义段的基本属性。下表是在小模式下段的基本属性对应表。

 

伪指令

缺省段名

对齐类型

组合类型

类别

段组名

.CODE

_TEXT

WORD

PUBLIC

'CODE'

 

.FARDATA

FAR_DATA

PARA

NONE

'FAR_DATA'

 

.FARDATA?

FAR_BSS

PARA

NONE

'FAR_BSS'

 

.STACK

STACK

PARA

STACK

'STACK'

DGROUP

.DATA

DATA

WORD

PUBLIC

'DATA'

DGROUP

.DATA?

BSS

WORD

PUBLIC

'BSS'

DGROUP

.CONST

CONST

WORD

PUBLIC

'CONST'

DGROUP

 

在其它存储模型下,由伪指令".CODE"说明的代码段段名在"_TEXT"之前还要加上其模块名(源程序名)。假设,某模块名为ABC,则其缺省的代码段段名就为ABC_TEXT。因此,在这种情况下,程序的模块名或源程序名不要以数字开头。

 

例,非简化段的程序:

 

简化段定义的方法的程序:

.MODEL  SMALL

.STACK  128

.DATA

MSG DB "Simplified Segment Directives.$"

.CODE

MOV  AX, @DATA     ;取数据段的段值

MOV DS, AX           ;把给段寄存器DS赋值

MOV DX, offset MSG

MOV AH, 9H

INT 21h

MOV AX, 4C00H

INT 21h

END

 

另外在汇编程序MASM还提供了二组简化的代码伪指令.STARTUP.EXIT

 

l         .STARTUP——在代码段的开始,用于自动初始化寄存器DSSSSP

l         .EXIT——用于结束程序的运行,它等价于下列二条语句:

 

MOV AH, 4CH

INT  21h

 

当使用汇编程序TASM时,以上二条伪指令分别改为:STARTUPCODEEXITCODE。假设使用汇编程序MASM,那么,上面的例子可改写成下例的形式:

 

.MODEL  SMALL

.STACK  128

.DATA

MSG DB "Simplified Segment Directives.$"

.CODE

.STARTUP                               ;自动初始化寄存器DSSSSP

MOV DX, offset MSG

MOV AH, 9H

INT 21h

.EXIT

END