DOS程序员参考手册[16B]

时间:2022-09-02 19:29:31

499页
系统
Int 21h             功能25h                                 版本1
                    设置中断向量
安全地修改中断向量,以使其指向某个指向的中断处理程序。
调用寄存器: AH              25h
              AL            中断号
              DS:DX       指向中断处理程序的指针
返回寄存器:无
注释:该功能可以使在其他情况下可能延缓的操作得以快速进行,即改变中
断向量。由于中断向量被保存在低端内存中的一个表内(参见第11章“中断处
理程序”),因此,可以很容易地直接改变它们。但是,如果在改变过程中,尤其
是当只有部分中断地址被传送给这个表时出现了中断,那么这一过程是十分
危险的。
      与写入自己的代码以安全地管理中断设备操作不一样,用户可以直接使
用这种功能,以安全地把中断向量表更改到用户提供的某个地址上。这是用于
改变中断向量方面唯一得到验证的方法。
      改变中断向量也会导致一些特殊的问题。当程序按常规方式终止时,中断
22h、23h和24h会自动地复位为各自的初始值(参见Int 20h、Int 27h和功能
00h、31h和4Ch)。如果程序修改了其他任何中断向量,那么这些向量就会停
留在它们的改变值上,甚至在程序终止后亦不会复原。这样往往会引起一些问
题;例如在程序终止后出现了中断情况会导致中断跳转到一个不存在的中断
处理例程上。
      为了防止出现这类情况,改变中断向量的程序应首先使用功能35h,以获
取初始向量值并将其保存起来。这样在程序终止后,初始向量值便用于改变中
断向量。把向量改变为除22h、23h或24h以外的中断的程序,还必须有能力捕
获可能终止程序的各种非常规途径,这些途径包括Ctrl-C或Ctrl-Break中断
服务,DOS关键出错服务以及各种有可能导致程序终止的潜在中断、如被零
除中断。
      如果程序不能截取可能终止它的任何方法或所有方法,其结果是中断向
量仍然保持挂起。如果程序冲毁了且不能将中断向量复位,那么唯一安全的途
径是在进行别的操作之前将系统复位。
系统
Int 21h           功能26h                                   版本1
                    创建PSP
从当前正执行的程序中把程序段前缀(PSP)复制给指定的段地址,然后将其

500页
更新,以供新的程序使用
调用寄存器: AH              26h
              DX            新PSP的段地址
返回寄存器:无
注释:该功能创建出PSP,并作好运行另一道程序的准备。在指定的内存段地
址处,当前程序的PSP被复制。有关PSP的情况已在第3章“动态的DOS”中
作了介绍。
      从理论上讲,把COM文件复制到新PSP之后的内存空间里并执行程序,
这是有可能的,但这可能算不上是什么好办法,原因很简单,即该功能已经过
时,在版本2和以后的版本中,它已被更为复杂且更易于使用的EXEC功能
(功能4Bh)所取代。Microsoft和IBM公开地建议用户在创建程序时应使用
EXEC功能而不要使用功能26h。EXEC在处理程序的装载和执行方面具有更
优的性能,并且能防止程序在操作过程中出现潜在的错误。该功能不装载和执
行其它的程序;它只为一种程序准备PSP。调用某个程序的功能必须仍然装载
和执行同一程序。
      如果程序改变了用于Int 22h、23h和24h的中断向量,那么新的向量就会
被复制到新创建的PSP中。此外,该功能还能适当地更新内存分配信息。
      Microsoft建议用户不要再使用这种功能,除非得用它来维持旧软件。可
随时终止对该功能的支持。应使用功能4Bh, 子功能00h来代替该功能。
磁盘
Int 21h           功能27h                                   版本1
                  随机块读取(FCB)
从磁盘文件中把一个或多个连续随机记录读给磁盘传送区(DTA)。
调用寄存器: AH              27h
              CX            要读取的记录数
              DS:DX      指向已打开的FCB的指针
返回寄存器: AL
                            00h,成功地读完全部记录
                            01h,无读操作,遇到了EOF
                            02h,已取消读操作,DTA边界出错
                            03h,读取了部分记录,遇到了EOF
              CX            读取的记录数
注释:该功能可用文件控制块(FCB)从磁盘文件中读取一组连续的随机记
录。也可以只从先前打开(功能0Fh)的文件中读取信息。第9章“目录和文
件”中已详细地介绍了文件以及FCB的情况。
501页
        要使用这种功能,必须确保在CX中出现所希望的记录数,并且DS:DX
    必须指向成功地打开文件后而创建的FCB。设置在此FCB中的参数可控制随
    机读取。而要读取的起始记录通过在FCB中设置随机记录字段来指定,并且
    每一个记录的大小可通过记录大小字段来控制。在调用该功能之前,可以改变
    这些FCB字段值,以便这些值符合应用程序的要求。有了这些值,DOS便可
    计算出读操作开始的文件位置。
        当该功能完成其任务时,信息就从DTA中的磁盘内读了出来。(关于
    DTA的详细情况可参见第9章和功能1Ah)。当成功地实现了该功能时,FCB
    的随机记录、当前块和当前记录等字段就全部得到更新。
        由于从磁盘中读出的信息被保存在DTA中,因此DTA必须有足够的容
    量以容纳这些信息块。否则,这些信息就会覆盖其他的数据或程序。
        一旦出现了其他操作,通过AL寄存器返回的状态代码便会指示出错。如
    果AL的值为0,表明未出错;如果AL为任何其他值,则表明在此操作期间出
    现过某种错误。如果该功能读出的数据量太大,以致超出了DTA的内存段边
    界(以000为终点内存地址),那么该功能就会失败,并返回AL=2也可以只
    读取部分记录(AL=3),并以0字符补齐余下部分。
        在网络环境中,必须拥有读出权以便能使用此功能。
        Microsoft建议用户不要再使用这种功能,除非得用它来维持旧软件。可
    随时终止对该功能的支持。应使用功能3Fh来代替该功能。
磁盘
Int 21h             功能28h                                   版本1
                    随机块写(FCB)
从磁盘传送区(DTA)中把一个或多个连续随机记录写入磁盘
调用寄存器: AH                28h
                CX            要写的记录数
                DS:DX      指向已打开的FCB的指针
返回寄存器: AL
                              00h,成功地写完了全部记录
                              01h,没有进行写操作,磁盘已满或为只读文件
                              02h,取消了写操作,DTA边界出错
                CX            已写入的记录数
注释:该功能可通过使用文件控制块把一组连续的随机记录写入磁盘文件。
    也可以只把信息写给已先打开(功能0Fh)的或新创建(功能16h)的文件。第9
章“目录和文件”已详细地介绍了文件和FCB的情况,对此有疑问的读者可参
看第9章。
502页
      要使用这种功能,必须确保CX中保存的是要写入的记录数,并且DS:
DX应指向成功地打开或创建文件之后才创建的FCB。可在FCB中设置参数
来控制随机写,可通过在FCB中设置随机字段来指定要写入的起始记录,并
且可通过记录大小字段来控制每个记录的大小。在调用该功能之前,可把这
些FCB字段的值改变成对应用程序合适的值。DOS可使用这些值计算开始读
操作的文件位置。
      由于要写入磁盘的信息来自DTA,因此必须保证所写的记录大小和记录
数据目与希望的数据量相当。否则,一不留神就会把其他数据(无用的信息)写
给磁盘文件。关于DTA的详细情况可参见第9章“目录和文件”以及功能
1Ah。
      如果所写入的数据量没有填满DOS磁盘缓冲区(指DOS内部的),那么
就应加上该磁盘缓冲区原有的数据,然后再确定是否有必要将其写给磁盘。
      一旦成功地实现了该功能,FCB的随机记录、当前块以及当前记录等字
段就会得到更新。
      在操作过程中,如果出现了其他FCB文件操作,那么通过AL寄存器中
返回的状态代码便会指示出错。若AL为0,说明没有出错;若AL为非0值,
则表明在该操作期间产生了某种错误。其中AL=1表示磁盘已满或要写入的
文件为只读文件;AL=2表明在写操作过程中,超出了DTA的内存段边界
(以000为终点的内存地址),并且该功能已失败。
      在网络环境中,必须拥有写入权限才能使用该功能。
      Microsoft建议用户不要再使用这种功能,除非得用它来维持旧软件。可
随时终止对该功能的支持。应使用功能40h和42h来代替该功能。
磁盘
Int 21h           功能29h                                   版本1
                  分析文件名
把文件名字符串分析成文件控制块(FCB)以便于使用
调用寄存器: AH            29h
              AL          分析控制标志(参见表16.4)
              DS:SI    指向下一个字符串的指针
              ES:DI     指向FCB的指针
返回寄存器: AL
              00h,未找到通配符
              01h,已找到通配符
              FFh,驱动器标识符无效
              DS:SI     指向紧跟在被分析的文件名之后的
                          第一个字符的指针
503页
                ES:DI       指向未更新且未打开的FCB的指针
    注释:该功能最初用来从命令行中析取文件,并以正确的格式来保存此文件
    以便打开FCB。为了实现这个目的,可首先将指针指向文件名字符串,并接着
    将另一个指针指向打算使用的FCB。没有必要采用任何种类的格式来保存
    FCB,单用内存块就能十分有效地保存好它。
        在所有版本中,分隔符无非就是如下几种:句号(.)、冒号(:)、分号(;),等
    号(=)、加号(+)、标记和空格。在DOS版本1中,还有以下几种符号也可用
    作分隔符:双引号(")、斜线(/)、左括号([)和右括号(])。
        该功能返回一个用于所期望的文件的FCB,这个FCB不仅大小合适而且
    是未打开的,同时,该功能还返回一个指向该文件的文件名之后第一个字符的
    指针(如果在几个文件名之中的某个文件名内分析命令行,那么该功能的作用
    是很明显的)。在执行该功能时,系统会自动地把星号字符,转换成一个或多个
    问号字符,以终止文件名或扩展名。
        由于该功能是一种FCB功能,它不可能与路径名兼容,因此,在文件名中
    不能出现有目录。该功能可以只分析当前目录中的文件,并且可通过表16.4
    中给出的分析标志来控制文件名的解释。
                            表16.4分析控制标志
            位
                                    含    义
    76543210
    . . . . . . . 0         停止分析,表明已找到文件分隔符
    . . . . . . . 1         忽略前导分隔符
    . . . . . . 0.         如果字符串中不含驱动器字母,则把FCB中的驱动
                            器ID置为0
    . . . . . . 1.         如果字符串中不含驱动器字母,则让FCB中的驱动
                            器ID保持不变
    . . . . . 0. .          如果字符串中不含文件名,就把FCB中的文件名设
                            置为8个空格(20H)
    . . . . . 1. .          如果字符串中不含文件名,就让FCB中的文件名保
                            持不变
    . . . . 0. . .          如果字符串中不含扩展名,就把FCB中的扩展名字
                            设置为3个空格字符
    . . . . 1. . .          如果字符串中不含扩展名,就让FCB中的扩展名保
                            持不变
      一旦使用FCB功能,就可用该功能来正确地设置FCB。该功能的作用是
正确地格式化FCB、并且为其作打开的准备。要想使用FCB的打开或创建功
能,必须将ES中的指针移动到DS:DX上。
      如果所分析的对象中不含非法的文件名,该功能就会返回指针ES:DI,
以便ES:DI+1指向空白字符。

504页
时钟
Int 21h           功能2Ah                               版本1
                  获取系统日期
从系统中获取年、月、日以及星期几
调用寄存器: AH              2Ah
返回寄存器: CX             年份(1980-2099)
                DH          月份(1-12)
                DL          日期(1-31)
                AL          星期几(0=星期天,1=星期一,等等)
                            DOS版本1.1或更高的版本中才出现
                            这一功能
    注释:该功能返回DOS计算出的当前系统日期。这只是对DOS内部时钟的
    检查,而不是访问已安装的实时时钟/日历。按照惯例,如果系统安装有时钟/
    日历,那么在启动该系统时,或者人为地在系统中设置分隔时,就只能从AU-
    TOEXEC.BAT文件中检查时钟或日历。
      有时候,计算日期的系统可能会按照难以预料的方式偏离准确的时间。此
    时系统日期或时间就有可能未得到正确的更新,或者进程有可能干扰或改变
    内部系统时间。该功能就会因此返回不正确的日期(并且,不访问时钟或日期
    芯片,是不可能检查到这个日期的)。
        影响该功能准确性的一个常见错误表现在让系统连续超过24小时地运
    行或不使用(例如,超过一周)。由于只有当DOS检测到已设置的零点标志时,
    日期才能往前进,并且只有在调用有限的几个功能之一时才能实现这个过程,
    因此,在不使用系统时,日期不可能往前进。在下一次使用该系统时,虽然可检
    测到零点(midnight)标志,但是系统却没有记录这段时间已经过了几次零点,
    因而只把日期往后加一天。注意BIOS功能1Ah(获取时钟计数)的任务之一 
    就是重新设置零点标志。当系统经过一段时间的停用之后,最简单的日期较正
    办法是在再次使用该系统时,首先检查并改变系统记录日期。
        为了便于使用,该功能与功能2Bh(设置系统日期) 使用同样的寄存器格
    式。
时钟
Int 21h           功能2Bh                                版本1
                  设置系统日期
在不改变系统时间的前提下,把系统日期设置为某个指定的值
调用寄存器: AH            2Bh
505页
                CX            年份(1980-2099)
                DH            月份(1-12)
                DL            日期(1-31)
    返回寄存器: AL            00h,成功地设置了日期
                              FFh,日期无效,未设置
注释:该功能使用与获取系统日期功能同样的格式。如果已安装了时钟/日
    历,那么通过使用该功能就能够访问该时钟/日历,以获取当前日期并更新系
统日期。在没有安装时钟/日历的前提下,则可揭示用户输入日期并在操作系
    统中对其进行校正,这样,调用获取系统日期功能就能返回正确的日期。
      在文件操作过程中,可使用通过该功能设置的日期来屏蔽文件。
      如果计算机系统带有CMOS时钟,该功能就能令其设置它自己的日期。
时钟
Int 21h         功能2Ch                             版本1
                获取系统时间
获取按小时、分、秒和百分之一秒计算的系统时间
调用寄存器: AH          2Ch
返回寄存器: CH         小时(0-23)
            CL          分(0-59)
            DH          秒(0-59)
            DL          百分之一秒(0-99)
注释:同获取系统日期一样,获取系统时间功能是一种很有用,但却不需要我
们付诸大多注意力的功能。常常要用到该功能以报告出时间或在屏幕上显示
出时间。但是,在使用该功能时,应注意如下两点:
        该功能不从时钟/日历芯片中获取时间。它只获取DOS内部时间,这
        个时间是唯一一种像DOS的设置一样准确的时间。
        在许多系统上,系统的实时时钟精确度都不高,不能分辨出百分之一
        秒的时间。在这种情况下,该功能返回一种不连续的时间值来表示百
        分之一秒时间。
      使用用于非实际系统时间的时间功能的应用程序没有必要去担心时间设
置情况。在有些程序中,也可用先把DOS时间设置为0然后再检查所经过的
时间的应用程序如计时器等。但是,在写入这类程序时,应防止其他程序从时
钟内获取当天的时间,如果先把DOS的时间设置为0,再用应用程序来记录
经过的时间,那么当其他程序返回错误的系统时间时,正在使用这种程序的用
户就会受到干扰。
      该功能使用的寄存器格式与用功能2Dh(设置系统时间)的寄存器格式是

506页
相同的。
时钟
Int 21h         功能2Dh                               版本1
                设置系统时间
在不改变系统时间的前提下,把系统时间设置成指定的小时、分、秒和百分之
一秒
调用寄存器: AH                2Dh
                CH            小时(0-23)
                CL            分(0-59)
                DH            秒(0-59)
                DL            百分之一秒(0-99)
返回寄存器: AL                00h,时间设置成功
                              FFh,日期无效,未设置
注释:在下列情况下,设置系统时间是有益处的:
      ·程序配备有时钟/日历,并且能从芯片时钟准确地设置出日期和时间
      ·程序要求用户设置某个具体时间
      ·用时钟记录经过的时间;先把时钟调整为零,然后用它来显示或记录
        经过的时间而不是系统时间
    这种寄存器格式(与用于功能2Ch——获取系统时间的寄存器格式相同)
允许用户获取时间,寻问有关时间的问题,并且接着更新已改变的时间。在有
专人使用的情况下,最好将时间精确到上下波动不超过1秒的范围内。应尽可
能地按百分之一秒来计算经过的时间,典型的用户都希望采用这种精确度。设
置更高的时间精确度,例如用于天文学方面的应用程序)要求用到特殊的同步
化技术。
    从时钟/日历芯片中或从时间服务器如WWV无线电链络中计算出时间
的程序能把时间精确到百分之一秒。在要求一致的基础上,一些计算机不能返
回具有这种精确度的时间,因为实时时钟的精确度不够。
    如果计算机拥有CMOS时间,该功能就可引发CMOS时钟设置它自己的
时间。
时钟
Int 21h         功能2Eh                             版本1
                设置检验标志
激活DOS检验标志;在写给磁盘时打开这种标志会引导另外的CRC检查(周
期性冗余检查)并增加磁盘传送时间
507页
调用寄存器: AH              2Eh
                AL           00h,关掉检验标志
                            01h,打开检验标志
                DH           00h(早于3.0的DOS版本)
    返回寄存器:无
    注释:怎样才能不通过检验磁盘写而证实它们是正确的呢?虽然能对所有写
    给磁盘的数据强制实行磁盘检验,但是,同平常的操作相比,这种操作过程要
    花去两倍以上的时间。在有些非IBM的BIOS分支系统上,甚至不支持这种操
    作。
        那么到底为什么不这样做呢?很明显,是出于时间上的原因。在没有必要
绝对保证每个磁盘写都正确的时候,就应关掉检验标志。仅仅当面对十分关键
    的功能时,才有必要设置这一标志,但使用之后也应将其关掉。
        即使打开检验标志,也不能绝对保证所写的数据都是正确的,因为检验过
    程不是把所写的数据同支持写的数据进行逐字节地比较而实现的。在这一过
    程中,系统等到完成一个周期才读出所写入的数据,并通过磁盘控制器计算出
    CRC值,然后再把计算出的CRC同第一次把数据写给磁盘时所计算出的值
    进行比较。
        这一过程不能保证数据在内存与磁盘控制器之间的传递时不会出现任何
    错误;该过程只能证实控制器写给磁盘的值与用于计算出第一个CRC的值相
    等,然后再将同一计算过程重复一遍。但是,由于大多数磁盘出错都会导致介
    质失效,这种出错阻止了系统从写入的正确数据中回读CRC,因此,这种检验
    毫无稗益。但是,对很关键的工作如数据的归档传送并随后从硬盘中擦除该数
    据,就必须采用唯一能保证绝对准确的数据传送途径,即:把复制的数据与初
    始数据进行逐字节的比较。
        可用功能54h来确定检验标志的当前设置情况。
磁盘
Int 21h           功能2Fh                               版本2
                  获取DTA地址
    获取用于文件控制块(FCB)文件操作的磁盘传送(DTA)指针的当前值。
    调用寄存器: AH        2Fh
    返回寄存器: ES:BX  指向DTA的指针
    注释:缺省DTA是在程序段前缀(PSP)中位于偏移值80h处的一个拥有
    128个字节的缓冲区。在实际应用中,这种DTA的大小对大多数程序来说都
    够用。但是,若要处理大型的记录或程序提出特殊的磁盘传送要求,那就应再
    设置一个DTA。
      功能1Ah的作用是设置DTA;功能2Fh则能告诉你DTA位于什么地

508页
    方。但是,功能2Fh却不能告诉你DTA有多大(这种信息是必须有的)。在实
    际操作中,如果不能确定DTA的大小是否够用,那么唯一的选择就是自己把
    一个能够处理特定操作的大内存块设置为DTA。
系统
Int 21h             功能30h                                     版本2
                    获取DOS版本号
    返回DOS版本号作为参照,以便应用程序确定软件系统的容量;早于2.0以
    前的DOS版本都返回版本号0。
    调用寄存器: AH            30h
                AL            版本标志
                00h           OEM号
                01h            DOS版本标志
    返回寄存器: AL           主版本号(2.3)
                AH            次版本号(2.1=10)
                BH             OEM号或DOS版本标志
                BL: CX       24位的系列号
    注释:对于直接与DOS打交道的程序员来说,知道DOS版本号是十分有必
    要的,它允许程序员为已安装的系统版本定制程序。把该功能返回的版本号加
    上DOS版本2.0就可能够检验系统能否支持我们所需要的DOS调用。(注
    意:若使用Microsoft C和Borland C++,这些值就能用作全局变量)。
        如果程序运行的DOS版本早于2.0,该功能返回的主、次版本号都为0。
    这样的值能立即告诉你如下的重要信息,即:无路径名、无目录并且无硬盘支
    持。如果在为DOS版本2.0编写程序,但随后却发现你拥有只是DOS的1.x
    版本,那么此时必须采取以下措施:
        1.通过Int 21h,功能09h返回一个错误信息。
        2.通过Int 21h,功能00h退出该程序。
        如果打算支持早于2.0的DOS版本,上述信息将限制你使用某些DOS
    功能。
        在编写程序时,要注意的不只是DOS 1.X提供的限制。因为程序员们已
习惯于使用各种功能来扩展他们的能力,就好像这些功能都能用得上。DOS
    版本3.3增加了一些功能,并允许增加打开文件的数目,以及清除磁盘的文件
    缓冲区。在数据库程序中,使用这些功能可使数据库更易于写。但是,没有
    DOS版本3.3的用户如果不能找到其他途径来解决DOS早期版本中存在的
    各种问题,他们就只能步别人的后尘(并且有可能不是DOS将来版本的买
    主)。
        如果返回了DOS版本标志,那么位3置位表明MS-DOS是在ROM中运
509页
行;否则,表明它是在RAM中运行的,其余的位都未定义。如果返回了OEM
号,是与OEM相关的系列号都出现在BL:CX中,如果没有使用OEM,BL:
CX的值为0。
      DOS版本号通过MS-DOS SETVER命令而设置的,与功能3306h返回
的版本号相比,这个值可能有出入。
系统
Int 21h             功能31h                                   版本2
                    终止并驻留
终止程序并把控制权返回给父进程
调用寄存器: AH              31h
                AL        返回代码
                DX          要保留的内存大小(按节计算)
返回寄存器:无
注释:终止并驻留实用程序是如此的普遍,以致我们很难找出有哪个系统不
使用一个或多个这样的实用程序。除了可用作诸如弹出式计算器、日历和便笺
(notepad)之类的实用程序之外,还可用TSR来为程序序列提供常规的子例
程服务。建成了一种可通过调用指定的中断来激活的功能库之后,就能为此程
序提供标准的实用程序例程,而不必直接将例行程序与程序进行连接。这种功
能减少了模块的大小,并加速了装载模块的进程。
      TSR的作用是终止程序的操作(像功能4Ch一样)但却不把程序占用的
内存返回到由DOS管理的内存库。这样便允许程序继续保存活性并且当它将
自己联结上某种中断时便能被再次激活。例如,将某种程序联结上时钟中断时
就能激活该程序并在屏幕上显示出时钟。并且,如果按下某个键或者程序调用
了中断功能,同样也能激活该程序。
      该功能可替代最初出现在DOS版本1中的Int 27h TSR功能。这种初始
的TSR功能只允许最多64K的内存供自己享用,并且不提供返回代码。而功
能31h则允许它自己使用超过64K的内存并能控制返回代码,通过功能
4Dh,这种返回代码就能供程序的父程序使用。这样便允许批处理文件控制自
身内ERRORLEVEL参数变量的执行情况。
      在启动程序时,这种TSR功能就试图把通过DX寄存器请求的内存分配
给已驻留的程序。但该功能不处理通过调用功能48h而分配全进程的内存。功
能31不关闭程序打开的任何文件,而是让程序打开的文件继续保持打开状
态。通过程序段前缀(PSP)中某个未公开的区域就能把句柄功能与当前活动
的进程联系在一起。当该TSR功能不在活动的进程中时,它就会通过使用当
前活动的进程所打开的句柄来引用文件。但是这种方法不适用于文件控制块
(FCB)功能,因为这种功能是通过进程自身的区域来缓冲的。(关于FCB的具

510页
体情况可参见第9章“目录和文件”。)
      所有使用句柄功能来处理文件和设备(并且在弹时或者相反在活动时需
要使用句柄功能)的TSR,在使用句柄之前必须通过使用未公开的功能50h
和51h来转换DOs关于当前活动进程的定义。否则,就会出现我们不希望出
现的结果,并且还可能严重地毁坏其他程序或数据。
系统:
Int 21h             功能32h                                     版本2
                    获取驱动器参数块
    获取为指定磁盘驱动器定义字符特征的驱动器参数块;在DL=0时,该功能
    的作用与功能1Fh的作用相同。
调用寄存器: AH              32h
                DL          驱动器号(0=缺省;1=A;以此类推)
    返回寄存器: AL         如果驱动器无效则为FFh
                DS:BX     驱动器参数块的地址
    注释:使用该功能时,DS:BX便会返回磁盘参数块(DPB)的地址,这时所说
    的磁盘参数块是DOS用来确定在输入DL时,由DL指定的驱动器内磁盘的
    特定结构信息的参数块。
      表16.3给出了DPB的结构(参见功能1Fh)。注意,不同的DOS版本有
不同的DPB结构,而且,表中给出的每一项后面都注明了各自的用途,使用时
应先看看用途说明。
      由于该功能通过DS寄存器来给出返回值,因此,在调用该功能之前必须
先保存DS的值。
系统
Int 21h             功能33h     子功能00h                       版本2
                    获取Ctrl-Break标志
获取Ctrl-Break检验标志的状态
调用寄存器: AH              33h
                AL           00h,获取标志状态
返回寄存器: DL              00h,关掉Ctrl-Break检验标志
                            01h,打开Ctrl-Break检验标志
注释:除了用于少数的I/O功能外(参见字符I/O功能01h-0Ch),在Int 21h
功能的处理过程中,大部分时间不对Ctrl-Break或Ctrl-C字符进行检查。一旦
开始检查,除了少数几个纯设置或获取标志数的功能外,对其余的Int 21h功
能都要进行检查。子功能00h通过DL返回Ctrl-Break标志的当前状态、至于
511页
如何改变Ctrl-Break检验标志的状态,可参见子功能01h。
    在允许检验的前提下,如果找到了Ctrl-Break或Ctrl-C,那么程序的控制
权就被传递给用于Int 23h的处理程序。此时,可用你自己的某个功能来替换
出Int 23h处理程序,并处理Ctrl-Break或Ctrl-C,而不是禁止Int23h处理程
序。
    这里值得注意的是,Ctrl-Break/Ctrl-C标志是一种系统的全局性标志,它
能影响在DOS系统上运行的所有程序。由于是一种系统全局标志,因此在对
其进行处理的过程中,必须加以小心,因为它有可能影响到其他的进程、却不
影响令该功能激活或失活的进程。
系统
Int 21h           功能33h   子功能01h                   版本2
                  设置Ctrl-Break标志
设置Ctrl-Break/Ctrl-C检验标志的状态
调用寄存器: AH            33h
              AL           01h设置标志状态
              DL           00h,已停止对Ctrl-Break的检查
                             01h,正在进行Ctrl-Break检查
返回寄存器:无
注释:除了用于少数几种I/O功能外(这种例外情况可参见字符I/O功能
01h-0Ch),在Int 21h功能的处理过程中,很少检查Ctrl-Break/Ctrl-C字符。
当检查开始时,除了少数几种纯粹只设置或获取标志数据的功能外,对其余的
Int 21h功能都要进行检查。子功能01h则能建立起Ctrl-Break检验标志的当
前状态;关于检验其状态的信息可参见子功能00h。
      在允许检查时,如果找到了Ctrl-Break/Ctrl-C,那系统的控制权就被转交
给了用于Int 23h的处理程序。可以用你自己的程序来替换出Int 23h处理程
序并处理Ctrl-Break/Ctrl-C,而不用去禁止这种处理程序。
      值得注意的是Ctrl-Break/Ctrl-C标志是一种系统全局标志,它能影响
在DOS系统上运行的一切进程。由于是一种系统全局标志,因此,在对它进行
处理时应加以小心,因为它有可能影响其他进程,却对激活或禁止该功能的进
程不起作用。
系统
Int 21h         功能33h     子功能05h                 版本2
                获取引导驱动器代码
返回一种代码,该代码能反映出最近是从哪一个驱动器中引导系统的
512页
调用寄存器: AH                33h
                 AL            05h,获取引导驱动器代码
返回寄存器: DL               引导驱动器代码(1=A,2=B,3=C如此等等)
注释:通过版本4中才推出的这种功能,程序就能确定最近是从哪个驱动器
中引导系统的。每当系统进行自身的初始化时,这种信息就被保存在DOS内
核区域内。
系统
Int 21h             功能33h     子功能06h                     版本2
                    获取MS-DOS版本号
返回MS-DOS版本号修订版本号以及版本标志
调用寄存器: AH              33h
              AL             06h,获取MS-DOS的版本号
返回寄存器: BL             主版本号
              BH            次版本号
              DL          位0-2中为修订版本号;其余的位都是保留位,
                            并且值为0
              DH            版本标志。位3置位,表明MS- DOS在ROM中
                            运行;否则表明MS-DOS在RAM中运行。位4
                            置位,表明MS-DOS在上位内存区(HMA)内
                            运行;否则表明MSDOS在常规内存中运行。
                            其余的位都用作保留,其值都为0。
注释:通过SETVER不能改变MS-DOS的版本号
系统
Int 21h             功能34h                                     版本2
                    返回InDOS标志的地址
一种内部的DOS标志用于表明DOS何时在处理Int 21h功能
调用寄存器: AH              34h
返回寄存器: ES:BX       指向InDOS标志的指针
注释:一旦DOS进入了Int 21h功能,DOS就会加上InDOS标志,当DOS退
出时,它又会失去这种标志。 DOS和终止并驻留(TSR)实用程序都用这种标
志来确定DOS是否在内核中并且是否在处理Int 21h功能。当TSR实用程序
确定DOS在处理其他功能时,它可选择做以下两事情之一:
      ·继续这一进程,因为此时不需要使用Int 21h功能。
513页
          拒绝处理,因为需要用到Int 21h功能。
        值得注意的是操作系统内核不完全是可重入的。因此,当操作系统正处在
    内核中时如果出现了中断,服务例程就不能使用Int 21h功能来处理中断,因
    为对一种功能的调用可能与前面的调用发生冲突。在这种情况下,稍不小心就
    会冲毁系统,不过,也绝对没有必要去翻出中断处理程序来处理此时的中断。
        出于操作上的需要,小部分DOS内核代码的确可通过Int 21h接口来使
    用其他部分的代码,并且把InDOS标志用作防止代码出错的信号。此时In-
    DOS标志还可保证正式的TSR程序如PRINT.COM及其类似的程序能正常
    运转。但是,这种标志也常常出现错误引导的情况。
        当DOS在等待键盘输入时,它在循环过程中是空闲的,并且一旦有字符
    输入进来它就会读取这些字符。因此,只要DOS尚处于等待状态,就能安全地
    使用文件处理及其他一些功能,即使InDOS标志指示的是其他情况。为了让
    你清楚可安全地使用这些功能,DOS在它的输入循环中不间断地调用Int 28h
    (键盘忙碌循环)。TSR能截获Int 28h,这样,当Int 28h缺省时,它就成为一个
    指向IRET的指针,并且只要还在正常运转,它就会检查要做的事情。
        例如,如果按下某个热键启动了TSR之后,但它却发现DOS正在执行
    Int 21h功能,因为已设置了InDOS标志,此时,TSR就会设置一种内部的标
    志来表明“我已被调用,但我不能做任何事情”。无论何时,只要调用Int 28h,
    就能检测到InDOS标志。反过来,如果设置InDOS标志,处理程序就会立即
    转向TSR部分以实现被请求的功能。
        在时钟计数期间,TSR还能截取时钟中断,并检查InDOS和TSR引用标
    志。这样做的目的是为了防止在首次调用TSR时,出现Int 21h功能(而不是
    字符I/O功能)是活动的情况。因为一旦出现这样的情况,时钟中断就能检测
    到InDOS标志的清除以及TSR引用标志的置位。然后,时钟中断根据实际情
    况确定可以实现的请求功能。
        但是,在DOS版本2中使用Int 28h仍然会莫名其妙地导致系统冲毁。究
    其原因在于版本2在未来得及把控制权调度给任何被请求的功能之前已先切
    换到它自己的内部堆栈上;这样,当DOS在处理00到0Ch范围内的某个功能
    时(在调用Int 28h时,DOS几乎都在处理这个范围内的某个功能),如果出现
    了调用其它功能的情况,那么第二个堆栈就会切换出来,其结果是破坏了初始
    功能调用所需要的信息。
        防止的办法十分简单但却极有意思:即通过操纵DOS的关键出错
    (CritErr)标志,令DOS相信它正在处理一种关键性的错误。在调用某个功能
    之前,先设置CritErr标志能强迫DOS改变用它自己的内部堆栈。但在退出该
    功能之后,必须将这一标志恢复到它的初始值。
        在DOS版本3中,系统在进行任何堆栈切换之前,首先修改DOS调度代
    码以检测起作用的功能;如果调用程序请求这些功能中的任何一个DOS都会
    使用调用者自己的堆栈,从而可避免出现问题。在DOS版本4中,这种调度代

514页
码依然保持未变。
      CirtErr标志只是一个字节,它表明DOS已遇到了严重出错的情况,并且
正在处理Int 24h(关键出错)处理程序例程。为了让这种处理程序尽可能地应
    用到更多的DOS功能中去,就可设置CritErr标志并导致DOS调度代码以使
    用备用的内部堆栈而不是普通的堆栈空间。虽然调度代码的方式与完全可重
入的编码方式不同,但这样做能允许有限的功能重新使用调度的代码。
      在版本2至版本4之间的所有版本中,CirtErr标志与InDOS标志是毗邻
    的。遗憾的是,在版本2和版本3之间,CritErro标志的位置出现了变动。在版
    本2中,它是位于紧挨在InDOS标志之上的一个字节,而在版本3和版本4
    中,它却变成了紧跟在InDOS标志之下的一个字节。
    注意:若从Int 28h处理程序中进行调用,该功能就会导致出现一些问题。该
          功能的正确用法应是在它成为常驻功能之前,先安装TSR。基于这一
          点可使用所有的DOS功能来确定适用于CritErr的正确位置。使用这
          种功能可获取和保存InDOS标志的地址,确定DOS版本号,并根据
          要求相应地增加或消除CritErr标志,并把该标志的地址保存在一个
          单独的指针内。
      这样,当TSR弹出时,它就能使用它自己的InDOS指针以确定DOS是
    否为活动的,并且如果有必要,它还可用它自己的CritErr指针来获取该标志
    的当前值。然后将该值保存起来,并设置CritErr标志以强制使用备用的堆栈、
    着手处理一切急需处理的事情,并在退出之前恢复初始的标志值。
系统
Int 21h           功能35h                                 版本2
                  获取中断向量
获取用于指定中断的中断处理程序地址
调用寄存器: AH              35h
              AL            中断号
返回寄存器: ES:BX       指向中断处理程序的指针
注释:对某个指定的中断来说,中断处理程序地址虽然是绝对可用的,但是,
该功能却是获取中断向当前设置的唯一可靠的途径。该功能可保证顺利地完
成获取工作并为向量返回一个可靠的值,其他的程序例如终止驻留(TSR)实
用程序则可在该功能顺利地返回了值之后改变这一中断向量。当单用户、单任
务操作的系统出现在该功能的使用范围内时,上述过程却会发生。
      当设置一道程序以便从某个中断处理开始工作时,就应使用功能35h来
确定该中断的初始设置,以便在完成工作时可将该中断还原。在做这项工作时
必须细心,因为有可能出现与TSR或其他中断处理程序发生冲突的情况。如
515页
果能记住某个中断值,并且随着TSR的启用而改变了这个值,那么就要以采
用一种能禁止该TSR的方法来替换出这一中断。
      为了防止出现冲突,应一直打算恢复的中断向量同程序最初在该向量中
设置的值进行对照。如果发现这些值不相同,那么说明自从保存了这个值以
后,其他的程序已修改了这个值,并且此时已无法安全地实现恢复操作或者不
能安全地从内存中撤走程序。如果当前值与初始值相符合,就可以安全地把中
断恢复到其初始值。
磁盘
Int 21h             功能36h                                   版本2
                    获取*磁盘空间
    除了有选择地获取磁盘的有关信息,还获取该驱动器上有用的磁盘空间
    调用寄存器: AH          36h
                DL        磁盘驱动器(0=缺省驱动器;1=A,如此等等)
    返回寄存器: AX         每簇的扇区数(如果驱动器无效,则为FFFFh)
                BX          有用的簇数
                CX          每扇区的字节数
                DX          驱动器上的簇数
    注释:该功能与功能1BH和1Ch相似,其作用是返回可用来确定磁盘上有用
    空间的基本信息。
      使用该功能时,可从指定要检查的磁盘驱动器着手。此时,可获取如下的
原始信息:
        ·每簇的扇区数
        ·可用的簇数
        ·每扇区的字节数
        ·驱动器上的总簇数
      得到这些信息后,就可按下面的算式计算出可用的空间量:
(有用的簇数)*(每簇的扇区数)*(每扇区的字节数)
所得的结果即是该驱动器上可用的字节数。将这一数字除以1024可得到千字
节数,或除以记录长度得到可用于数据库等的记录数。
      要得到磁盘上有用的空间总量,可按下面的算式计算:
(驱动器上的总簇数)*(每簇的扇区数)*(每扇区的字节数)
得出结果后,就可写出一种功能来打印出如下信息:
          xxxx bytes free out of yyy

516页
功能1Bh和1Ch可返回与上述类似的信息。
STOP
Int 21h         功能37h   子功能00h                   版本2
                获取开关字符(Switchar)
获取当前开关字符
调用寄存器: AH              37h
              AL           00h
返回寄存器: AL              FFh,表示AL子功能不在0-3这个范围内
              DL            开关字符
注释:开关字符是DOS在把字符串分析成指定的命令开关时所使用的字符。
通常情况我们都把开关字符设置成斜线(/),但是,根据应用程序的要求我们
也可将它设置成其他字符。
STOP
Int 21h           功能37h     子功能01h
                  设置开关字符
允许将当前开关字符复位
调用寄存器: AH              37h
              AL           01h
              DL            开关字符
返回寄存器: AL              FFh,表示AL子功能不在0-3这一范围内
注释:开关字符是以DOS在把字符串分析成指定的命令开关时所使用的字符,
通常情况都用斜线(/)来表示,但也可根据应用程序的需要,将它设置成其他
的字符。
      如果使用这种功能,首先必须确定当前的开关字符(子功能0)并将其保
存起来,以便在完成了程序之后,能将当前开关字符恢复到它的初始化状态。
STOP
Int 21h           功能37h   子功能02h                     版本2
                  读取设备的可用性
    指出设备名称前面有无必要加上假路径名/DEV/
    调用寄存器: AH          37h
                AL         02h
    返回寄存器: AL          FFh,表示AL子功能不在0-3这个范围内
                DL        0,/DEV/必须加在设备名之前

517页
                              <>0,不必把/DEV/加在设备名的前面
    注释:设备可用性标志(仅仅在版本2中采用)控制一种与UNIX类似的功
    能,这类功能通过强迫为各种设备加上假目录DEV从而使得文件和设备具
    有同样的名称,当该标志为00时,表示只能在DEV目录中打开或关闭设备;
    若为非零标志,则表示允许设备领先于文件名,这意味着在系统内,所有文件
    都不会有与设备相同的名字。在版本3内,这种标志被永久地设置为非零值,
    并且禁止子功能3的使用。
STOP
Int 21h              功能37h     子功能03h                 仅用于版本2
                    设置设备的可用性
    确定在设备名前面有无必要加上假路径名/DEV/
    调用寄存器: AH            37h
                AL           03h
                DL          0,必须把/DEV/加在设备名之前
                              <>0,没有必要把/DEV/加在设备名之前
返回寄存器: AL             FFh,表示AL子功能不在0-3这个范围内
                DL          设备的可用性标志(同输入一样)
注释:设备可用性标志(仅用于版本2)控制着一种与UNIX类似的功能,该
功能通过强制地为所有设备加上假目录DEV;从而允许文件和设备具有同样
    的名称。该标志为00时,表示只能在DEV目录内打开或关闭设备;任何非零
    标志都允许设备领先于文件名,这就意味着在整个系统内没有任何文件拥有
与设备相同的名字。版本3已将这一标志永久地设置成了非零值,并且已禁止
    了子功能3的使用。
系统
Int 21h             功能38h                                     版本2
                    获取/设置当前国家信息
获取当前国家信息;在DOS 3.0以及更高的版本中还允许设置当前国家信息
调用寄存器: AH              38h
              AL           00,获取当前国家信息
                            在DOS  3.0以及更高的版本中
                            01-FEh,规定的小于255的国家代码
                            FFh,国家代码出现在BX寄存器中
              BX            如果AL=FFh则为国家代码
              DS:DX      指向信息缓冲区的指针
              DX            为FFFFh以设置国家代码(以DOS3.0以及

518页
                              更高的版本)
    返回寄存器:进位标志清除表示成功
                BX            国家代码(仅用于DOS版本3)
                DS:DX       指向返回的国家信息的指针
                  进位标志置位表示出错
                  AH          错误代码
                              02h,无效的国家(文件未找到)
    注释:由于DOS是一种国际性的磁盘操作系统,因此,为DOS设计的程序必
    须能在国际性的设置中工作。该功能的作用是通知程序对各种用于显示信息
    的国家参数应分别采用什么样的表现方式。例如,日期格式类型的国家参数用
    字节0和1进行编码。
        当该功能获得了与国家有关的信息时,它就会通过这种信息返回一个指
    向32个字节的缓冲区的指针。在DOS版本3以及更高的版本中,该功能还可
    用来设置供其他程序使用的国家信息。
        国家代码通常为国际性的电话前缀代码。一些较典型的代码(例如,
    American Samoa为684,Portugal为351)几乎可在所有电话号码簿的前部找
    到。值得注意的是,这些号码可以大于255。为了适应这种情况,当AL寄存器
    被设置为FFh时,该功能可使用BX寄存器来保存这些代码。
        表16.5列出了国家信息表的格式,这些信息都是DS:DX指针所指向
    的信息。
                        表16.5国家信息缓冲区中的内容
位偏移值              长度          意    义
    DOS版本2
    00h                   字              日期和时间格式
                          0=美国          月日年,时时:分分:秒秒
                          1=欧洲          日月年,时时:分分:秒秒
                          2=日本         年月日,时时:分分:秒秒
    02h                   字节            货币符号
    03h                   字节            零
    04h                   字节            千分隔符
    05h                   字节            零
    06h                   字节            小数分隔符
    07h                   字节            零
    08h                    18字节         保留
    Dos版本3或版本4
    00h                   字              日期格式
                          0= 美国         月日年
519页
位偏移值              长度            意    义
                        1= 欧洲          日月年
                        2= 日本         年月日
02h                      5字节          货币符号串(ASCIIZ)
07h                     字节            千分隔符
08h                     字节            零
09h                     字节            小数分隔符
0Ah                     字节            零
0Bh                     字节            日期分隔符
0Ch                     字节            零
0Dh                     字节            时间分隔符
0Eh                     字节            零
 0Fh                字节              货币格式
                                        00h=在货币前面的符号,中间无间隔
                                        01h=在货币后面的符号,中间无间隔
                                        02h=在货币前面的符号,间隔一个空格
                                        03h=在货币后面的符号,间隔一个空格
                                        04h=代替小数分隔符的符号
10h                   字节              小数点之后的位数
11h                   字节              时间格式
                                        位0=0,12小时钟
                                        位0=1,24小时钟
12h                   双字              大小字变换调用地址
16h                     字节            数据列表分隔符
17h                     字              零
18h                      8字节          保留
DOS版本5
00h                     字              日期格式
                        0=美国         月日年
                        1=欧洲         日月年
                        2=日本         年月日
02h                      5字节          货币符号串(ASCIIZ)
07h                      2字节          千分隔符(ASCIIZ)
09h                      2字节          小数分隔符(ASCIIZ)
0Bh                    2字节           日期分隔符(ASCIIZ)
0Dh                      2字节          时间分隔符(ASCIIZ)
0Fh                     字节            货币格式
                                         00h=在货币前面的符号,中间无间隔
                                        01h=在货币后面的符号,中间无间隔
                                        02h=在货币前面的符号,间隔一个空格
                                        03h=在货币后面的符号,间隔一个空格
                                        04h=代替小数点分隔符的符号
10h                   字节              小数点之后的位数