汇编语言编写DOS下的内存驻留程序(4)

四 基本的驻留程序
4.1 一个基本的COM程序
DOS之下有两种形式的可执行文件,这两种文件分别是COM文件和EXE文件.其中,COM文件可以迅速地加载和执行,但是其大小不能超过64K字节,只能有一个段,代码段.而且起始地址为100H指令必须为程序的启动指令.EXE文件可以加载到许多个段中,因此程序的大小没有限制,但是程序加载的过程就比较慢,而且对于内存驻留程序来说还会造成更大的麻烦.
以下是一个可以正确执行的COM文件,但其内容是空的;只是一个COM文件的框架,可以把你写的任何应用部分加在这个文件中,形成一个COM格式的内存驻留程序:
;Section 1
cseg segment
assume cs:cseg,ds:cseg
org 100h
;Section 2
start:
ret
;Section 3
cseg ends
end start
上面的程序可以分成三部分,第一部分定义了代码段和数据段分别放在程序中的位置,以及执行代码的起始地址.第二部分是可执行的程序,在这个例子只一个RET指令而已.第三部分是程序包段的终结,其中END叙述包含了程序开始执行地址.
若是把上面的程序经过汇编连接,你会发现所产生的COM文件只有一个字节长.这是因为所产生的COM文件没有程序段前缀(Programsegmetn profix),因为在DOS下所有和COM文件都有相同的程序段前缀.当DOS加载一个COM文件到内存中时,就会自动地产生一份正确的程序段前缀.一个程序在执行的过程中,可以根据需要修改其程序段前缀,但是在一开始,所有COM文件的程序前缀都是相同的.下面是程序前缀的格式.
偏移位置 含义
0000H 程序终止处理子程序地址(INT 20H)
0002H 分配段的结束地址,段值
0004H 保留
0005H 调用DOS的服务
000AH 前一个父程序的IP和CS
000EH 前一个父程序的CONTROL_C处理子程序地址
0012H 前一个父程序包的硬件错误处理子程序地址
0016H 保留
002CH 环境段的地址值
005EH 保留
005CH FCB1
006CH ` FCB2
0080H 命令行的参数和磁盘转移区域
4.2 一个最小的内存驻留程序
上面的程序只是一个一般的DOS程序而已.并不是内存驻留的.以下是一个基本的内存驻留程序结构:
;Section 1
cseg segment
assume cs:cseg;ds:cseg
org 100h
start: ;Section 2
nop 
done: ;Section 3
mov dx,offset done
int 27h
;Section 4
cseg ends
end start
和前一个程序相比,这个程序只是增加了一个DONE部分.这个部分使用了INT 27H这个中断调用,来终止并驻留在内存(Terminate and Stay Resident)中.使用INT 27H这个中断调用时,必须设定好一个指针,让这个指针指向内存中可以使用的部分,事实上,这就相当于设置一个COM文件可加载的位置.另外DOS还提供了INT 21H,AH=31H(驻留程序,Keep process),但是使用这个中断调用时,我们必须设定所保留的内存大小,而不是设定一个指针;另外这个中断调用会送出退出码.
使用INT 27H时,必须设定一个指针指向可用存储位置的开头,以便让DOS用来加载稍后执行的程序.DOS本身有一个指针,这个指针是加载COM文件或EXE文件时的基准地址值.INT尿27H 会改变这个指针或为新的数值.同时造成新指针和旧指针之间的存储空间无法让DOS使用因此这样做会造成可用存储位置愈来愈少.
调用INT 27H时所使用的指针是个FAR指针,其中DX存放的是位移指针(Offset pointer),它可以指到64K字节之内的范围.而DOS是段指针(Segment pointer),它可以指到IBM PC中640K字节的任何一个段.在上面的例子中,DS的内容不必另外设定,因为当COM文件加载时,DS的内容就CS的内容相同了.
经常在编写汇编程序时,常犯的一个错误就是:把assume ds:cseg这个叙述误认为是,存放某一预设值到DS中,事实上,汇编语言程序中的Assume叙述不会产生任何的程序代码,这个功能是告诉汇编器做某些必要的假设,以便正确地汇编程序.譬如以下的程序:
cseg segment
.............
assume ds:cseg
mov ah,radix
.............
radix db 16
.............
cseg ends
上面的程序汇编时,当汇编器看到mov ah,radix这个指令时,它就根据assume ds:cseg来产生一定形式的赋值指令.在面的Assume ds:cseg叙述是告诉汇编器,数据段就位于目前的代码段中.这是内存驻留程序的一项重要关键.如果DS的内容和CS不相同时,无论是否有assume 叙述,程序执行时都会失败.
4.3 改良的内存驻留程序
上面所介绍的内存驻留程序实际上没有做任何事,只是驻留在内存中而已.事实上,在START和END之间放入任何程序代码,都只会执行一次而已然后就永远驻留在内存中,除非是使用转移指令转到START的地址去,否则将永远无法被使用.还要注意一点,START的地址值并非固定不变,它会根据程序执行时计算机的状态而改变.
下面的这个程序只是把需要驻留的程序代码装载好,但是并不会执行.
;Section 1
cseg segment
assume cs:cseg,ds:cseg
org 100h
;Section 2
start:
jmp initialize
;Section 3
app_start:
nop
initialize:
;Section 4
mov dx,offset initialize
int 27h
;Section 5
cseg ends
end start
上面的程序一开始执行时就传到initialize标志的地方,装置好驻留在内存的应用部分.原先的DONE已经改成initialize,而驻留在内存的程序代码则放在App_Start 和Initialize之间.
另外,你也许注意到了,程序的起始地址并不是Initialize而是Start.这是因为所有COM程序的起始地址都是100H;而上面的程序中Start是放在100H的地方.如果把Initialize放在End之后,Initialize就变成起始地址,但是这样的程序无法透过EXE2BIN转换成COM文件了.如果无法产生COM文件时,那么就必须直接处理段的内容.
4.4 减少内存的额外负担
到目前为止,都没有接触到程序前缀,当使用INT 27H时,事实上是把指针以前的东西都保留在内存中,这也包括了COM的程序段前缀.因为COM文件执行完毕后,才可以把程序段前缀移掉.
从上面的事实可以看出:如果程序段前缀只能在COM装置程序结束后才可以移去,那么就可以由驻留在内存中的程序代码完成.要做到这一点,可以把整个程序往下移动256个字节.但又如何做到这一点呢?我们可以设定一个标志(Flag),用来指示这个程序是否执行过.如果这个驻留程序或是第一次执行时,就把整个程序往下移动256个字节,以便把程序段前缀移去.但是如果驻留程序在装置好之后,经过一段长时间仍然没有被执行时,怎么办呢?如果同时载入了好几个驻留程序时,双该如何呢?这些重要的事情都需要使用不同的程序代码来解决.如果说这些程序代码超出了256字节时,那么所占用的存储位置就超出程序段前缀所浪费的空间.有些人用一些比较简短的代码来解决这个问题,但是还是比较麻烦.因此对于大部分的内存驻留程序而言,除非存储空间太少,以至于256字节变得很重要,否则最好不要去处理程序段前缀,这样子会让你的程序简洁而且容易阅读.

时间: 2024-11-08 17:46:54

汇编语言编写DOS下的内存驻留程序(4)的相关文章

汇编语言编写DOS下的内存驻留程序(3)

三 中断矢量3.1 IBM PC提供的中断IBM PC有两种基本形态的中断.如果是由外围设备所产生的中断就叫做硬件中断(Hardware interrupt),譬如:键盘,磁盘机和时钟等外围设备都可以产生硬件中断.外围设备所产生的中断信号都连接到中断控制器,中断控制器可以根据它们之间的重要性来安排优先顺序,以便使CPU有效地处理这些硬件信号.另一种中断是软件中断(Software interrupt),软件中断也叫做陷井(Trap),它是由执行中的软件所产生.虽然软件包中断的处理方式和硬件中断完

汇编语言编写DOS下的内存驻留程序(1)

绪言0.1 内存驻留与中断 内存驻留程序英文叫Terminate and Stay Resident Program,缩写为TSR.这些程序加载进内存,执行完后,就驻留在内存里,当满足条件时,调到前台来执行. 内存驻留程序的常用形式有:  >诸如Borland 的SideKick弹出式实用程序  >日历系统  >网络服务器  >通讯程序  >本地的DOS扩展(如CCDOS,UCDOS等中文系统都属于这个范畴)  >一些可恶的人利用TSR技术制作很多可恶的病毒程序,几乎所

汇编语言编写DOS下的内存驻留程序(5)

五 键盘输入扩充程序有了前一节的基本驻留程序为基础,就可以建立起不同的应用程序.接下来,就写一个驻留程序,把用户敲入的字符,用一系列的字符来取代.这样可以减少用户的击键次数.首先,先复习一下前一节的驻留程序的格式,如下所示:cseg segmentassume cs:cseg,ds:csegorg 100hstart: jmp InitializeOld_Keyboard_IO dd ? ;Section 1new_keyboard_io proc farsti ;Section 2pushfa

汇编语言编写DOS下的内存驻留程序(2)

基本原理2.1 8086/8088IBM PC中央处理单元(Central Processing Unit)是微处理器Inter 8088,8088是8086是小的版本.对于编写程序而言,两者几乎完全相同.两者之间的差别是在于:它们对外的沟通.8086和外界沟通时是经由16位的输入输出通道,内存存取也是每次以16位为单位,8088和8086极为相似,但是它和外界沟通时就必须经由16位的通道.2.1.1 寄存器8086/8088的结构简单,其中包含了一组一般用途的16位寄存器.AX,BX,CX,D

如何进行系统配置 ——了解DOS下的内存

DOS操作系统最早设计时,PC机的硬件系统只支持1M字节的寻址空间,所以DOS只能管理最多1M字节的连续内存空间.在这1M内存中,又只有640K被留给应用程序使用,它们被称为常规内存或基本内存,其它384K被称为高端内存,是留给视频显示和BIOS等使用的.在1982年,640K内存对微型计算机来说显得绰绰有余,人们甚至认为,640K的内存可以用来干任何事.现在看起来有些可笑,但在当时,情况确实如此. 现在的情况是,即使你的电脑装有几兆或几十兆内存,但如果你使用DOS操作系统,那么你也只有640K

DOS下内存的配置

我们大家都知道,DOS大体上不能够完全依靠人机界面的方式来一步步地完成系统的配置.若要让系统发挥出最大的性能,必须依靠我们的进一步努力.下面介绍一下DOS内存的配置方法. 实模式的DOS通常只能使用1M以下的内存空间.其中基本内存为640K,而上位内存则需要相应的内存管理器.基本内存的管理尤为重要,因为使用不当会造成一些程序无法运行.那么,应如何优化使用它呢?这儿有一些建议. 首先,加载提供上位内存(UMB)的内存管理器.通常有EMM386和QEMM等,不过这些工具自身占用的内存较大,在此推荐的

DOS下内存的配置_DOS/BAT

实模式的DOS通常只能使用1M以下的内存空间.其中基本内存为640K,而上位内存则需要相应的内存管理器.基本内存的管理尤为重要,因为使用不当会造成一些程序无法运行.那么,应如何优化使用它呢?这儿有一些建议. 首先,加载提供上位内存(UMB)的内存管理器.通常有EMM386和QEMM等,不过这些工具自身占用的内存较大,在此推荐的是UMBPCI,这是一个 仍在发展的工具,可提供最大高达162K的UMB,而且如果放在HIMEM前可完全不占用基本内存.然后,将所有的设备驱动程序/TSR调入UMB(用 D

DOS下内存的配置方法_DOS/BAT

我们大家都知道,DOS大体上不能够完全依靠人机界面的方式来一步步地完成系统的配置.若要让系统发挥出最大的性能,必须依靠我们的进一步努力.下面介绍一下DOS内存的配置方法.  实模式的DOS通常只能使用1M以下的内存空间.其中基本内存为640K,而上位内存则需要相应的内存管理器.基本内存的管理尤为重要,因为使用不当会造成一些程序无法运行.那么,应如何优化使用它呢?这儿有一些建议.  首先,加载提供上位内存(UMB)的内存管理器.通常有EMM386和QEMM等,不过这些工具自身占用的内存较大,在此推

在DOS下使用注册表扫描程序

从windows98之后,windows系统加入了对注册表的 管理程序,该程序有两个版本,scanregw.exe工作在windows环境中,Scanreg.exe工作在dos环境.并用一个Scanreg.ini文件与之辅助.介绍该程序For windows版本的文章很多,朋友们可以自己 查找参阅.这里仅介绍如何在dos下使用Scanreg.exe程序. 由于程序 是在dos模式下工作.因此,尽管你的操作系统是 中文版的windows,这时出现的也是英文字符界面.程序操作是由命令行和一些选项 开