Chinaunix首页 | 论坛 | 博客
  • 博客访问: 226410
  • 博文数量: 45
  • 博客积分: 1850
  • 博客等级: 上尉
  • 技术积分: 473
  • 用 户 组: 普通用户
  • 注册时间: 2005-07-11 10:21
文章分类
文章存档

2006年(17)

2005年(28)

我的朋友

分类:

2006-03-30 12:15:14

序段的定义和属性
一、DOS的程序结构
DOS操作系统的两种可执行程序是EXE和COM
1、EXE程序
EXE程序可以有独立的代码、数据和堆栈段,还可以有多个代码段和多个数据段,程序长度可以超过64KB,执行起始地址可以任意指定。规则的EXE文件在磁盘上由两部分组成:文件头和装入模块。装入模块就是程序本身。文件头则是由连接程序生成,包含有文件的控制信息和重定位信息,供DOS装入EXE文件时使用。实际上大EXE文件还可能包含一个附加部分,此部分由开发者用连接程序以外的工具附加到程序末尾,不属于装入模块,也不直接装入主存,仅供程序本身使用。当DOS装入或执行一个程序时,DOS确定当时主存最低的可用地址作为该程序的装入起始点,此点以下的区域称为程序段。在程序段内偏移0处,DOS为该程序建立一个程序段前缀控制块PSP(Program Segment Prefix),它占用256(=100h)个字节,而在偏移100h处才装入程序本身,如下图:
 
EXE程序的加载需要重新定位:
(1)DS和ES指向PSP段地址,而不是程序的数据段和附加段,所以程序中需要根据实际的数据段改变DS或ES
(2)CS:IP和SS:Sp是由连接程序确定的值,指向程序的代码段和堆栈段。如果不指定堆栈段,则SS=PSP段地址,Sp=100h,堆栈段占用PSP中部分区域。所以有时候不设置堆栈段也能正常工作。但为了安全起见,程序应该设置足够的堆栈空间。
2、COM程序
COM程序是一种将代码、数据和堆栈段合一的结构紧凑的程序,所有代码、数据都在一个逻辑段内,不超过64KB。COM文件存储在磁盘上是主存的完全影像,不包含重新定位的加载信息,与EXE文件相比其加载速度更快,占用的磁盘空间也少。尽管DOS也为COM程序建立PSP,但是由于两种文件的结构不同,所以加载到内存后各段设置不完全一样。如下图:
 
(1)所有段地址都指向PSP的段地址
(2)程序执行的起始点是PSP后的第一条指令,即IP=100h,即COM程序的第一条指令必须是可执行指令,程序的起始执行处是程序头
(3)堆栈区设在段尾(通常为FFFEH),在栈低置0000字。
二、段定义格式的伪指令
在前面我已经讲过了汇编程序的两种原程序格式即简化段格式和完整段格式。这里讲解简化段定义的伪指令
(一)简化段定义格式伪指令
1、存储模式伪指令
存储模式决定一个程序的规模,也确定进行子程序调用、指令转移和数据访问的缺省属性。使用简化段格式时,必须有存储模式.MODEL语句,格式如下:
.MODEL 存储模式 [,语言类型] [,操作系统类型] [,堆栈选项]
.MODEL语句必须位于所有段定义语句之前,共有7种不同的存储模式,分别为:
(1)TINY(微型模式)——所有的段地址寄存器都被设置为同一个值,即意味代码、数据和堆栈段都在一个段内,不大于64KB,访问操作数和指令只需要使用16位偏移地址。
(2)SMALL(小型模式)——在小模式下,一个程序至多只能有一个代码段和一个数据段,每段不大于64KB。这里数据段指数据段、堆栈段和附加段的总和。小模式下程序的最大长度为128KB。访问操作数和指令都只需要16位偏移地址,指令转移、程序调用以及数据访问都是近属性(NEAR),即小模式下的调用类型和数据指针缺省分别为近调用和近指针。
(3)COMPACT(紧凑模式)——代码段被限制在64KB的段内,数据段可以多个,超过64KB,调用类型缺省为近调用,数据指针缺省为远(FAR)指针。(数据量大代码量小程序)
(4)MEDIUM(中型模式)——代码段可以超过64KB,有多个,数据段只能有一个不大于64KB,数据指针缺省为近指针,调用类型缺省为远调用。(数据量小代码量大程序)
(5)LARGE(大型模式)——允许的代码段数据段都有多个,都可以超过64KB,但全部的静态数据(不能改变的数据)仍限制在64KB内,调用类型和数据指针缺省分别为远调用和远指针。
(6)HUGE(巨型模式)——与大型模式基本相同,只是静态数据不再局限于64KB
(7)FLAT(平展模式)——用于创建一个32位的程序,它只能运行在32位X86CPU上。该语句前要使用32位X86 CPU的处理器说明伪指令。DOS下不能使用FLAT模式,而编写32位Windows9.x或Windows NT的程序时,必须采用FLAT模式。
完整的MODEL语句还可以选择“语言类型”,如C,PASCAL等,表示采用制定语言的命名和调用规则,它将影响PUBLIC和EXTERN等伪指令。操作系统类型默认和唯一支持的就是os_dos,堆栈选项默认是NEARSTACK,表示堆栈段寄存器SS等于数据段寄存器DS;FARSTACK则表示SS不等于DS。
2、简化段定义伪指令
语句.CODE、.DATA、.STACK分别表示代码段、数据段和堆栈段的开始,一个段的开始自动结束前面的一个段。采用简化段定义指令之前,必须有存储模式语句.MODEL
(1).STACK [大小]
.STACK创建一个堆栈段,段明stack,参数制定堆栈段所占用的字节数,默认是1KB(=1024=0400H字节)
(2).DATA
     .DATA?
数据段伪指令,DATA创建一个数据段,段名是:_DATA.它用于定义具有初值得变量,当然也允许定义无初值得变量。无初值的变量可以安排在另一个段中,用.DATA?伪指令创建,它建立的数据段名是:_BSS。使用.DATA?伪指令可以减小形成的EXE文件,并与其他语言保持最大的兼容性。另外.CONST伪指令用于建立只读的茶馆能量数据段(段名:CONST),.FARDATA和.FARDATA?伪指令分别建立有初值和无初值得远调用数据段。
(3).CODE  [段名]
创建一个代码段,它的参数指定该代码段的段名没给出使用默认值。在TINY、SMALL、COMPACT和FLAT模式下,默认代码段名是:_TEXT,在MEDIUM、LARGE和HUGE模式下,默认段名是:模块名_TEXT。另外,在使用简化段定义中,各段名和其他用户所需要的信息可以使用MASM已定义的符号,这些符号主要有:
@CODE——表示.CODE伪指令定义的段名
@DATA——表示由.DATA和.DATA?等定义的数据段的段名
还有@CURSEG  当前段名、@STACK  堆栈段名  、@CODESIZE 代码段规模  、@DATASIZE 数据段规模等
3、程序开始伪指令
.STARTUP
按照给定的CPU类型,根据.MODEL语句选择的存储模式、操作系统和堆栈类型,产生程序开始执行的代码;同时指定程序开始执行的起始点。在DOS下,.STARTUP语句还将初始化DS值,调整SS和SP,在前面汇编(六)的li6-1.lst中可以看出,在小模式下,.STARTUP主要设置了数据段DS值,同时按照存储模式的要求使堆栈段SS=DS;为了保证堆栈区域不变,栈顶指针SP也需要相应调整,即加上数据段所占用的字节数。连接程序会根据程序的起始点正确的设置CS:IP,根据程序的大小和堆栈段的大小设置SS:SP,但没有设置DS、ES。
4、程序终止伪指令
.exit [返回数码]
此语句产生终止程序执行返回操作系统的指令代码,可选参数是一个返回的数值,通常用0表示没有错误。
5、汇编结束伪指令
END [标号]
END伪指令指示汇编程序MASM到此结束汇编过程。源程序的最后必须有一条END语句,可选标号用于指定程序开始执行点,连接程序据此设置CS:IP
 
阅读(3176) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~