DOS程序员手册(十四)

附录A ASCII字符集

十进制        十六进制      二进制              AscII         控制        按键

X10         X16           X2                字符

000               00              0000 0000              null              NUL            ^@

001               01              0000 0001                                SOH            ^A

002               02              0000 0010                              STX            ^B

003               03             0000 0011                                ETX            ^C

004               04              0000 0100                                EOT            ^D

005               05             0000 0101                                ENQ            ^E

006               06              0000 0110                                ACK            ^F

007               07              0000 0111                                BEL            ^G

008                08              0000 1000                             BS             ^H

009               09              0000 1001                                HT               ^I

010               0A             0000 1010                                LF             ^J

011               0B              0000 1011                                VT             ^K

012               0C              0000 1100                                FF             ^L

013               00              0000 1101                                CR             ^M

014                0E              0000 1110                             SO             ^N

015               0F              0000 1111                                SI             ^O

016               10              0001 0000                                DLE           ^P

017               11              0001 0001                                DC1            ^Q

018               12              0001 0010                                 DC2            ^R

019               13              0001 0011                !!               DC3            ^S

020                14              0001 0100                               DC4           ^T

021                15              0001 0101                             NAK            ^U

022               16              0001 0110                -               SYN            ^V

023                17              0001 0111                            ETB            ^W

024                18              0001 1000                               CAN           ^X

025               19              0001 1001                                EM             ^Y

026               1A             0001 1010                                 SUB           ^Z

027            1B        0001 1011                     ESC      ^[

028           1C      0001 1100          FS          FS        ^\

029            1D        0001 1101         GS          GS       ^]

800页

十进制        十六进制    二进制            ASCII       控制          按键

X10         X16         X2                字符

030                 1E            0001 1110              RS

031                 1F           0001 1111              US

032               20              0010 0000              SP

033               21              0010 0001                !

    034           22              0010 0010                "

035                 23            0010 0011                #

036                 24            0010 0100                $

037                 25           0010 0101                %

038               26              0010 0110                &

039               27              0010 0111                '

040                 28            0010 1000                (

041                  29            0010 1001              )

042                 2A          0010 1010                *

043                 2B            0010 1011                +

044                 2C            0010 1100                ,

    045             2D            0010 1101                -

    046             2E            0010 1110                .

    047             2F            0010 1111                /

    048             30            0011 0000                0

    049             31            0011 0001                1

    050             32           0011 0010                2

   051             33            0011 0011                3

052               34            0011 0100                 4

053               35              0011 0101                5

054               36              0011 0110                6

055               37              0011 0111                7

056               38              0011 1000                8

057               39              0011 1001                9

058               3A            0011 1010                :

059               3B              0011 1011                ;

060                 3C            0011 1100                <

061                 3D            0011 1101                =

062                 3E            0011 1110                >

063                 3F            0011 1111                ?

064                 40            0100 0000                @

    065             41            0100 0001                A

   066             42            0100 0010                B

    067             43            0100 0011                C

    068             44            0100 0100                D

801页

十进制    十六进制  二进制        ASCII    控制      按键

X10     X16       X2            字符

069                45            0100 0101              E

070                46            0100 0110              F

071               47              0100 0111              G

072               48              0100 1000              H

073               49              0100 1001              I

074              4A              0100 1010              J

075               4B             0100 1011              K

076               4C              0100 1100              L

077               4D              0100 1101              M

078              4E             0100 1110              N

079               4F              0100 1111              O

080               50              0101 0000              P

081               51              0101 0001              Q

082               52              0101 0010              R

088               53              0101 0011              S

084               54              0101 0100              T

085               55              0101 0101              U

086                56             0101 0110               V

087                57            0101 0111              W

088                58             0101 1000              X

089                59             0101 1001              Y

090                5A            0101 1010              Z

091                5B             0101 1011               [

092               5C              0101 1100                \

093               5D               0101 1101              ]

094               5E              0101 1110               ^

095               5F              0101 1111              _

096               60              0110 0000              `

097               61              0110 0001                a

098               62              0110 0010              b

099               63              0110 0011                c

100               64              0110 0100               6

101               65             0110 0101                e

102               66             0110 0110                f

103               67              0110 0111                g

104               68              0110 1000                h

105                69              0110 1001               i

106                6A              0110 1010              j

802页

十进制      十六进制    二进制        ASCII     控制        按键

X10        X16         X2            字符

107             6B          0110 1011             k

108              6C         0110 1100             l

109              6D         0110 1101             m

110              6E         0110 1110             n

111              6F         0110 1111             o

112              70           0111 0000           p

113             71            0111 0001          q

114              72           0111 0010          r

115             73            0111 0011          s

116             74            0111 0100         t

117              75           0111 0101           u

118              76           0111 0110          v

119             77            0111 0111          w

120             78            0111 1000          x

121             79            0111 1001            V

122             7A            0111 1010            Z

123             7B            0111 1011          {

124              7C            0111 1100          |

125             7D            0111 1101            }

126             7E            0111 1110            ~

127             7F            0111 1111          DEL

128               80              1000 0000

129               81              1000 0001

130               82              1000 0010

131               83              1000 0011

132               84              1000 0100

133               85              1000 0101

134               86              1000 0110

135               87              1000 0111

136               88              1000 1000

137               89              1000 1001

138                 8A            1000 1010

139               8B              1000 1011

140               8C              1000 1100

141               80              1000 1101

142               8E              1000 1110

143               8F              1000 1111

144               90              1001 0000

803页

十进制        十六进制    二进制            ASCII       控制       按键

X10         x16         X2                字符

145               91                1001 0001

146               92                1001 0010

147               93                1001 0011

148               94                1001 0100

149               95                1001 0101

150              96                1001 0110

151               97                1001 0111

152               98                1001 1000

153               99                1001 1001

154               9A                1001 1010

155               9B                1001 1011

156               9C                1001 1100

157               9D                1001 1101

158               9E                1001 1110

159               9F                1001 1111

160               A0                1010 0000

161               A1                1010 0001

162               A2                1010 0010

162               A3                1010 0011

164               A4                1010 0100

165               A5                1010 0101

166               A6                1010 0110

167               A7                1010 0111

168               A8                1010 1000

169               A9                1010 1001

170               AA             1010 1010

171               AB                1010 1011

172               AC                1010 1100

173               AD             1010 1101

174               AE                1010 1110

175               AF                1010 1111

176               B0               1011 0000

177               B1               1011 0001

178               B2               1011 0010

179               B3               1011 0011

180               B4               1011 0100

181               B5                1011 0101

182               B6               1011 0110

804页

十进制      十六进制    二进制            ASCII       控制        按键

X10         X16         X2                字符

    183             B7             1011 0111

    184              B8             1011 1000

    185             B9             1011 1001

    186               BA            1011 1010

    187              BB            1011 1011

    188              BC             1011 1100

    189              BD             1011 1101

    190             BE             1011 1110

    191             BF              1011 1111

    192             C0              1100 0000

    193             C1              1100 0001

    194             C2              1100 0010

    195             C3              1100 0011

    196             C4              1100 0100

    197             C5              1100 0101

    198             C6              1100 0110

    199             C7              1100 0111

    200             C8              1100 1000

    201             C9              1100 1001

    202             CA              1100 1010

    203             CB              1100 1011

    204             CC              1100 1100

    205             CD              1100 1101

    206             CE              1100 1110

    207             CF              1100 1111

    208             D0              1101 0000

    209             D1              1101 0001

    210             D2              1101 0010

    211             D3              1101 0011

    212             D4              1101 0100

    213             D5              1101 0101

    214             D6              1101 0110

    215             D7              1101 0111

    216             D8              1101 1000

    217             D9              1101 1001

    218             DA              1101 1010

    219             DB              1101 1011

    220             DC              1101 1100

    221              DD             1101 1101

805页

十进制      十六进制      二进制            AsCII       控制          按键

X10           X16          X2                字符

222          DE            1101 1110

223           DF          1101 1111

224              E0               1110 0000

225               E1                1110 0001

226               E2                1110 0010

227               E3                1110 0011

228               E4                1110 0100

229               E5                1110 0101

230               E6                1110 0110

231               E7                1110 0111

232               E8                1110 1000

233               E9               1110 1001

234               EA                1110 1010

235               EB                1110 1011

236               EC                1110 1100

237               ED                1110 1101

238               EE                1110 1110

239               EF                1110 1111

240               F0               1111 0000

241               F1                1111 0001

242               F2                1111 0010

243               F3                1111 0011

244               F4                1111 0100

245               F5                1111 0101

246               F6                1111 0110

247               F7                1111 0111

248               F8                1111 1000

249              F9                1111 1001

250               FA                1111 1010

251               FB                1111 1011

252               FC                1111 1100

253               FD                1111 1101

254               FE                1111 1110

255               FF                1111 1111

806页

附录B 选中的内存位置

      介绍选中的内存位置表的目的是帮助读者了解系统功能的操作方式。直接访问这些

位置中的任何一个都会使得程序极其不可移植,所以,如果不是没有任何别的办法得到所

需的特性和响应,就不应对其进行直接访问。

      弄清楚了这些信息在内存中的位置,首先能有助于获取信息。但是改变BIOS和DOS

数据区中的信息将产生极大的破坏(当然,如果对冲毁系统不介意的话,这样做也极其有

趣)。

                      B.1中断表

      绝对地址的00000至003FF为中断地址表。该表由中断00至FFh的中断地址组成,

每个地址占用4个字节。因此,为了在中断地址表中找到某个指定中断的地址,只需将中

断号乘以4就可以了。例如,用于中断C3h的绝对地址为030Ch。在表B.1中,前两列的

号采用的十六进制表示方法。

                          表B.1 中断00h至FFh的中断地址

中断号               地址                    含    义

Int 00               00000                硬件除0

Int 01               00004                硬件单步捕获

Int 02               00008                不可屏蔽

Int 03               0000C                调试程序断点设置

Int 04               00010                算术溢出

Int 05               00014                 BIOS打印屏幕

Int 06               00018                无效操作码

Int 08               00020                 IRQ0—时钟计数

Int 09               00024                 IRQ1—键盘动作

Int 0A            00028                 IRQ2

Int 0B               0002C                 IRQ3-COM2

Int 0C               00030                 IRQ4-COM1

Int 0D               00034                 IRQ5—PC/XT硬盘

Int 0D                                      IRQ5-PCATLPT2

Int 0E               00038                 IRQ6—软盘

Int0F               0003C                 IRQ7-LPT1

Int 10               00040                 BIOS视频服务

807页

中断号              地址                  含    义

Int 11               00044               BIOS设备列表服务

Int 12               00048               BIOS内存大小服务

Int 13               0004C               BIOS磁盘/软盘服务

Int 14               00050              BIOS通信服务

Int 15               00054              BIOS系统服务

Int 16               00058               BIOS键盘服务

Int 17               0005C               BIOS打印机服务

Int 18               00060              执行ROMBASIC

Int 19               00064              重引导系统

Int 1A               00068               BIOS当天时间服务

Int 1B               0006C              Ctrl-Break处理程序地址

Int 1C               00070              供Int 08处理程序调用

Int 1D               00074              视频初始化参数表

Int 1E               00078              磁盘初始化参数表

Int 1F               0007C              图形字符表

Int 20               00080               DOS程序终止

Int 21               00084               DOS功能服务

Int 22               00088              程序终止地址

Int 23               0008C               DOSCtrl-Break

Int 24              00090               关键出错处理程序

Int 25               00094               DOS绝对磁盘读

Int 26               00098               DOS绝对磁盘写

Int 27               0009C               DOSTSR

Int 28               000A0               DOS空闲中断

Int 29               000A4               DOS快速存放字符

Int2A              000A8               MS-Net访问

Int 2E               000B8              DOS主外壳程序装入程序

Int 2F               000BC               DOS多路复用中断

Int 33               000CC              鼠标中断

Int 3F               000FC              覆盖管理程序

Int 40               00100              如果安装了硬盘则为软盘中断向量

Int 41               00104              硬盘1参数表

Int 42               00108               EGA BIOS将其用于重定向视频中断

Int 43               0010C               EGA初始化参数表

Int 44               00110               EGA字符表

Int 44                                   Novell NetWare API

Int 46               00118              硬盘2参数表

Int 4A                00128               PCAT:Int 70报警

Int 5A               00168              簇

Int 5B               0016C              由簇程序使用

Int 5c               00170             Net BIOS接口

808页

中断号              地址                    含    义

Int 67               0019C                扩展内存管理程序服务

Int 70               001C0                 IRQ8——PCAT实时时钟

Int 71               001C4                 IRQ9-pc AT重定向为Int 0A

Int 72                 001C8               IRQ10

Int 73                 001CC               IRQ11

Int 74                 001D0               IRQ12—鼠标中断

Int 75                 001D4               IRQ13-PCAT数学协处理器

Int 76                 001D8               IRQ14——硬盘事件

Int 77                 001DC               IRQ15

Int 7A                001E8               NoVEll NetWare API

                      B.2 BIOS数据区

      绝对磁盘范围00400至004FF为ROM BIOS的数据区。这一区域是一个大杂烩,其

中包括了各种数据结构,表、地址和标志。在下表中,第一列为数据的绝对地址,第2列为

从BIOS数据区开始算起的偏移值——即从段地址0040处开始的偏移值。之所以将这两

列的信息部列举出来是为了便于选择一个更适合不同编程风格的值(头两列的值都采用

的是十六进制表示法)。其余两列是作为解释用的。

      注意地址00500处的标志。尽管从表面上看该标志位于BIOS数据区之外,但由于它

是由打印屏幕例程使用的,因此,它实质上属于这个数据块。

                              表B.2 BIOS数据区

地址          偏移值    长度            含    义

00400          00       字            COM1地址(0表示未使用)

00402          02       字            COM2地址(0表示未使用)

00404          04         字          COM3地址(0表示未使用)

00406          06         字          COM4地址(0表示未使用)

00408          08         字          LPT1地址(0表示未使用)

0040A        0A          字          LPT2地址(0表示未使用)

0040C          0C         字          LPT3地址(0表示未使用)

0040E          0E         字          LPT4地址(0表示未使用)

00410          10         字          设备标志

00412          12         字节        初始化标志

00413          13         字          以千字节为单位的基本内存大小

00415          15         字节        在I/O通道中的内存量

00416          16         字节        未使用

00417          17         字          键盘状态标志

00419          19         字          ALT-键小键盘存储空间

0041A          1A         字          键盘打印超前缓冲区头

0041C          1C         字          键盘打印超前缓冲区尾

809页

地址          偏移值      长度            含    义

0041E          1E          16字节       键盘打印超前缓冲区

0043E          3E         字节          软盘数据

0043F          3F         字节          软盘电机状态

00440          40         字节          软盘电机超时计数

00441          41         字节          最后一次软盘操作状态

00442          42          7字节        磁盘命令工作区域

00449          49         字节          当前显示模式

0044A          4A         字            屏幕列数

0044C          4C         字            以字节为单位的显示内存页大小

0044E          4E         字            相对于当前显示页的偏移值

00450          50         字            显示页0的光标位置

00452         52          字            显示页1的光标位置

00454          54         字            显示页2的光标位置

00456          56         字            显示页3的光标位置

00458          58         字            显示页4的光标位置

0045A          5A         字            显示页5的光标位置

0045C          5C         字            显示页6的光标位置

0045E          5E         字            显示页7的光标位置

00460          60         字            当前光标模式

00462          62         字节          当前视频页号

00463          63         字            活动显示卡的端口地址

00465          65         字节          视频硬件方式选择寄存器值

00466          66         字节          彩色调色板设置

00467          67         双字          磁带数据

0046B        6B          字节          中断发生标志

0046C          6C         双字          从零点开始的计时器计数

00470          70         字节          零点标志(如果自上次读取以来经过了零点,则该标

                                        志置位)

00471          71         字节          中断标志

00472          72         字            复位标志

00474          74         字节          最近一次硬盘操作的状态

00475          75         字节          硬盘驱动器数

00476          76         字节          硬盘控制字节

00477          77         字节          硬盘I/O端口偏移值

00478        78          字节          LPT1超时计数器

00479          79         字节          LPT2超时计数器

0047A          7A         字节          LPT3超时计数器

0047B         7B          字节          LPT4超时计数器

0047C          7C         字节          COM1超时计数器

0047D          7D         字节          COM2超时计数器

0047E          7E         字节          COM3超时计数器

810页

地址          偏移值      长度            含    义

0047F          7F         字节          COM4超时计数器

00480          80         字            相对于键盘缓冲区开头的偏移值

00482          82         字            相对于键盘缓冲区末尾的偏移值

00484          84         字节          EGA/MCGA/VGA屏幕上的行数(以0为基数)

00485          85         字            在EGA/MCGA/VGA屏幕上的字符高度

00487          87         字            EGA/VGA控制标志

00489          89         字节          MCGA/VGA控制标志

0048A          8A         字节          MCGA/VGA数据偏移值指针

0048B         8B          字节          软盘介质控制标志

0048C          8C         字节          硬盘控制卡的状态

0048D          8D         字节          硬盘控制卡的出错标志

0048E          8E         字节          硬盘中断控制标志

0048F          8F         字节          软盘控制器信息

00490          90         字节          软盘驱动器0当前介质状态

00491          91         字节          软盘驱动器1当前介质状态

00492          92         字节          软盘驱动器0起始介质状态

00493          93         字节          软盘驱动器1起始介质状态

00494          94         字节          软盘驱动器0磁道号

00495          95         字节          软盘驱动器1磁道号

00496          96         字节          键盘状态

00497           97        字节          键盘LED控制

00498          98         双字          用户等待例程标志指针

0049C          9C         双字          用户等待计数器

004A0          A0         字节          用户等待活动标志

004A8          A8         双字          EGA/MCGA/VGA视频保存表指针

00500          100        字节          打印屏幕状态标志

811页

附录C 一种标准的TSR标识技术

      对于在同一时间里同时使用几种TSR程序来说,长期以来一直存在着一个问题,这

就是:当这些程序之间出现冲突时,我们找不到任何可遵循的标准来管理冲突。

      早在1986年,一大群TSR开发者组织起了一支队伍,旨在建立这样一种标准。大多

数在TSR开发上居于领导地位的开发者参加了这一组织。

      然而,在经过首次努力尝试以生产出一种可供独家程序和商业化程序使用的完整应

用程序接口(这种努力未能得到商用TSR出版部门的足够支持)之后的一段时间时,许多

成员离开了这一队伍,并转而从事其它方面的研究工作。不过,他们在共同研究期间已开

发并发行了一种接口,该接口允许开发者与他们自己的(或其它人的)TSR进行通信,此

    外,他们的设计部门还把用于Microsoft和Turbo C、TurboPascal版本4和版本5以及汇

    编语言程序的原有例程库(即众所周知的TesSeRact)设计成了一种可用的共享件。

      TesSeRact标准指定了一组链接着DOS的多路复用中断(2Fh)的功能。由于DOs使

    用这种中断来与其自己的TSR(如ASSIGN、PRINT和SHARE)通信,因此,TesSeRact

    开发队伍感到最合适的方法是用相同的接口来服务于不同的TSR程序。并且通过把AX

    设置为某个特殊代码(5453h或ASCII中的TS)来调用中断2Fh便可访问这些TesSeRact

    功能。

      但这种用法与已公开的Int 2Fh标准用法不相符,在采用标准用法时,DOS规定:标

    识代码必须在AH寄存器中(并在80h-FFh范围内),AL=0表示该中断用于已“安装

    否?”的功能。

      在公开TesSeRact的正式用法之前,这支开发队伍已开发出了TesSeRact的标准,并

    且初始拷贝的用途太广泛了,以致不允许对这样一种基本特征作出改变。不相容性也不会

    造成任何问题,因为目前尚不知道哪个功能当前正使用54h代码(即使有程序在使用,那

么它还同时拥有53h功能的机会几乎没有)。

      还值得一提的是,自从版本3.3引入了APPEND之后,DOS就开始不遵循它自己的

    规则;它使用了B7h代码,而这个代码的正式身份是作为非DOS应用程序的保留代码。

        为了实现减少不同来源的TSR之间彼此产生的冲突这一原始目标,这支开发队伍还

    鼓励所有开发者在各自的代码中支持TesSeRact标准。具体做法是通过开发一个用于Int

    2Fh的处理程序,以便支持用户参数块和本附录将通过特殊的TS标识代码来介绍的两

    种功能。

812页

                      C.1用户参数块

    与TesSeRact兼容的要求之一是必须支持UserParms数据区。该区域的描述如下(这

一区域必须处在用于Int 2Fh的TSR处理程序的开头):

        New_2F:    Jmp 0verParms         ; Int 2F vector points here

        UserParms db 8 dup l(' ')       ; 8-byte Program ID string

        IdNum      dw 0                  ; TSR identification number

        FuncFlag dd 0ffffffffh           ;  supported function bit  map

        HotKey     db 0                  ;  scan code of hot key to use

        ShiftSt    db 0                  ; shift state to use for popup

        HotFlag    db 0                 ;which hot key iS in use

        ExtCnt     db0                  ; number of extmhot keys

        ExtHot     dd  0                ; pointer to extra hot keys

        Status     dw 0                  ;  TSR Status flags

        OurPSP     dw 0                  ; ourPSP segment

        ourDTA     dd 0                  ;  our  DTA region

        DSeg       dw 0                  ; user's  default data Segment

    注意,这里仅仅只是列举该数据区结构的一部分;而没有列举由TesSeRact库保持并

使用的元素。

    FuncFlag是一个位映象的4字节变量,显示着TSR所支持的所有多路复用功能。每

当调用这种功能时,必须通过BX把其功能号传送给处理程序,而不是像标准情况下通过

AL来传送,其原因我们曾解释过。该变量的映象如下:

        位 0      功能00h(检查安装—必需功能)

        位1       功能01h(返回用户参数—必需功能)

        位2       功能02h(检查热键)

        位3       功能03h(置换INT24h)

        位4       功能04N(返回数据指针)

        位5       功能05h(设置附加热键)

        位6-7    未定义—留待将来使用

        位8       功能10h(允许TSR)

        位9       功能11h(禁止TSR)

        位10      功能12h(从RAM中释放TSR)

        位11      功能13h(重新启动TSR)

        位12      功能14h(获取当前状态)

        位13      功能15h(设置TSR状态)

        位14      功能16h(获取弹出式打印)

        位15      未定义 —留待将来使用

        位16      功能20h(调用用户进程)

        位17      功能21h(填充键盘缓冲区)

        位18- 31  未定义—留待将来使用

 

813页

      如果TSR支持所用的功能,那么必须把对应的位置为1,否则必须将其置为0,使用

TesSeRact库例库的程序在返回时会把FuneFlag置为FFFFFFFFh。其它的TSR则必须

把未定义的变量设置为0,以便同它们自己的变量区别开来。

                    C.2功能00h(检查安装)

      检查安装(功能00h)可确定系统是否安装了某个程序。该功能可通过以下方式来调

用:

          mov        ax , 5453h            ; TS code

          mov        si , offset IDStr     ; see below

        mov          ds,seg IDStr

          xor        cx ,cx                ; handle counter

          xor       bx,bX                   ;  function 0000

        int          2Fh

      IDStr是一个8字节数据区,它保存着一个独一无二的TSR标识符串。 Int 2Fh例程

必须把传送给它的字符串(如下例所示)与它自己的8字节字符串进行比较。如果这两个

字符串相符合,TSR在返回时就必须把CX设置为它自己的TSR句柄,并把AX寄存器

设置为0FFFFFh。

      如果标识字符串与传送的字符串不匹配,那么TSR应恢复所有寄存器,增加一个cx

寄存器,并继续沿着程序链往下传送中断。在使用该功能时如果在链接到下一个TSR之

前,系统中每个TesSeRact兼容的TSR都增加了一个CX寄存器,而在此时,中断进程又

实际上返回到调用者这边,那么在这种时候,CX寄存器要么为被找到的TSR的句柄,或

者在没有找到与IDStr相匹配的TSR时为下一个可用的句柄。

      如果没有能找到匹配,在返回时AL就不会等于FFh;这样,TSR安装程序就可把

CX的内容用作句柄,以通过它来进行自我标识,并将它保存在参数块的IdNum字中。

    下面的代码是根据TesSeRact库的Int 2Fh处理程序编辑而成的,它显示出了处理程

序必须做哪些事情才能证明两个程序是完全相同的:

            overparms:

                    cmp      ax,5453h                         ;ax=5453h for TesSeRact

                    jne        not_our_2F    ; some other multiplex function

                    push       dS                                  ; Save for next handler

                    push      CS

                    pop       ds                 ; set DS while here

                    push    ax

                    push      bx

              or   bx, bx                  ; do check for install first,

              jnz  test_for_1             ;tny other function test

        ;following is the CHECK INSTALL code

        ;DS:SI points to ID string

        ;CX iS current number in chain

            push CX

            push Si                        ;  Save SI for next one

            lea    di,UserParms            ;the program copy of IDStr

 

814页

                push  CS

                pop     es

                mov      cx,8                          ;test for match

                rep    cmpsb

                pop     Si

                pop     cx

                jnz      next_one                     ;no match, not us

                pop      bx                             ;matched, empty stack

                pop     ax

                mov     cX,es:[di]                ;return IdNum in cx

                xor    ax,ax

                 dec     ax      ;AX=-1  means already her

                jmp      shor done_2F

           next_one                                    ; try next higher ID code :

                Inc     CX

                 pop    bx              ;restore for next to use

                pop      ax

                pop     ds

          not_our_2f:           ;chain to next 2F handler

                jmp   dword ptr[oldint2F]           ; via saved pointer to it

          done_2F:                                    ; return tO caller

                pop      ds

                iret

              C.3功能01h(返回用户参数指针)

      若要支持TesSeRact标准,至少还得需要的一种功能便是功能01h,它必须返回一个

指向用户参数块区域的远指针。该功能的调用方法如下:

          mov        ax,  5453h

          mov       bX,01h               ; function number

          mov        cx,TsrIdNum          ; identmcation number

          int       2Fh

      如果CX中的标识号与TSR的ID号(由功能00h返回的)相符合,则该功能在返回

时必须让ES:指向用户参数(UserParms)区,并让AX等于0。下面的代码段列举了这样

做的一种方法:

          cest_for_1:

          cmp      cx,IdNum                     ;if not Function 00h

          jne      not_our_2F                 ;the program copy

          push     cs                ;got it, set up for return

          pop     es

          lea     bx,UserParms

          xor      ax,  ax                     ;success status code

          pop     ds

          jmp done_2F

 

815页

                  C.4其它TesSeRact功能

      完整的TesSeRact文档对其它TesSeRact功能进行详细的介绍,这种文档可从

TesSeRact开发队伍中获取或通过从BBS中卸载下来,以及可从专用于TesSeRact库的

联机服务中获得。如果希望得到一份TesSeRact的Int 2Fh处理程序的源代码,用户可按

下面的地址寄上一封信,并在信封上注明自己的地址:

      TesSeRact Development Team

        1657 The Fairwavs, Suite 101

        Jenkintown,PA 19046

      若想了解更为详细的信息,读者可按照CompuServe 7073120或MCIMAIL 315-5415

(TESSERACT)这两个地址与TesSeRact Development Team取得联系。

816页

附录D 保留的DOS功能

      本书的DOS参考手册一章已经详细地介绍了与Int 21h相对应的所有虚拟功能;这

些功能中包括那些被正式标记为“保留的”且是大多数参考手册中所没有公开的功能。其

余各参考手册章节介绍了一些标记为保留的或未公开的功能。但是,由于现有的编程体系

保持了高度的编程连续性,因此,不可能保证在此讲到每一个已知的功能。

      不仅如此,本书介绍保留功能的材料都来源于非正式的途径。在许多情况下,这些介

绍来源于DOS代码的反汇编部分和对它可能实现的内容进行分析的结果。鉴于此,这些

描述有可能不是百分之百的准确,尽管作者已尽了最大的努力以便为读者提供最好的可

用信息。

      这些功能可从总体上分成四个组,我们将在本附录中对它们分别进行介绍。介绍完成

这四个功能组之后,我们还将为读者介绍一对程序,这对程序可使用最令人感兴趣的保留

功能之一,以提供在其它情况下不能获得的信息。

      这些功能之所以被“保留”,其中一个最主要的原因是留下余地以便供设计者们能在

不同的版本中,按照任何方式来改变它们。这种情况在每个新的DOs版本中都不同程度

地出现过。这类现在不仅有可能,而且在用到这些未公开的功能时,往往成为现实;但是,

当围绕着它们去设计一道程序时,往往意味着将承担极大的风险。值得欣慰的是,随着这

些未公开的功能被越来越多地投入使用,它们在市场上也受到了越来越多人的欢迎,并且

Microsoft十分乐意将它们的目的和用途变得大众化。

                D.1未公开的DOS功能的种类

        现将四种未公开的DOS功能列举如下:

        ·有用的功能,其中包括诸如SetPID和GetDPB之类的事情

        ·未使用的功能,它们往往无功而返

        ·用于挂接“将来”功能的功能,它们可能曾经被实现过或未被实现过

        ·其特征尚未得到确定的功能

        每一个DOS版本都拥有各自未公开的功能。例如,DOS版1中只有1种未公开的功

能。而到了DOS版本2,这个数字至少上升到了9,并且在DOS版本4出台前后,这个数

字已发展到超过了50。一种功能所适合的范围很大程度上与取决于编程者是谁。

 

817页

                      D.2覆盖范围

      在市场上大量发行的书籍都十分详细地介绍了未公开的DOS功能。如果读者是一位

在访问DOS功能方面持严谨态度的程序员,那么就应该添置这类书刊(参见附录E提出

的建议)。

      《DOS程序员参考手册》第4版介绍了大量未公开的DOS功能。它们分别出现在本

书的各个主要部分和DOS参考手册一章里。表D.1列出了本书所介绍的这些未公开的

DOS功能。但本附录并不是要介绍所有这些功能,相反,该附录将着重介绍其中一些用户

极有兴趣的,甚至是发现它极其有用的功能。

                    表D.1《DOS程序员参考手册》中介绍的未公开的功能

Int        Func        Sub      名    称                            版    本

21         37        00h      获取切换字符                        版本2或更高

21         37        01h      获取切换字符                        版本2或更高

21         37        02h      读取设备可用性                      版本2或版本4.0

21         37        03h      设置设备可用性                      版本2

21         52                 获取磁盘列表                        版本2或更高

21         53                 把BPB转换成DPB                      版本2或更高

21        55                  创建PSP                             版本2或更高

21         5D        00h      把数据保存到DOS保存区               版本3或更高

21         5D        06h      获取关键出错标志地址                版本3或更高

21         5E        01h      设置机器名                          版本3.1或更高

21         60                 扩展路径名字符串                    版本3或更高

21         64                 设置当前国家字节                    版本3或更高

21         6A                 分配内存                            版本4或更高

29                            快速放置字符                        版本2或更高

2A                             Microsoft网络接口                  版本3或更高

2E                            主外围程序装入程序                  版本3或更高

2F         05                 获取外围关键出错处理程序安装状态    版本3或更高

2F         08                 获取DRIVER.SYS安装状态            版本3或更高

2F         12        00h      获取DOS安装状态                     版本3或更高

2F         12        01h      清除文件                            版本3或更高

2F         12        02h      获取中断向量地址                    版本3或更高

2F         12        03h      获取DOS数据段                       版本3或更高

2F         12        04h      常规化路径分隔符                    版本3或更高

2F         12        05h      输出字符                            版本3或更高

2F         12        06h      调用关键出错                        版本3或更高

2F         12        07h      移动磁盘缓冲区                      版本3

2F         12        08h      减少用户计数                        版本3或更高

2F         12        0Ch      供DOS使用的IOCTL打开                版本3或更高

2F         12        0Dh      获取关闭文件的数据和时间            版本3或更高

818页

Int        Func    Sub      名    称                        版    本

2F         12      0Eh      搜索缓冲区链                    版本3

2F         12      10h      寻找已修改的缓冲区              版本3

2F         12      10h      时间拖延                        版本4或更高

2F         12      11h      常规化ASCIIZ文件名              版本3或更高

2F         12      12h      检查ASCIIZ字符串长度            版本3或更高

2F         12      13h      字体和国家转换                  版本3或更高

2F         12      14h      比较32位的数字                  版本3或更高

2F         12      16h      获取DCB地址                     版本3或更高

2F         12      17h      获取LDT地址                     版本3或更高

2F         12      18h      获取用户堆栈地址                版本3或更高

2F         12      19h      设置LDT指针                     版本3或更高

2F         12      1Ah      从路径名中获取驱动器代码        版本3或更高

2F         12      18h      闰年调整                        版本3或更高

2F         12      1Ch     计算从月头开始的天数            版本3或更高

2F         12      1Dh      计算日期                        版本3或更高

2F         12      1Eh      比较字符串                      版本3或更高

2F         12      1Fh      初始化LDT                     版本3或更高

2F         12      20h      获取DCB号                       版本3或更高

2F         12      21h      扩展ASCIIZ路径名                版本3或更高

2F         12      22h      转换扩展出错代码                版本3或更高

2F         12      24h      执行延迟                        版本3或更高

2F         12      25h      获取ASCIIZ字符串长度            版本3或更高

2F         12      26h      打开文件                        版本4或更高

2F         12      27h      关闭文件                        版本4或更高

2F         12      28h      定位文件指针                    版本4或更高

2F         12      29h      读取文件                        版本4或更高

2F         12      2Bh     IOCTL接口                       版本4或更高

2F         12      2Dh      获取扩展出错代码                版本4或更高

2F         12      2Fh      保存DX                          版本4或更高

2F         15              CD-ROM接口                      版本3或更高

                D.3使用功能52h—表中表

      随着DOS版本3的问世,以及网络支持的应用,DOS发现它有必要标准化系统配置

信息,以便网络操作所求的全部新增加的任选功能都能获取各自所需的信息。Dr. Edwin-

Floyd(Microsoft和IBM之外最早发现这个标准的存在和用途者之一)将这一结果称为配

置变量表(CVD,并且慢漫地变成了众所周知的表中表(List of Lists)。该表中的大多数

在版本2中就已经存在了,并且在版本3中得到了巨大的扩展,并且它在RAM中的位置

    也有了轻微的变动。

 

819页

      表中表位于MSDOS.SYS程序的前端。该表含有指向内存控制块(MCB)链的指针,

和其它必需的控制信息,以及现有的或允许的驱动器数。

D.3.1内容和布局

      在DOS版本2中,CTV只有25个字节长。而在版本3和版本4中,它占有42个字

节。在所有这三种版本中,CVT紧紧挨在NUL。设备驱动程序——总是程序链中的第一个

驱动程序的前面。(可安装的驱动程序适合于放在NUL驱动程序和后续驱动程序之间的

区域,也就是IO.SYS文件部分)。

      要想定位CVT,可使用未公开的Int 21h功能52h。当在不设置任何参数的情况下调

用此功能时,它会通过ES:BX返回一个指向DOS所维持的第一个驱动器参数块的地

址。在版本2中,该项成了CVT中的第2个驱动器参数块的地址(在它之前的是一个2字

节的值,即内存控制块链链头的段地址)。在版本3或版本4中,这一地址变成了8个字

节,因为在MCB段字的前面加进了一个指向当前缓冲控制块的远指针和一个用于当前

缓冲区位置的16位偏移值。

      因此,在版本2中,必须把该功能返回的BX值减去2,并且在版本3和版本4中把这

个值减去8,才可达到CVT的前端。

      既然已掌握了怎样访问CVT,不妨来看看它究竟保存着一些什么样的内容。

      版本2的VCT

      下列列举的配置变量表布局显示了该表在DOS版本2中是怎样首次出现的。星号表

明所在的地址是未公开的Int 21h,功能52h返回的地址,并且表中列出的字节偏移值都

是相对于这一地址而言的。

偏移值字节        字段长度              含    义

-02h                 字                第一个内存控制块的地址

*00h                双字              指向第一个驱动器参数块的指针

04h                 双字              指向第一个DCB(系统文件表设备控制块)的指针

08h                 双字              指向CLOCK$设备驱动程序的指针

0Ch                 双字              指向CON设备驱动程序的指针

10h                 字节              逻辑驱动程序器数

11h                 字                在任意块设备上每扇区最多的字节数

13h                 双字              指向磁盘缓冲区链链头的指针

17h                                    NUL设备驱动程序头;设备驱动程序链中的第一个设备

偏移值-02h处的字所指定的内存控制块的格式比较简单,现列举如下:

偏移值字节        字段长度              含    义

00h               字节            MCB标识符;M表示除最后一个外的每一个MCB,Z代表

                                  最后一个内存控制块。总是位于段内的偏移值0000h处

820页

偏移值字节          字段长度              含    义

01h                 字              拥有该MCB的进程的PSP地址,或为0000h以表明没有

                                    在内存控制块中指定这种内存。

03h                 字              以节为单位的后继内存块大小,其中不包括这一16字节

                                    的MCB区域。

04h                 字节            余下未使用的节

      由CVT中偏移值00h处的22字节所指定的驱动器参数块是本书的参考手册部分所

    介绍的与未公开的中断21h,功能52h相关联的结构。它在版本2与版本3之间保持了原

    样。由于参考手册部分已全面介绍了驱动器参数块,这里就不再重复了。在系统中的每个

驱动器(包括软盘系统中的驱动器B)都有各自的DPB;并且紧挨着最后一个DPB的块指

针含有FFFF:FFFFh以标志链路的结束。

      系统中的DCB数目是通过CONFIG.SYS中的FILES=行来建立的。如果没有指定

FILES=值,则缺省数目为5。 DCBs是以“链接”方式组合起来的,每条链路前面都有一个

    3字节链路头:

偏移值字节          字段长度              含    义

00h                 双字            指向下一个链路头的远指针,或为FFFF:FFFFh,表示此

                                    处为链中的最后一条链路

04h                 字              链路中的块数

在CVT中,偏移值04h处的双字指向含有DCB链中第一个设备控制块的链路头部。在

DOS版本2中,这种40字节的DCB布局与已公开的FCB结构略有不同:

偏移值字节        字段长度              含    义

00h             字节                DCB的当前用户数

01h             字节                打开的DCB所处在的模式

02h             字节                目录项中的属性字节,或设备的00h

03h             字节                驱动器代码(1=A,以及等等)

04h              8字节              文件或设备名

0Ch              3字节              文件扩展名,或空白

0Fh              13字节             没有破解;可能与用于文件的FCB相同

1Ch             双字                指向用于设备的设备驱动程序的远指针;而对于文件来

                                    说,这仍然是个谜

20h              8字节              未能破解

    偏移值11h处的字指示出了在任何块设备上最大的扇区大小。它是在安装了块设备

 

821页

驱动程序后进行加电初始化期间被设置的,并且它建立了配置本章创建的缓冲区的大小。

这一进程能确保每个缓冲区有足够大的空间以保存系统中现有的最大扇区,而且大小正

好够用。

      在CVT中,偏移值13h处的双字所指向磁盘缓冲区链分布如下(而用于版本2中的

十分细小的缓冲区组织至今仍未能有人译解得开):

偏移值字节          字段长度              含    义

00h                 双字            指向下一个缓冲区的远指针,或为FFFF:FFFFh以指示

                                    链的末端

04h                 4字             控制信息没有被全部译成代码,包括标志字节、逻辑扇区

                                    号和驱动器代码

0Ch                 双字            指向与缓冲区相关的DPB的远指针

10h                 未知            缓冲区自己,通常为512字节,但实际大小是通过保存在

                                    CVT中偏移值11h处的值设置的。

版本3的CVT

      在DOS版本3中,配置变量表分别向两端进行了延伸,如下所示。如同在版本2中一

样,带星号处为未公开的中断21h,功能52h返回的地址,表中所有字节偏移值都是相对

于这一地址而言的。

偏移值字节        字段长度              含    义

-08h               双字              在BUFFERS=链中的当前缓冲区

-04h               字                当前缓冲区内的偏移值

-02h               字                第一个内存控制块的段

* 00h               双字              指向第一个驱动器参数块的指针

04h                 双字              指向第一个DCB(系统文件表设备控制块)的指针

08h                 双字              指向CLOCK$设备驱动程序的指针

0Ch                 双字              指向CON设备驱动程序的指针

10h                 字                在任何块设备上每扇区的最多字节数

12h                 双字              指向磁盘缓冲区链开头的指针

16h                 双字              指向逻辑驱动器表的指针

1Ah                 双字              指向DOS的FCB链开头的指针

1Eh                 字                在交换时应保存的FCB数

20h                 字节              块设备数

21h               字节                逻辑驱动器数,由CONFIG.SYS中的LASTDRIVE值设

                                      置(如果不指定,系统会自动缺省为5)

22h                                    NUL设备驱动程序的开头;设备驱动程序链中的第一个

                                      设备

    位于偏移值-08处的双字所指的是磁盘缓冲区链中的当前缓冲区;缓冲区控制块的

布局容以后再述。偏移值-04处的字是当前缓冲区内相对于缓冲区中第一个字节的字节

 

822页

偏移值;值0000h表示已经用到了该缓冲区的最后一个字节,并且应该访问链中的下一个

缓冲区了。

      与在版本2中一样,在这里,偏移值-02处的字是MCB链中第一个内存控制块的段

地址。并且,实际内存控制块的布局也与在版本2中的布局相同。此外,DPB链(其第一项

为偏移值00h处的双字节指定)也与版本2的相同。

      版本3的驱动器控制块在版本2的基础上进行扩展,以便适应联网和多进程共享相

同文件或设备的使用。但是,同版本2中一样,驱动器控制块仍然被收集到链路中,并且每

条链路都带了一个链路头,而且链路头的布局也没变。每个DCB的新的结构布局如下:

偏移值字节        字段长度              含  义

00h                 字              该DCB的用户数

02h                 字              每个打开DCB的访问模式

04h                 字              磁盘属性字

05h                 字节            设备属性

06h                 字节            第2个设备属性字

07h                 双字            指向设备驱动程序的远指针

0Bh                 字              第一个簇号

0Dh                 字              文件时间字

0Fh                 字              文件日期字

11h                 双字            总文件大小

15h                 双字              当前字节位置

19h                 字              总簇数计数

1Bh                 字              当前簇号

1Dh                 字                目录扇区

1Fh                 字节              目录项索引(在扇区内)

20h                  8字节          设备或文件名

28h                  3字节          文件扩展名或空白

2Bh                字                未知

2Dh                 字              未知

2Fh                 字              未知

31h                 字              所有者的PSP段地址

33h                 字              未知

      偏移值10h处的字指示了任何块设备上最大的扇区大小。该大小是在安装了块设备

驱动程序之后进行加电初始化期间被设置的。它可用来建立在配置期间创建的缓冲区的

大小,以确保每个缓冲区能有足够大的空间来保存系统中现有的最大扇区,并且又不留更

多的余地。

      位于偏移值12h的双字指向磁盘缓冲区器链的开头。在磁盘缓冲区链中,每个缓冲区

的大小为10h的字所指定的值(通常为512个字节),加上在该数据区前面的16个字节的

链首。其布局如下:

 

823页

偏移值字节        字段长度            含    义

00h             双字          指向下一个缓冲区的远指针,或为FFFF:FFFFh以表示

                              到了链的末端

04h             字节          逻辑驱动器代码

05h             字节          动作码

06h             字            逻辑扇区号

08h             字节          FAT数或01

09h             字节          每FAT的扇区数,或00

0Ah             双字          指向与该缓冲区相关的DPB的远指针

0Eh             字            未用

10h             不固定        缓冲区自己,通常为512字节,但其实际大小是通过保存

                              在CVT中的偏移值10h处的值来设置的

    在版本2中,当前目录曾是DPB的一部分,而自版本3开始它就变成了一个独立的

表,即逻辑驱动器表。在CVT中,位于偏移量16h处的双字指向LDT,这个LDT保存着

一个用于每个系统逻辑驱动器的项,直到设置在CONFIG.SYS文件的LASTDRIVE中

的值为止。从驱动器A开始,最小的项数在缺省时为5(A:至E:)。在版本3中,每个设置

驱动器表为81个字节,它们在内存中彼此首尾相连。每个表的布局如下:

偏移值字节        字段长度              含    义

00h                  2字节        实际驱动器标志符和:

02h                  65字节       为ASCIIZ字符串的驱动器当前路径(包括根目录斜线和

                                  用于终止00h字节的空间)

43h                 字            驱动器的当前状态(位图):

                                  8000h=未知,可以表示远程网络驱动器

                                  4000h=可以使用

                                  2000h=未知

                                  1000h=SUBST单元

45h                 双字          指向用于驱动器的DPB的指针

49h                 字            当前目录的第一个簇

4Bh                字            未知

40h                 字            未知

4Fh                 字            在报告目录时要跳过的字节数;0002表示普通驱动器,更

                                  大的值表示为被替代的单元

      位于偏移值1Ah处的双字以及尾随其单字都与CONFIG.SYS中的FCBs=行相关。

它们分别是一个指向系统FCB链的远指针和在请求交换时应保护它们以防止交换的

FCB数。虽然当初设计FCB的目的主要是供网络使用,但程序也常常将它们用在单用户

环境中,系统FCB采用了与DCB相同的布局,并且,像DCB一样,它们是通过链接方式

 

824页

    组织起来的,每条链路中含有多个文件控制块。

      在版本3里CVT中的最后两项(位于偏移值20h和21h)分别是块设备数和逻辑驱

    动器数。第一项是根据安装块设备时系统所遇到的总单元之数而建立的,第二项则是通过

    CONFIG.SYS中的LASTDRIVE=行来设置的。

      版本4的CVT

        同版本2和版本3之间的差别相比,在版本3和版本4之间,对CVT及其相应的各

    个表所进行的改变显得有点微不足道。但是,在EMS支持方面版本4确实对CVT区域

    动了些手术,其中主要的有把16位的逻辑扇区号变成了32位的号。此外,版本4还重写

    了缓冲区算法,并因此对缓冲区结构作出较大幅度的调整。下表列出的就是在版本4中使

    用的CVT,唯一的重大改变是位于偏移值12h处的旧缓冲区链首指针变成了一个指向新

    的EMS链接记录的指针。

偏移值字节          字段长度            含    义

     -08h             双字          在BUFFERS=链中的当前缓冲区

     -04h             字              当前缓冲区内的偏移值

     -02h             字            第一个内存控制块的段

    *00h              双字          指向第一个驱动器参数块的指针

    04h               双字          指向第一个DCB(系统文件表设备控制块)的指针

    08h             双字            指向CLOCK$设备驱动程序的指针

    0Ch               双字          指向CON设备驱动程序的指针

    10h               字            在任意块设备上每扇区的最多字节数

    12h             双字            指向通往DOS缓冲区链的EMS链接记录的指针(版本3

                                    和版本4之间的唯一变化)

    16h               双字          指向逻辑驱动器表(其布局见下面的讨论,与版本3略有

                                      不同)的指针

    1Ah             双字            指向DOS的FCB链首的指针

    1Eh               字            在交换时应保存的FCB数

    20h               字节          块设备数

    21h               字节          逻辑驱动器数,由CONFIG.SYS中的LASTDRIVE值设

                                    置(如果不指定,系统会自动缺省为5)

    22h                              NUL设备驱动程序的开头;设备驱动程序链中的第一个

                                    设备

      在版本4中,低于中断21h,功能52h返回的地址的继续保存未变,但是,由偏移值-

08h处的双字指定的缓冲区控制块却有很大的改变。在版本4之前,每个缓冲区都有其自

己独一无二的段地址,并且远指针链只沿着朝前的方向链接缓冲区。而在版本4中,通过

单EMS连接块(下面将要介绍)所能接触的缓冲区在同一段内,并且,是通过在末端链中

的近指针将它们双向地链接起来的(即向前和向后)。

      为了适应新的缓冲算法,版本4已将缓冲区控制块大小从16个字节扩展到了20个

字节。其结构如下:

 

825页

偏移位字节        字段长度              含    义

00h               字              链中前一个缓冲区的偏移值,是段内或EMS物理页内的

                                  偏移值

02h               字              链中下一个缓冲区的偏移值,是段内或EMS物理页内的

                                  偏移值

04h               字节            逻辑驱动器代码(同版本3一样)

05h               字节            动作代码(不一定与版本3相同)

06h               双字            逻辑扇区号,是从版本3中扩展而来的

0Ah               字节            FAT数,或为01;完整的含义尚不清楚

0Bh                字              如果FAT在缓冲区内则为每FAT的扇区数;其它情况下

                                  含义不明

0Dh               双字            一远指针,指向与所在缓冲区相关的物理驱动器

11h               字              含义不明

13h               字              含义不明

14h                512字节        缓冲区自己;同在版本3中一样,大小是通过CVT中的字

                                  设置的,但通过常情况下为512字节

      为了加速缓冲区搜索,版本4已将一种全新的连接记录加给了缓冲区运算。这种11

字节记录保存着一种散列值,并指向相关的BCB。其详细情况目前尚未完全弄清楚,但已

弄清楚了它的结构,其结构如下:

偏移值字节        字段长度              含    义

00h               字                散列值

02h               双字              指向相关BCB的远指针

06h               字节              应用计数器

07h               双字              含义不明

    在版本4中,为适应新的保存缓冲区功能而增加的第二个新记录是在EMS而不是常

规内存中。该记录通过一种连接记录而把一个EMM句柄和物理页联系在一起。由于系统

软件和非IBM的EMS硬件之间存在兼容性问题,这样便不可能在EMS是活动的时候去

仔细检查系统是如何使用这种记录的;下面介绍的情况是针对非EMS环境的:

偏移值字节        字段长度              含    义

00h                 双字            指向前面介绍的连接记录的远指针

04h                 字              通过连接记录控制的页数

06h                 双字            含义不明

0Ah                 字              含义不明

0Ch                 字节            标志;当不在使用EMS时,值为FF

0Dh                 字              EMS句柄值

0Eh                 字节            EMS物理页号

826页

      在版本4中,还有一个遭到改变的区域就是DPB结构,通过CVT中偏移值00h处的

指针即可达到这一结构。在驱动器参数块中,唯一的改变是“每FAT的扇区数”由8位变

成了16位,所增加的8位是由于增加了一个用于随后各项的偏移值字节造成的。

      在版本4中,介于DPB指针之上一直到偏移值12h之间的各项保持未变。不过,在偏

移值12h处的一个远指针已变成了一个指向用于磁盘缓冲区的EMS记录的指针,这一

点我们已经在介绍BCB的改变时顺便提到过。

      此外,通过CVT中的偏移值16h的远指针可以达到的LDT也被扩展了7个字节。至

于这7个字节的用途目前尚未得到确定。新的LDT结构如下:

偏移值字节          字段长度              含    义

00h                 2字节           实际驱动器标志符和:

02h                  65字节         为ASCIIZ字符串的驱动器当前路径(包括根目录斜线和

                                    用于结尾00h字节的空间)

43h                 字              驱动器的当前状态(位图):

                                    8000h=未知

                                    4000h=可以使用

                                    2000h=未知

                                    1000h=被替代的单元

45h                 双字            指向用于驱动器的DPB的指针

49h                 字              当前目录的第一个簇

48h                 字              未知

4Dh                 字              未知

4Fh                 字              在报告目录时要跳过的字节数;0002表示普通驱动器,若

                                    是替代的单元则为更大的值

51h                 字节            未知

52h                 字              未知

54h                 字              未知

56h                 字              未知

      CVT的余下内容与版3相同,这一点读者可通过反汇编和进行测试来证实。

D.3.2 CVT3.PAS一个用于版本3的程序

      伴随程序(CVT3.PAS)能起到两方面的作用,一方面作为一个实例,可让读者了解未

公开的Int 21h,功能52h实际使用;另一方面,它可作为一种工具来探索清楚在版本3中

运行的系统是怎样布置CVT的。该程序如列表0.1所示:

    列表0.1

{cvt3.pas       Turbo Pascal V5.0 version for DOS 3.x

    *       Copyright 1987, 1988,  1989 Jim Kyle All Rights Reserved

    *       The program, and the information it contains, may be freelY

    *       distributed and uSed as long as this entire comment section

    *       is not altered.

 

827页

}

PROGRAM CVT3;

{$A-, B-, D+, E-, F-, I+, L+, N+, O-, R-, S+, V- }

{$m 8192,0,0 }

USES DOS;

TYPE

bcb = RECORD { Buffer Control Block format }

nxcb : pointer; { +00 next one in chain }

ldrv : byte; { +04 logical drive code }

action: byte; { +05 action code }

lsect : word; { +06 logical Sector # }

nf : byte; { +08 nbr FATs or 01 }

secf : byte; { +09 sectors/FAT or 00 }

pdry : pointer; { +0A phys dry tbl ptr }

fill : integer; { +0E unknown }

buf : array[0..511] of byte; { +10 the buffer itself }

END ;

bcbptr =^bcb ;

mcb = RECORD { Mem Alloc Block header format }

flag : char; { +00 must be M or Z }

owner : word; { +01 PSP seg or 0000 }

siz : word; { +03 Number paragraphs }

END ;

mcbptr = ^mcb ;

dpb = RECORD { Drive Parameter Block format }

drvc : byte; { +00 drive code }

dunit : byte;   { +01 unit number }

bps : integer; { +02 bytes per sector }

spc : byte; { +04 sec per cluster -1 }

pwr2 : byte; { +05 power of 2 }

rsrvs : integer; { +06 Reserved sectors }

nfats : byte; { +08 number of FATs }

dirsiz : word;  { +09 root dir size }

fus : word; { +0B first usable sectr }

tcc : word; { +0D total clstr ct +1 }

spf : byte; { +0F sec per FAT }

fds : word; { +10 first dir Sector }

drvr : pointer; { +12 driver pointer }

mcode : byte; { +16 media code }

accflg : byte; { +17 access flag }

nxt : pointer; { +18 next table ptr }

lastused : wordi; { +1C last used cluster }

filler : word; { +1E usually FFFF }

END ;

dpbptr = ^dpb ;

chn = RECORD { Chain links for DCB, FCB chains }

nxtlnk : pointer; { +00 next link or FFFF }

nmbr : integer; { +04 number blocks here }

END ;

Chnptr = ^chn ;

dcb = RECORD { Device Control Block format }

nusers : integer; { +00 users for this DCB }

mode : integer; { +02 0,1,2 per OPEN }

datrb :byte; { +04 disk attrib byte }

dvatr : byte; { +05 device attrib this }

atrb2 : byte; { +06 2nd device attrib }

pdrvr : pointer; { +07 points to driver }

frstc : word; { +0B ,first cluSter nbr }

828页

modtm : word; { +0D file time word }

moddt : word; { +0F file date word }

totsiz : longint; { +11 total file size }

curpos : longint; { +15 current byte pos }

clsctr : word; { +19 total cluster ctr }

curcls : word; { +1B current cluster }

dirsec : word; { +1D directory sector }

dirndx : byte; { +1F dir entry index 0..}

name : array[0..7] of char; { +20 dev/file name }

ext : array[0..3] of char; { +28 file extension }

fill2 : word; { +26 unknown }

fill3 : word; { +20 unknown }

fill4 : word; { +2F unknown }

owner : word; { +31 PSP of owner proc }

fill5 : word; { +33 unknown }

END ;

dcbptr = ^ dcb ;

ldt = RECORD { Logical Drive Table format }

name   : array[0..67] of char;{ +00 drive and path }

code : byte; { +44 drive in use code }

mydpb : dpbptr; { +45 DPB for this drive }

dirclu : word; { +49 directory cluster }

filler2: word; { +48 FFFF }

filler3: word, { +40 FFFF }

patlen : word; { +4F SUBST path length }

END ;

ldtptr= ^ldt ;

cvt = RECORD { Configuration Variable Table }

curbfr : bcbptr; { current buffer pointer }

memchn : mcbptr; { start of MCS chain }

pdrvs : dpbptr; { Fn $52 points to here }

dcbchn : dcbptr; { set up by FILES= }

clkdev : pointer; { set by DEVICE= (clock$)}

condey : pointer; { set by DEVICE= (con) )

secsiz : integer; { maximum block size }

bfrchn : bcbptr; { set up by BUFFERS= }

ldrvs : ldtptr; { set up by LASTDRIVE= }

fcbchn : Chnptr; { set up by FCBS= }

filler : integer; { number of FCBs to keep }

npdrvs : byte; { set by driver list }

nldrvs : byte; { set by LASTDRIVE= }

END ;

Cvtptr = ^cvt ;

dtstr = string[8]; {date-time strings }

pstrg = string[9]; { pointer-conversion fmt }

memst = string[2]; { memory usage string }

VAR

cvtbase : cvtptr;

curbuf : bcbptr;

Cunmcb : mcbptr;

curdpb : dpbptr;

curchn : chnptr;

curdcb

curfcb : dcbptr;

curldt : ldtptr;

bcbctr ,

dcbctr : integer ; { counters }

 

829页

b : Registers;

PawsFlag: Boolean, { controls screen-full pausing }

lctr : integer; { counts lines displayed }

function hexnlb:byte) : char; { converts nibble to char }

begin

b := b and 15;  { force to only 4 bits }

if b > 9 then inc(b,7);  { adjust for hex digits }

hexn := chr(b+48); { convert to character }

end ;

function hexb(b:byte) : string;

begin

hexb := hexn(b shr 4) + hexn(b); { assemble the nibbles }

end ;

function hexw(w:word) : string;

begin

hexw := hexb(w shr 8) + hexb(w); { assemble the bytes }

end ;

function hexl(l: longint) : string;

begin

hexl := hexw(l shr 16) + hexw(l); { assemble the words }

end ;

PROCEDURE holdup;  { count lines and wait if fUll }

BEGIN

IF PawsFlag THEN

BEGIN

inc ( lct r ) ;

if lctr > 23 then

BEGIN

lctr := 0;

readln ;

END

END

END ;

FUNCTION xp( p : pointer ) : pstrg; { displays pointer P }

BEGIN

xp := hexwlseg(p^)) + ':'  + hexw(ofs(p^)) ;

END ;

PROCEDURE dmplf : pointer); { display hex dump of data to CRT }

VAR

x : ^byte;

i : integer;

c : char;

BEGIN

x : = f ;

write( xp(f), '>' ) ;

FOR i:=0 to 15 DO

BEGIN

write( hexb(x^) ) ;

if i=7 then write( '-' )

else write ( ' ' ) ;

x := pointer(longint(x) + 1);

END ;

write ( ' ' ) ;

x : = f ;

FOR i:=0 to 15 DO

BEGIN

830页

c := char($7f AND x^);

if c< ''then c : = '.';

write( c );

if i=7 then write( ' ' ) ;

x := pointer(longint(x) + 1 );

END ;

writeln ;

holdup ;

END ;

PROCEDURE dpbtrc(a: pointer) ; { trace and report DPB data }

VAR

ofsv : word;

PROCEDURE dpbrpt; { reports each DPB's content }

BEGIN

writeln;

holdup ;

write( 'Drive', char (curdpb^ .drvr+ord('A') ) ) ;

write(': (unit ' , curdpb^.dunit, of driver at ' , xp(curdpb^.drvr) ) ;

writeln( ' ) media code =', hexb(curdpb^ .mcode) ) ;

holdup ;

write( ' ' , curdpb^ .bps:3,'bytes per sector, ) ;

write( ' ',curdpb^ .spc+1 :2,'sectors per cluster,') ;

writeln(' ', curdpb^ .tcc-1 :4, , total cluster count') ;

holdup ;

write( ' Res sectors: ' , curdpb^ .rsrvs,' ') ;

writet(' ',curdpb^ .nfats, ' FAT' ' s, ',curdpb^ .spf :2, ' sec ea ' ) ;

write( ' FAT entry : ' ) ;

IF (curdpb^.tcc) > $0FFC

THEN write( 16 )

ELSE write( 12 );

writeln('bits Root: ' , curdpb^ .dirsiz:3, ' entries');

holdup;

write(' First root sector: ' , curdpb^.fds:3 );

write(' First data sector: ' , curdpb^.fus:3 );

writeln( ' Last cluster used : ' ,  hexw(curdpb^ . lastused) ) ;

holdup ;

END; { of dpbrpt proc }

BEGIN

curdpb := a;

ofsv := 0;

writeln ;

holdup ;

writeln( 'DRIVE PARWETER BLOCK (DPB) DATA- -') ;

hOldup ;

WHILE (ofsv <> $FFFF) DO

BEGIN

ofsv := word(longint ( curdpb^ . nxt ) ) ;

dpbrpt ;

curdpb : = dpbptr(curdpb^ .nxt) ;

END ;

write ( #12 ) ;

END; { of dpbtrc proc }

PROCEDURE bcbtrc(a : pointer) ;

VAR

ofsv : word;

PROCEDURE bcbppt(a : bcbptr);

VAR

i : integer;

 

831页

x : pointer;

BEGIN

writeln ;

holdup ;

inc ( bcbctr ) ;

writeln( 'Buffer Control Block ' , bcbctr:2, ' at ' , xp(a) ) ;

holdup ;

write ( ' Logical ' ' ' , char ( ord ('A ' ) +a^ . ldrv) ) ;

write( ' :'' , Sector ' , hexw(a^ . lsect) ) ;

writeln( ' Action code : ' , hexb (a^ . action ) ) ;

holdup ;

write( ' NFATS:', hexb( a^ .nf) ) ;

write( ' SPF: ' , hexb(a^ . secf ) ) ;

write( ' DPB: ' , xp(a^ .pdrv) ) ;

writeln( ' FILL: ' , hexw(a^ .fill) ) ;

holdup ;

x:= addr(bcbptr(a) ^ .buf[O] ) ;

FOR i:=0 to 31 Do

dmp (pointer ( longint ( x ) + ( i SHL 4) ) ) ;

END ; { of bcbrpt proc }

BEGIN { bcbtrc routine }

bcbctr := 0;

ofsv := 0;

WHILE (ofsv <> $FFFF) DO

BEGIN

ofsv := word(longint( bcbptr(a)^ .nxcb ) ) ;

bcbrpt (a);

a := bcbptr(a) ^ .nxcb;

END ;

wnite (#1 2 ) ;

END; { bcbtrc routine }

PROCEDURE dcbtrc(t : dtstr; a : pointer);

VAR

ofsv : word;

FUNCTION f_tm(n : word) : dtstr;

VAR

buf : dtstr;

b : byte;

BEGIN

b := ((n SHR 11) AND 31);

buf[1] :=char((b DIV 10) + 48) ;

buf[2] :=char((b MOD 10) + 48);

buf[3] := ' : ' ;

b := ((n SHR 5) AND 63);

buf[4] :=char((b DIV 10) + 48);

buf[S] :=char((b MOD 10) + 48);

buf[6] :=': ';

b := ((n SHL 1) AND 63);

buf[7] :=char((b DIV 10) + 48);

buf[8] :=char((b MOD 10) + 48);

f_tm := buf;

END ;

FUNCTION t_dt(n : word) : dtstr;

VAR

buf : dtstr;

b : byte;

BEGIN

832页

b :=((n SHR 5) AND 15);

buf[1] :=char((b DIV 10) + 48);

buf[2] :=char((b MOD 10) + 48);

buf [3] : = '1';

b := ( n AND 31);

buf[4] :=char((b DIV 10) + 48);

buf[5] :=char((b MOD 10) + 48);

buf[6] := '/';

b:=((n SHR 9) AND 15) +80;

buf[7] :=char((b DIV 10) + 48);

buf[8] :=char((b MOD 10) + 48);

f_dt := buf;

END ;

PROCEDURE dcbnpt( var t : dtstr; n : integer );

type

acctyp = array[0..3] of string[7] ;

const

actyp : acctyp = ( ' READ' , 'WRITE ' , ' R/W' , ' unknown ' ) ;

var

isdvc : Boolean;

BEGIN

WHILE (n > 0) DO

BEGIN

INC (dcbCtr) ;

writeln ;

holdup ;

wnite (t, '',dcbctr:2 );

IF (curdcb^ . name[0] = #0) THEN

BEGIN

writeln( ' at ' , xp(curdcb) , ' not used since bootup' );

holdup ;

END

else

BEGIN

isdvc := (curdcb^.dvatc and 128) <> 0;

write( ' for ' ) ;

IF isdvc

THEN write('device ' )

ELSE write( 'file ' );

write ( curdcb^ . name [ 0 ] , curdcb^ . name [ 1 ] , curdcb^ . name [ 2 ] ) ;

write ( curdcb^ . name [ 3] , curdcb^ . name [ 4 ] , curdcb^ . name [ 5 ]) ;

write ( curdcb^ . name [ 6 ] , curdcb^ . name [ 7 ] );

IF (NOT isdvc) THEN { block driver }

write( ' . ' , curdcb^ .ext[0] , curdcb^ .ext[ 1 ] , curdcb^ .ext[2] ) ;

write( ' at ' , xp( curdcb ) );

write( ' shows ' , curdcb^ .nusers) ;

writeln( ' OPENs') ;

holdup ;

write( ' opened for', actyp[3 AND (curdcb^.mode)] ) ;

write( ' access' ) ;

IF ($FFFC AND (curdcb^ .mode) )<>0 THEN

write( ' ( ' , hexw(curdcb^ .mode) , ' ) ' ) ;

writeln('by process ' , hexw(curdcb^ .owner) ) ;

holdup ;

IF( isdvc ) THEN { Device }

BEGIN

write( ' Device driver at', xp(curdcb^ .pdrvr) ) ;

write( ' is in ' ) ;

if ( (curdcb^ .dvatr) AND 32)<>0 THEN write( ' Raw' )

ELSE write( 'Cooked ' ) ;

write('mode and is ' ) ;

if ( (curdcb^ .dvatr) AND 64)=0 THEN write( ' not ' ) ;

 

833页

writeln ('ready');

holdup ;

END

else { File }

BEGIN

write(' File is on drive ' , char(ord( 'A' )+( (curdcb^ .dvatr) AND 31 ) ) ) ;

write(': (driver at ' , xp(curdcb^ .pdrvr) ) ;

write(' ) and has ' ) ;

if ( (curdcb^ .dvatr) AND 64)<>0 THEN write( ' not ' ) :

writeln( ' been written to. ' ) ;

holdup ;

writeln( ' File ' ' s attribute byte = ' , hexb(curdcb^ .datrb) ) ;

holdup ;

END ;

write (' Mod Time/date:');

write (f_tm(curdcb^.modtm) , ' , ' ) ;

writeln ( f_dt ( curdcb^ . moddt ) ) ;

holdup ;

write ('Dir Sector: ' , hexw(curdcb^.dirsec) , ' ' ) ;

writeln( ' Dir index : ' , curdcb^ .dirndx :4, ' ' ) ;

holdup ;

write ( ' First Cluster: ' , hexw(curdcb^ .frstc) , ' ' );

write ( ' Prev Clusters: ' , curdcb^ .clsctr:4, ' ' ) ;

writeln('Current Cluster : ',hexw(curdcb^ . curcls) , ' ') ;

holdup ;

write ( ' Directory size: ' , curdcb^ .totsiz:6, ' ' ) ;

writeln( ' Curr byte count : ' , curdcb^ .curpos :6 ) ;

holdup ;

write( ' Fill2= ' , hexw(curdcb^ . fill2) , '') ;

write ( ' Fill3=', hexw(curdcb^.fill3) , ' ' ) ;

write ( ' Fill4=' , hexw(Curdcb^.fill4) , ' ' ) ;

writeln( ' Fills= ' , hexw(curdcb^ .fill5) ) ;

holdup ;

END ;

curdcb := pointer(longint(curdcb) + sizeof(dcb) - 1 );

DEC( n );

END;  { n >= 0 loop }

END; { of dcbrpt }

BEGIN

curchn := chnptr(a) ;

dcbctr := 0;

ofsv := 0;

WHILE (ofsv <> $FFFF) DO

BEGIN

ofsv : = word ( longint (curchn^ . nxtlnk ) );

curdcb : = dcbptr ( longint (curchn) +sizeof (chn ) ) ;

writeln ;

holdup ;

write ( 'Link at , xp(curchn),' contains ' );

writeln( curchn^ . nmbr, ' ' , t,'s--' ) ;

holdup ;

dcbrpt (t, curchn^ .nmbr) ;

curchn := chnptr(curchn^ .nxtlnk) ;

END ;

Write (#12) ;

END ;

PROCEDURE memtrc(a : pointer) ;

VAR

z : longint;

PROCEDURE memrpt ( s , o , a : word) ;

 

834页

FUNCTION memu(a : word) : memst ; { determine memory use }

var

x : char;

BEGIN

x := char( mem[a:0] );

CASE X OF

#$CD :

memu : =  ' Program' ;

'A' . . 'Z' :

memu := ' Environment ' ;

else

memu :=' Data ';

End ;

END ;

BEGIN

z := longint(s) SHL 4;

write( z:6, ' bytes ' );

IF (o<>0) THEN

writeln('USED by proc ' , hexw(o) , ' , at ' , hexw( a ) , ' :0000, for ' , memu(a) )

else

writeln( 'FREE at ' , hexw( a ) , ' :0000' ) ;

holdup ;

END; { of memrpt }

BEGIN

curmcb :=  mcbptr(a);

writeln ;

holdup ;

writeln( 'MEMORY ALLOCATION CHAIN ' ) ;

holdup ;

WHILE (curmcb^ .flag = 'M' ) DO

BEGIN

memrpt (curmcb^ . siz , curmcb^ .owner, SEG(curmcb^ )+1 ) ;

curmcb := ptr( seg(curmcb^) + (cunmcb^.siz + 1), 0 );

END ;

IF (curmcb^ .flag <> 'Z' ) THEN

BEGIN

writeln(#13, #10, 'MEMORY ALLOCATION ERROR at ' , xp(curmcb) ) ;

halt (255 ) ;

END ;

memrpt ( curmcb^ . siz , curmcb^ .owner , SEG(curmcb^ )+1 ) ;

write ( #12 ) ;

END; { of memtpc )

PROCEDURE ldttrc( a: ldtptr; n: byte );

PROCEDURE ldtppt( l: ldtptr; d: byte );

VAR

ldrive : char;

i : integer;

BEGIN

ldrive := chr( $41 + d );

if (1^.code AND byte($40) )=0 then

writeln( 'Logical Drive ' , ldrive, ' not yet defined' )

else

begin

write ( 'Logical Drive ' , ldrive );

writeln( ' = Physical drive ' , l^.name[0] ) ;

holdup ;

write ( 'The current (full) pathspec is: ' );

i : = 0 ;

repeat

write ( l^.name[i] );

inc( i );

 

835页

until (l^ . name[i]= #0) ;

writeln ;

end ;

holdup ;

if (l^ . code = $50) then

writeln( 'Code = 0*50 - - result of SUSST command ' )

else if(l^ .code = $40) then

writeln( 'Code = 0*40 - - physical (or aliased) device' )

else

writeln ( ' Code =0x ' , hexb( l^ .code) , ' - - unknown ' ) ;

holdup ;

writeln( 'Directory Cluster = ' , hexw( l^ .dirclu ) ) ;

holdup ;

writeln( 'Path Length to ignore = ' , hexw( l^.patlen ) ) ;

holdup ;

writeln ;

holdup ;

END; { of ldtcpt }

VAR

o : byte;

BEGIN

curldt := a;

writeln ;

holdup;

writeln( ' LOGICAL DRIVE TABLES (Set by LASTDRIVE=, SUBST, etc. ) : ' ) ;

holdup ;

dec( n ) ; { convert for zero-based reference }

for o := 0 to n do { loop through continuous tables }

begin

ldtrpt (curldt , o) ;

curldt := ptr(seg(curldt^) , ( ofs(curldt^) + sizeof(ldt) ) ) ;

end ;

write ( #1 2 ) ;

END; { Of ldttpc }

{ main }

SEGIN

b.ah := $30, { Check for correct DOS version }

MsDos ( b ) ;

if b.al <> 3 then { If not verSion 3.x, get right out }

begin

writeln( 'Wrong DOS version: ' , b.al,'.', b.ah );

halt(255) ; { return ErrorLevel=255 }

end ;

PawsFlag := ParamCount = 0; { else set up for paging output }

lctr := 0;

writeln( 'Configuration Variables, DOS version ' , b.al, ' .', b.ah ) ;

holdup ;

b.ah := $52; { Get CVT pointer set up }

msdos (b) ; { (using undocumented function ) }

cvtbase := ptr(b.es, b.bx-8) ; { hold pointer to CVT }

writeln ;

holdup ;

writeln( 'CVT is located at ' , xp(cvtbase) ) ;

holdup ;

write ( 'No. of Phys Drives (at', xp(@cvtbase^.npdrvs)) ;

writeln ( ' ) : ' , cvtbase^ . npdrvs) ;

holdup ;

write ( 'No. of Log. Drives (at ' , xp(@cvtbase^.nldrvs) ) ;

writeln( ' ) : ' , cvtbase^ .nldrvs) ;

hOldup ;

write ( ' Clock Device (ptr at', xp(@cvtbase^ .clkdev)) ;

836页

writeln ('):', xp(cvtbase^ . clkdev ) ) ;

holdup ;

write ('CON Device (ptr at', xp(@cvtbase^.condev) ) ;

writeln( ' ) : ' , xp(cvtbase^ . condev) ) ;

holdup ;

write (' Sector Size(?) (at', xp(@cvtbase^.secsiz)) ;

writeln ( ' ) : ' , hexw( cvtbase^ . secsiz) ) ;

holdup ;

write (' FCBs to keep (at ' , xp(@cvtbase^.filler));

writeln ( ' ) : ' , hexw(cvtbase^ . filler) ) ;

holdup ;

write ( '1. Memory Chain (ptr at ' , xp(@cvtbase^.memchn)) ;

writeln ( , ) : ' , xp(cvtbase^ . memchn ) ) ;

holdup ;

write ( '2. DCB Chain (ptr at ' , xp(@cvtbase^.dcbchn)) ;

writeln(') : ' , xp(cvtbase^ . dcbchn) ) ;

holdup ;

write ( '3. DPB Chain (ptr at', xp(@cvtbase^.pdrvs)) ;

writeln ( ' ) : ' , xp (cvtbase^ . pdrvs ) ) ;

holdup ;

write ( '4. FCB Chain (ptr at', xp(@cvtbase^.fcbchn) );

writeln ( ' ) :', xp( cvtbase^ . fcbchn) );

holdup ;

write ( '5. LDT Chain (ptr at , xp(@cvtbase^.ldrvs) ) ;

writeln( ' ) : ' , xp(cvtbase^ . ldrvs) ) ;

holdup ;

write ('6. Current Buffer (ptr at', xp(@cvtbase^.ourbfr));

writeln ( ' ) : ' , xp (cvtbase^ . curbfr ) ) ;

holdup ;

write ( '7. Buffer Chain (ptr at ' , xp(@cvtbase^.bfrchn));

writeln ( ' ) :', xp( cvtbase^ . bfrchn) ) ;

holdup ;

writeln ;

holdup ;

writeln ('TRACING MCB Chain=== ) ;

holdup ;

memtrc ( cvtbase ^ . memchn ) ;

writeln ;

holdup ;

writeln ('TRACING DCB Chain===');

holdup ;

dcbtrc( ' DCB' , cvtbase^ .dcbchn) ;

writeln ;

holdup ;

writeln ('TRACING DPB Chain=== ) ;

holdup ;

dpbtrc ( cvtbase ^ . pdrvs ) ;

writeln ;

holdup ;

writeln ( ' TRACING FCB Chain===' ) ;

holdup ;

dcbtrc ( ' FCB', cvtbase^ . fcbchn ) ;

writeln ;

holdup ;

writeln (' TRACING   LDT Chain===');

holdup ;

ldttrc ( cvtbase^ . ldrvs , cvtbase^ . nldrvs ) ;

writeln ;

holdup ;

 

(已经到附录了!未完。)

转载于:https://www.cnblogs.com/Chaobs/p/3838563.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值