现在的位置: 首页 > 综合 > 正文

DOS程序员参考手册[2]

2012年04月28日 ⁄ 综合 ⁄ 共 26564字 ⁄ 字号 评论关闭

12页
  第2章DOS系统结构
    DOS结构涉及硬件之上的整个机器。它不只是操作系统,并且包括整个计算机。如果
想要对使用什么功能或怎样使用它们作出最好的决定,就必须了解DOS的结构。
                    2.1“虚机”概念
    认识DOS的一个有用的方法是,将它看成是分布在子系统中的一种体系结构。该体
系中每层都提供了一个完整地定义的服务程序集合,以使更高一层可以使用它。因此,每
个层次都成了一个虚拟的机器,它便构成下一个更高层次的计算机。图2.1说明了这个关
于DOS系统的概念。
                            图2.1虚拟机器的层次结构
    物理的机器或硬件,是该体系的最底层。系统之间的很多区别就在于这一层。
    围绕着机器,常见的主要组成包括以下几个部分:
      ·来自Intel 8086家族的处理器:8086、8088、80186、80286、80386和80486
      ·在系统中相似的物理设备映象(换句话说,相似的指定中断和地址)。
      ·一个有限数量的总线设计。

13页
DOS的一个主要目的就是隐藏各机器之间的差异,以便在编程和用户层都以标准的
方法来使用计算机提供的各种性能。DOS成功地在各种IBM兼容计算机所选择的操作系
统上实现了一致。
                    2.2物理机器
    机器之间最大的差异就在硬件层,在这个层次一般会发现其“兼容性”是否真的兼容。
当有重大的硬件差异时,在这个层次操作的程序就不能工作了。
    物理的计算机系统(见图2.2)可以分为几个主要部分:
      ·中央处理器(CPU),完成计算机系统的操作。
      ·ROM和RAM,保留程序和数据。
      ·输入通道,为计算机输送信息。
      ·输出通道,将信息送给用户。
      ·存储设备(软盘和硬盘),临时地或永久地保留数据。
                                图2.2基本计算机的框图
    理解计算机系统的所有这些部分,对成功地开发出高质量的软件是很有必要的,特别
是使用DOS和BIOS尤为重要。下面将讨论这些部分。
                      2.3处理器
    在PC或兼容机上使用的中央处理器(CPU)是Intel公司8086系列处理器芯片的成
员。在使用的计算机中经常看到8086、8088、80186、80286、80386或80486芯片。Intel新
近已经发布的芯片,主要版本有80386sx、80386DX、80486SX、80486DX、80486DX2等。
在Intel系列中的每个芯片,不仅有区别于已有芯片的特有功能,而且也和早期版本保持
了兼容性。例如,80386(SX或DX)就可以完成80286或8088可以完成的所有工作,并加
上了它自己特有的功能。
    本书不详细研究芯片之间的特殊差异,但要知道DOS的主要版本是基于8086和
8088芯片的能力而设计的。在讨论DOS、BIOS和编程时,所有例子都是运行在8086或
8088上的(没有包括新芯片扩充的特有性能)。在本书中,所有的引用都是针对8086的,
但都适用于整个intel处理器系列。对DOS的一些新的附加和扩充,需要不同CPU芯片

14页
知识,我们在例子中将清楚地注明所需知识的类型。
    CPU是完成最简单操作的基本处理器。因为必须了解一些这个基本处理器的知识,
所以这节提供了一个8086家族处理器的概述。如果读者已熟悉这个题目,可以跳过此节。
如果要详细了解8086家族的编程,请看本书最后的参考书目。
    在本节的后面,将讨论作为一个程序员可以存取的CPU寄存器。然而,因为内存寻址
是在DOS层完成很多程序操作的基础,所以首先必须了解8086怎样对内存寻址。让我们
先看以下部分的内容。
2.3.1 8086内存寻址
    一些程序员批评8086的分段内存寻址方式。内存分段限制着数据项的大小,并且指
针结构也很复杂。然而,分段式内存对于DOS程序员来说至今仍还存在。它对解决8086
的固有设计问题是一个明智的方法,也是用8086的16位寄存器来表示乡8086的20位地
址值的最好的查找方式。 8086有20根地址线,它允许在一个内存区域内有2的20次方(即
1048576或1M)字节的寻址能力,但它的寄存器只有16位宽(寄存器的使用将在本章后
面“8086寄存器集”一节中讨论)。
    解决这个问题的方法就是将整个内存地址分成可以在16位寄存器中被独立存储的
“片”。因此,需要用两个寄存器来表示一个地址:一个寄存器存储基地址(或称作段地址),
另一个存储相对于基地址的偏移量。该方法理论上可以寻址2的32次方(大于40亿字节)的连续
地址。但要实现这个寻址区间,微处理器需要32条地址线,因此它大大地超过了8086的
能力。下面我们用例子说明该寻址区域是非常有用的。
    图2.3示出了包含100000000h(4294967296)或2的32次方个单元的4千兆内存空间区域。每
一行是一个区或段(segment),包含10000h(65,536或2的16次方)个单元。在选定的每个段内的
地址时,可以用相对于该段开始单元的偏移量表示,第一个单元的偏移量为0。书写时,采
用段:偏移量(segment : offset)的形式来表示地址,而且各地址值均采用十六进制形式。
    第一段的最后一个字节(位于0000: FFFFh)后面,紧跟的是下一段的第一个字节
(位于(0001 : 0000h)。每个内存单元的绝对地址——即它的本来位置,应从内存区的第
一个字节算起。它的计算公式如下:
                  实际地址=(段地址*段间隔)+偏移量
    图2.3显示了这一计算过程。当段间隔等于10000h(64K)时,段号便形成了8位绝对
地址的最高4位值。类似地,偏移地址则可以当作绝对地址的最低4位值。
    实际上,基地址和绝对地址之间的关系并不像图2.3所显示的那样简单。采用了先进
技术的硬件设备可以快速地处理地址转换,以取代人们从段和偏移量计算出绝对地址的
工作。
    尽管通过这个例子对理解是有帮助的,但它还留下了一个疑问:8086使用的是20位
(而非32位)地址。因此,这个例子必须修改成实际的工作方式。Intel开发的寻址方式是
将段寄存器的内容当成是整个地址的高16位,低4位指定为零。换句话说,段寄存器包含
了20位绝对地址的高4位16进制数,并且最低位(最右边一位)为零。再加上要计算的地

15页
                      围2.3间隔值为10000h字节的各内存段
                          (图中所有数字都为十六进制,除了后缀为“d” 的外,它表示该数为十进制。)
址偏移量寄存器中的地址值,就可得到所要的绝对地址了。图2.4显示了Intel寻址方式
中怎样从段—偏移量地址得到绝对地址。
                              图2.4如何计算一个绝对地址
      现在,我们已有了基于8086内存寻址概念,下面让我们再来讨论8086的寄存器集。
      8086用段。偏移量来寻址内存会导致一个反常现象;实际使用中的绝对地址可以以
多个组合方式来寻址。例如,下面所有的段。偏移量对表示的地址都对应的是同一个绝对
内存地址。
               0101:FFF0                   1000:1000
                03F1:D0F0                    1001:0FF0
               0900:8000                    1002:0FE0
                0CB7:4490                    1003:0FD0
               0FFF:1010                 1100:0000

16页
  所有这些分段式的地址都对应于同一个绝对地址:011000h。注意,每增加或减少此
地址的一个段位置,会对应地增加或减少偏移量中的10h位置。正如所看到的那样,内存
段可以用很多方式来覆盖。
2.3.2 8086寄存器集
      8086系列使用了14个独立的16位可组合的寄存器,按用途分组,可分为四类:
        ·通用寄存器
        ·段寄存器
        ·偏移量寄存器
        ·标志寄存器
      表2.1列出了各个寄存器和它们的分类。
                                    表2.1 8086寄存器集
寄存器        类别      用途
AX              通用
BX              通用
CX              通用
DX              通用
CS              段          代码段
DS              段          数据段
ES              段          附加段
SS              段          堆栈段
SP              偏移量      堆栈指针
BP              偏移量      基地址指针
SI              偏移量      源索引地址
DI              偏移量      目的索引地址
IP              偏移量      指令指针
Flags           标志        状态标志
      当面对各个寄存器时,你就明白了在硬件层是如何直接对CPU进行操作的。要注意
的是,这些操作尽管都由汇编语言来完成,但像BASIC、C和Pascal这样的高级语言也有
自己的方法来调用这些寄存器。(有关这方面的技术将在第4章“DOS和BIOS接口”中讨
论)。
      正如上面所提到的,8086寄存器集可以按照使用目的,分成四类,让我们对此分别介
绍。
      通用寄存器
      通用寄存器,正如其名字所提示的,用于存储最新结果或其它临时需要的通用目的。
当使用DOS或BIOS功能时,就需要用所需的值装入这些寄存器来完成各种功能。总要
在某个寄存器中包含一个值来对应指定的功能,并按所需附加一些其它参数。当从DOS
或BIOS功能返回时,程序中要使用的返回值也包含在寄存器中。
      通用寄存器是AX、BX、CX和DX。为了方便地使用8位或16位值,每个16位的寄存
器可以作为一对8位寄存器来寻址。寄存器命名为AL、AH、BL、BH等,分别用来寻址低
8位或高8位(L和H分别指示低和高)。图2.5表示了各个寄存器之间的关系。
      这些寄存器的使用非常广泛。无论是使用汇编语言,还是使用高级语言,只要调用访
问DOS或BIOS的例程,都常用到它们。

17页
                  图2.5 16位的寄存器可以当作一对8位寄存器来寻址
        段寄存器
      段寄存器在8086的内存寻址方式中起着很重要的作用。它存储了16位代表64K内
存段的基地址的值。读者可能回忆起来:这些值对应于20位基地址的高16位;低4位被
指定为零。 8086的内存寻址硬件将这些基地址和存储在CPU偏移量寄存器中的值进行
组合,得到实际应访问的地址。
      下面列出了所使用的各个段寄存器:
      ·CS(代码段)寄存器
      ·DS(数据段)寄存器
      ·ES(扩充段)寄存器
        ·SS(堆栈段)寄存器
      每个段寄存器指示不同的段。作为程序员,可以用所选的任何方法在一定范围内使用
这些段寄存器。在第3章“动态的DOS” 中,读者将看到怎样编程以及怎样使用段寄存器。
段寄存器是为用于以下工作场合而设计的:
      · CS保存包含正在运行程序代码段的基地址。
      · DS保存包含程序数据段的基地址。
      · ES是对DS寄存器的补充,用于保存“扩充”段的基地址,经常用于数据。
      ·SS保存程序堆栈的基地址,用来临时存放数据。
      前面提到的使用段寄存器的限制包括对使用CS和SS寄存器的限制。为了便于操
作,8086期望CS寄存器永远指向正在运行程序的代码段,同样SS寄存器永远指向当前
的堆栈段(对8086操作是必须的)。
      堆栈
      8086系列的处理器用一个名叫堆栈的结构来跟踪函数调用和其它操作中产生的信
息。每当一个子程序被调用时,处理器将各寄存器推入堆栈(PUSH操作),当从子程序返
回时,又将它们弹出(POP操作)。每次PUSH应将堆栈指针指向前一个低地址;POP则恢
复这个“移动的”指针。这些在SP上的操作是86芯片系列内置的操作,并且不能被改变;
事实上,正如编程所希望的,SP总是被初始化为指向堆栈存储空间的栈顶而不是栈底。
      程序员使用堆栈来存放计算的中间结果,或者向子程序传送参数值。各种编程语言

18页
  同样的目的而广泛地使用了堆栈。
      堆栈的工作很像自助餐馆的盘子堆,当一个项目加入到(PUSH进)堆上时,堆会变
大。当东西拿走时(POP出),最后一个加入堆的项目被第一个弹出。这个结构被称为是后
进先出(LIFO)结构。
      偏移量寄存器
      偏移量寄存器,正如其名字所表示的那样,一般用来作为内存地址的偏移量部分。地
址的段部分一般存在段寄存器中。
      因为地址被分成段寄存器和偏移量寄存器两部分,所以每个偏移量寄存器被隐含地
和指定的包含地址“其它”部分的段寄存器配对。这种配对是自动的,除非用特定的命令取
消这种默认的配对。
      在以下列表中,给出了5个偏移量寄存器和隐含的段寄存器之间的配对关系:
      ·SP(堆栈指针)寄存器(和SS配对)
      ·BN(基础指针)寄存器(和SS配对)
      ·SI(源索引)寄存器(和DS配对)
      ·DI(目的索引)寄存器(和DS配对)
      ·IP(指令指针)寄存器(和CS配对)
      根据这组寄存器在一般情况下所起的作用,可以将它们分成两类:指针寄存器和索引
寄存器。
      指针寄存器
      指针寄存器提供了一个在段中读取数值的常规方法。 SP永远指向当前堆栈的顶部,
并且自动地被各种汇编语言指令修改。其它指针寄存器,特别是BP,常在索引操作中用来
作为基本的(或参考)指针。例如,一些程序用BP指向堆栈中的一个固定位置。这个位置
以后可作为恢复子程序调用前放在堆栈中的变量的参考指针。在高级语言编译器中,BP
寄存器的使用便具备了存取参数的标准含意。
      指令指针(IP)保留下一条将被CPU执行的指令的地址偏移量。当IP和代码段(CS)
寄存器结合时,它们指向指令的绝对地址(CS : IP寄存器对永远用于这个用途)。IP的值
在每个指令从当前的代码段取出后,由CPU自动地增加。
      索引寄存器
     索引寄存器SI和DI,是特定的偏移量寄存器。特别是当SI和DI与DS和ES段寄存-
器合用时。例如,在字符串操作时,将使用DS:SI指向源串的地址,ES:DI指向目的串。
在非串操作中,程序员通常用SI和DI作为源操作数和目的数据的索引(偏移量),正象其
名字表示的那样。
      标志寄存器
      8086标志寄存器使用16位中的9位作为标志,表示处理器的状态或控制处理器的
操作方式。这些标志被分为两类:状态标志和控制标志。列出如下:

19页
        状态标志:
        ·CF(进位标志)
        ·PF(奇偶标志)
        ·AF(辅助进位标志)
        ·ZF(零标志)
        .OF(溢出标志)
          ·SF(符号标志)
        这些标志报告最后一个被运行的指令的状态。例如,如果最后一条指令产生的值是
    零,则零标志就被设置。状态标志的设置和清除是自动的,但程序也可以设置和清除标志。
    很多DOS和BIOS程序就使用进位标志来指示错误。
        控制标志是:
        ·DF(方向标志)
        ·TF(跟踪标志)
        ·IF(中断标志)
        方向标志控制着8086的指令在内存拷贝的区域内指定方向。跟踪标志将CPU置成
    “单步”方式(调试器用来控制程序的执行)。中断标志允许或禁止硬件中断响应。
    2.3.3 80286及其更高档的处理器
      从80286开始,使打破由8088/8086分段式结构设置的1M内存的限制成为可能。
    CPU可以在实地址方式下运行,即运行与8086和8088的能力一样的程序。程序员可以
    在实地址方式下编程,也可以在保护模式下编程。
      在保护模式下,建立了一个描述符表。这些表包括以前段寄存器信息——段的基地
    址。同时加上一些信息,如,是否可以被写入这个段的信息。段寄器则是现在的段选择符,
    它是描述符表的索引。
        在80286保护模式中,一个描述符表项包含有24位基地址。当80286在保护模式下
    运行时,它可以存取多达16M的内存。
        80386和80486继续扩充了内存寻址能力。像80286一样,它们可以在保护模式下编
    程;然而,现在的描述表项有32位基地址,它允许寻址多达40亿字节(46字节)的内存。
    为适应这个寻址能力的跳跃,通用、偏移量和标志寄存器现在也有了32位版本:EAX、
    EBX、ECX、EDX、ESP、EBP、ESI、EIP和EFLAGS。老的16位寄存器(例如AX和BX)仍
    然存在,只是作为32位寄存器的低16位。
        不仅CPU可以存取4G字节的内存,一个段也可以扩充到全部4G内存中。事实上现
    在32位结构可以和16位结构一样容易处理,在DOS环境中的80386-/80486- 特定软件
    已经形成了市场,其中包括两个相互竞争的保护模式环境。 DOS保护模式接口(DPMI)和
    虚拟控制程序接口(VCPI)。
        另外,还有一个DOS扩充程序,该程序允许专门针对80386-/80486的软件,在允许
    存取实地址模式下DOS和BIOS功能的同时,在保护模式下进行操作。 DOS扩充程序允

20页
    许应用程序在使用CPU的32位扩充能力的同时,仍能使用DOS和BIOS提供的服务。这
类程序常常比用等同的16位并且对DOS内存没有强制限制开发出的程序运行得要快。
2.3.4 CPU芯片的识别
    要使用80286、80386和80486 CPU的扩充功能,软件必须知道它运行在其中一个芯
片上,并且要知道在什么芯片上运行。有三种解决确定当前芯片问题的方法。第一种解决
方法是基于80386和80486在加电时用DH寄存器的10(标志)字节(3或4)来区分,它是
什么芯片。第二种方法是询问用户,他使用的是哪种芯片。第三种方法是从已知的芯片之
间的差异来推断出所使用的芯片是哪一种。
    第一种方法必须包含有已重编程的BIOS芯片,它超出了大多数程序员的能力,对用
户而言则更是苛刻。它也不能区分80286到8086之间的芯片。第二种方法假设用户知道
其机器是什么CPU;在很多情况下,这种假设是无效的。第三种方法需要做的工作比第二
种多,但比第一种少,并且是可靠的。
    列表2.1中的编码演示了怎样确定当前的CPU。它首先测试8088、8086和80286及
其之上芯片的不同之处。在8088中,一个值被推进堆栈后,堆栈指针在写入堆栈之前减
少。从80286开始,则是先写值,然后堆栈指针再减少。通过压入堆栈指针,可以检查写入
堆栈的值,来确定堆栈指针是在值写入之前还是在之后减少。如果要确定当前使用的是
80286、80386或80486,可以尝试设置80286没有使用的标志寄存器位、80286不允许使
用这些位,但80386和80486却允许。如果可以改变这些位的值,则是80386或80486。同
样的方法也可用来区别80386和80486。注意,使用66h大小的覆盖前缀去强制32位标
志寄存器被压入和弹出。这个方法是完全安全的,因为在这时,已经知道它至少是个
80386芯片。
    列表2.1
page 6o,132
;checkcpu.asm
; Determines whether the CPU in use is an 8088/8086, an 80286,  an
;80386, or an 80486.Print the CPU and return an errorlevel Of 0,
;2, 3,or4  for 8088/8086, 80286,80386,or 80486, respectively.
           .model small
            .Stack
            . data
say86      db        "8088 or 8086$"
say286 db              " 80286$"
say386 db              "80386$"
say486 db              "80486$"
            .code
            .startup
checkcpu proc
; The first step is to determine whether the chip is an 8088/8086.
;The key difference is based-on what the CPU does when it executes
;the PUSH instruction.The 8088/8086 decrements the stack
21页
; pointer first and then writes the saved value to the stack. The
; 80286, 80386, and 80486 write the value to the stack and then
; decrement the stack pointer. Thus, when SP is pushed and the
; pushed value is popped off, the value popped off equals the
; current stack pointer, unless the chip is an 8088 or 8086.
push   sp
pop ax
cmp ax,sp  ; if values are not the same,
jne is_86 , it is 8088/8086
; The second step is to detecmine whether the chip is an 80286.
; The key diffecence is the IOPL bits in the flags cegister;
; the 80386 and 80486 have them, and the 80286 does not. The
; 80286 does not let them be Set; the 80386 and 80486 do.
pushf
pop ax ; get flags in ax .
or ax,03000h ; set IOPL bits
push ax  ; stuff them back
popf , pop flags--this is where the 80286
; will put them back the way they were
pushf
pop ax ; get flags in ax
test ax,03000h ; if the IOPL bits are reset, the chip
jz iS_286 ; is an 80286
; The third Step is to determine Whether the chip iS an 80386.
; The key difference iS the alignment check bit in the flags
; register; the 80486 has one, and the 80386 does not. The 80386
; does not let you set that bit, but the 80486 does.
db 66h ; (32 bit instruction)
pushf
pop ax ; read low word of flags
and ax,00FFFh ; clear IOPL bits- -level zero
pop dx , read high word
or dx,00004h ; set alignment check bit
push dx ; push flags back
push ax
db 66h ; (32-bit instruction)
popf ; pop flags register- -this is where
; the 80386 undoes your work
db 66h ; (32-bit instruction)
pushf ; push flags back
pop ax ; read what you did
pop dx ; find out if the CPU reset the
test dx,4 ; alignment check bit
jz iS_386 ; if it did, the chip iS an 80386
is_486:
mov   dx,offset say486
mov al,4 ; errorlevel 4
jmp sayso
is_386:
mov dx, offset say386
mov al,3 ; errorlevel 3
jmp sayso
iS_286:
mov dx,offset say286
mov al,2 , errorlevel 2
22页
                      jmp     saySo
              is_86:
                  mov        dx ,offset say86
            mov        al,0           ;  errorlevel 0
              sayso:
                          push      ax        ;save errorlevel
                  mov        ah,9          ;call DOS wPite string function
                          int        21h
                          pop         ax                        ;retrieve  errorlevel
                    mov      ah , 04Ch         ;  terminate process with return code
                        int         21h
              checkcpu endp
                          end
2.3.5数学协处理器
      Intel 80x86系列的处理器,从8088到80386只能处理整数运算。对很多应用程序,有
整数运算就已足够。对于需要浮点运算的应用计算必须由已编好的特定的程序来处理。对
大多数应用程序来说,用户不需留意软件计算处理的开销。然而,对于浮点运算较多的数
学应用,开销变成了一个问题,这时的数学协处理器也变成必不可少的了;一些应用系统
甚至没有协处理器就不能运行。
      数学协处理器可以像处理器计算整数那样容易地计算浮点数。不仅如此,它还能和处
理器并行地处理所进行的计算工作。只有当数据被调入协处理器或从协处理器中读出数
据时,或者激活协处理器期间,才会需要处理器的配合,而在协处理器完成其功能期间,处
理器可以去做另外的属于它自己的工作。
2.3.6数学协处理器的识别
      Intel公司共有三种可以和主处理器一起工作的协处理器:8087、80287和80387,但
没有80187。因为8087也可以和80186和80188一起工作。也没有80487,因为在80486
内有内置的80387的等价物。要识别数学协处理器并不简单。表面上不匹配的处理器和
协处理器可以结合。事实上,8086 CPU和80287就可以组合在一起工作。
      与识别不同CPU的方法相比,识别协处理器的技术要利用不同代的协处理器之间的
细微差别。分辨系统中使用的是何种芯片,会由于在系统中根本未使用协处理器而复杂化
(数学协处理器决没有那么便宜——需要使用协处理器的应用也不普遍——使得卖方会
自动地将它们放入系统。另一方面,很少有卖方想把它们的产品放在失去和应用程序确定
的协处理器百分之一百兼容的地位上。折衷的方法是,在主板上放了一个协处理器的插
座,由用户选择是否要安装一个协处理器。)
      要确定当前协处理芯片是哪一种,可将一个位模式写进内存,试图初始化协处理器芯
片。然后数学协处理芯片运行一个将协处理器状态字写入内存的指令。如果拥有该芯片,
则有一个新值写入内存,如果没有该芯片,则写入的是位模式,而不是有效的协处理器状
    态字。
      当知道有协处理芯片存在后,可以用通过区别协处理器中断和读控制的方式来区分

23页
 8087和80287以及80387。这个过程对8087有效,但对80287或80387无效。要区别
80287和80387,可以创建出一个正的无穷大的值(正1除以0),再创建一个负的无穷大
的值,然后用协处理器来比较这两个值,因为80387在两个值之间有区别,而80287则没
有区别。
  在列表2.2中的过程可以被调用来确定当前使用的是哪个协处理器,如果它确实存
在的话。
    列表2.2
        page 60, 132
       ;CheCktpu. asm
        ;Determine the type Of math coprocessor(fpu)installed.
                  .model small
                  .stack
                  .data
        ScratCh dW          (?)            ;have the math chip  store data here
        Saynone db        " NO math coprocessor$"
        say87      db      "  8087$"
        say287   db       " 80287$"
        Say387 db         " 80387$"
                  .Code
                  .startup
      ·checkfpu proc
                  fninit                       ; initialize the fpu
                  mov      scratch ,  055AAh;the fpu will not write this
                  fnstsw Scratch               ;  have the fpu write its status word
                  cmp      byte ptr scratch,0;check lSb--it shbuld be 0
                  jne      no math             ; if not, retyrn
                  fnstcw scratch               ; now have the fpu write its  control word
                  mov      ax , Sccatch       ;  read the value
                  and      ax ,0103Fh         ;mask expected bits
                  cmp    ax ,0003Fh          ;  this is what you should see
                  jne     no_math              ; if different ,  no math chip
        ;Now that you know that you have an fpu ,  which one is it?
                  and      Scratch    0FF7Fh ;  clear interrupt bit
                  fldcw    scratch             ;  load the control word
                  fdisi                        ;  disable interrupts
                  fstcw    Scratch             ;  write the control word back
                  test     Sccatch , 00080h ; any effect on the word?
                  jnz   found_8087          ;  if so , it is an 8087
        ;The chip is not an 8087 , so it is an 80287 or 80387.
                  finit                       ;reinitialize the chip
                  fld1                         ;  push +1.0 onto the chip's stack
                  fldz                         ; push 0.0 onto the chip's stack
                  fdiv                        ; produce positive infinity
                  fld      st                  ;  produce negative infinity
                  fcompp                    ;compare
                  fstsw   scratch            ;write the status word
                  mov     ax , scratch

24页
        sahf                     ; copy AH into the flags register
            je       found_ 80287     ;  if Z bit set (equal)  ,  the
                                    ;   coprocessor found positive and
                                   ;   negative infinity to be equal
    ;The chip is an 80387
            mov      dx ,  offset say387
            mnv      al,3         ; errorlevel 3
                jmp      sayso
    no_math:
                mov       dX,offset saynone
                mov        al,0                  ; errorlevel 0
                jmp      sayso
      found_8087:
                mov          dx,offset  say87
            mov        al,1          ; errorlevel 1
            jmp    sayso
      found_80287:
                mov          dx,offset say287
            mov      al,2             ;  errorlevel 2
    sayso :
            push     ax                ;  save errorlevel
            mov     ah,9              ;  call DOS write string function
                int        21h
                pop         ax                       ;  retrieve errorlevel
            mov     ah , 04Ch         ; terminate Process with return code
                int         21h
    checkfpu endp
                end
                      2.4内      存
      PC及其兼容机中有四种类型的内存:
      ·ROM(只读内存)是安装在计算机中的永久内存,它通常保留特定的机器的
        BIOS部分。
      · RAM(随机存取内存)非永久地保留程序代码和数据。
      ·扩展内存(extended memory)(超过1M的内存)可以被80286处理器在保护模
        式下存取。
      ·扩充内存(expanded memory)加入到系统但不是直接被处理器映射的内存部
        分。这部分内存通过特定的扩充内存驱动系统来存取。
      读者可能已经听说过多种ROM,如PROM(可编程只读存储器)或EPROM(可擦写
可编程只读存储器),所有这些都属于ROM类型。尽管有人反对这样归类,但从DOS系
统程序的标准来看,PROM和其它一系列ROM都表示永久存储器。
      图2.6显示了在基本系统内存中内存的映射图。
      在第10章“程序和内存管理”中,将要详细讨论内存的分配和使用方法,并学习在程
序中怎样控制内存以及怎样使用内存。

25页
                        图2.6带有1兆内存机器的内存图
                        2.5I/O通道
      PC及其兼容机上的标准输入/输出(I/O)设备是键盘、视频监视器和打印机(见第5
章“输出设备”和第6章“输入设备”)。除了这些标准设备以外,计算机还常配有鼠标以及
一个或多个串行接口(见第6章和第7章“串行设备”)。
      可以增加诸如触觉感应屏幕(触摸屏)以及各种类型的传感器等一类的用户设备到
PC系统中。尽管讨论这些特殊设备已经超出了本书的范围,但在第12章“设备驱动程序”
中,将针对特定的设备,介绍怎样编写自己的驱动程序。
2.5.1键盘
      PC键盘从不知道从键盘上键入的内容。键盘不解释所击的键,只是直接告诉计算机
特定的键被按下或松开。键盘并不指定每个键的含意。但它指定每个键有一个唯一的数
值(扫描码)。这个扫描码被BIOS传送到计算机去解释。图2.7介绍了原始84键版本的

26页
键盘的扫描码。后来的键盘增加了更多的键,它将在第6章里介绍。
                                      图2.7键盘扫描码
      当使用者按下某一个键时,键盘通知计算机(通过Int 09h)那个键已被按下或松开。
当处理器执行Int 09h时,BIOS取得计算机瞬时的控制权,读取该键的扫描码。BIOS首先
检查像Shift和NumLock这样的双态键。如果双态键被按下或松开,BIOS修改在内存地
址0417h-0418h上的键盘状态位。接着,BIOS检查一些特定的组合键(如Ctrl-Alt-Del),
如果需要,就运行它们对应的特定的处理程序。
      如果扫描码还没有当作特殊用途的键(像NumLock,Ctrl-Alt-Del,Shift或者Ctrl等)
被“清除”的话,BIOS将它转换成等值的ASCII码。如果对该键没有正确的ASCII字符相
对应,它就给出值为零的ASCII码。然后,该ASCII字符,加上它的初始扫描码,就被保存
到键盘缓冲区中。这个缓冲区足以存放15个字符和它们的扫描码。如果缓冲区已满的话,
BIOS就会发出蜂鸣声(以表示键盘缓冲区满)并且去掉此键的扫描码的值。
      在字符到达键盘缓冲区后,就允许运行着的程序(包括DOS)使用它了。因为计算机
通常在几分之一秒中就响应,所以填满键盘缓冲区的机会是很小的,除非计算机忙于处理
其它任务。
      这里只能对键盘进行粗略的介绍,更详细的讨论键盘的编程请阅读第6章“输入设
备”。
2.5.2显示器屏幕
      PC支持多个视频接口卡的型号,并且每个显示卡都可工作在多个文本或图形模式
下,然而,编写一个适应各种显示的程序并没有想象的那么困难,因为DOS提供了确定显
示卡的种类以及当前工作模式的工具。
      第6章将详细讨论这些内容,这一节只介绍一些典型的显示卡类型。
      显示卡的类型
      对于大多数编程人员来说,至少应熟悉6种类型的显示卡。当然也有其它类型的显示
卡,但通常只用在一些特定的应用中。
      初始的“标准”显示器是单色显示卡(MDA)。这个系统以其明快的、清晰的字符以及
专业化的外观在计算机的商业应用中得到了很高的评价。其它视频卡(CGA、EGA、HGA、

27页
MCGA和VGA)也开始在不同的显示场合能被用户使用。表2.2列出了这些显示卡以及
它们开始使用的年代。
                                  表2.2显示卡和使用的年代
显示卡              推出的年份
MDA                       1981
CGA                       1982
    HGA                   1982
    EGA                     1984
    MCGA                    1987
    VGA                     1987
      在对单色显示卡的扩展中,彩色显示卡(CGA)使显示彩色成为可能,这一点是非常
重要的。CGA显示卡可以显示彩色和图形,但是显示字符不如MDA的清晰。这个不同的
原因在于产生每个字符的点阵象素数。 MDA使用9*14的字符框产生字符,而CGA使
用8*8的框。因为密度的不同,CGA的字符看起来要比MDA的字符“蠢”。
      大力神(Hercules)图形显示卡(HGA),结合单色屏幕的清晰的字符以及彩色图形卡
显示的图形产生了高分辨率的单色显示效果,因此它很快成为结合文本和图形的标准。
HGA不能产生彩色,但这个不足对它并不是特别不利。
      随着增强图形卡(EGA)彩色图形系统的推出,人们(和商业市场)开始发现,彩色使
他们的工作更加丰富多彩,更加有高度了。仅高亮度不足以在屏幕上显示各种变化,但可
以用彩色来强调很多事情。
      虽然只是少量的改进,使用也不广,但随着IBM PS/2型号25和30的多彩色图形阵
列(MCGA)和IBM PS/2型号50、60、80的视频图型阵列(VGA)的推出,显示的标准再一
次被重新确定。 MCGA类似于CGA,但它的分辨率更高。 MCGA分辨率是320*400;
CGA的分辨率是320*200。 VGA的分辨率(640*480)是EGA(640*350)适当扩充。两
种显示器中主要的改进则是所有的显示都使用的是模拟的而非数字的监视器。在模拟信
号下工作,新的视频系统可以显示256色的调色板(允许产生多达262144种颜色)。
      内存映射与显示卡
      在IBM系列中的视频显示卡都使用内存映射。换句话说,即将屏幕上所见的内容直
接映象到被显示卡控制的内存区域中。字符的实现很简单,它被直接写入显示内存,然后
显示卡从显示内存中读出该字符并将它显示到屏幕上。在图形模式下,显示卡将视频内存
的数据当作一个在屏幕上控制点的分离着的位的阵列。内存区域的使用按照显示模式以
及不同的显示卡有着很大的区别。表2.3详细列出了每个显示卡的视频缓存的起始位置
和长度。
                                  表2.3各显示卡的内存配置
显示器类型        显示模式          缓冲区段地址        缓冲区长度    显示页数
    MDA             文本              B000h                    4K          1
    CGA             文本              B800h                     16K         4/8
      图形              B800h                      16K         1
    HGA           图形                B000h                   64K           1
28页
                                                                  (续)
显示器类型      显示模式          缓冲区段地址      缓冲区长度      显示页数
    EGA           单色            B000h                 可变        可变
                  文本           B800h                可变        可变
                  图形            A000h                 可变        可变
    MCGA          文本            B800h                 32K         8
                  图形            A000h                  64K         1
    VGA           单色            B000h                 可变        可变
                  文本            B800h                 可变        可变
                  图形            A000h                 可变        可变
    尽管本节给出了显示卡功能的概述,但如果要了解更详细的信息,还是请参阅第5章
“输出设备”。第5章提供了一些关于显示卡怎样解释视频内存以及怎样用BIOS和DOS
功能去显示信息的内容。
2.5.3打印机
    在这本书中,名词打印机一般指连接在并行打印机上的打印机,而不指连在串行口上
的打印机(串行口将在下一节和第7章“串行设备”中讨论)。通过并行打印机接口,可以向
打印机传送一个初始信息,并且查询打印机当前状态,例如,打印纸是否用完等。这里特指
的是在DOS层用打印机可以做些什么。而打印机的使用则超出了本书的范围。
    在第5章“输出设备”中,读者将学到怎样编写一个程序,用BIOS和DOS功能直接访
问打印机。可以同时访问多个打印机(例如:LPT1和LPT2),并且可以解释返回码,来确
定打印机的状态。
2.5.4串行口
    当与一台并行打印机连接时,只能得到对并行打印机口的有限的控制。现在硬件已经
设计成几乎可以处理每个任务。你可以随意买一台打印机,并能保证在插上它之后,就能
正确地工作。然而,串行口则不同。
    当今大多数的计算机至少装备了一个串行口。它主要用来驱动串行打印机、鼠标或者
调制解调器,串行口还有些特殊的问题。连接双方必须设定它们的参数;如果参数设置不
对,就连接不通。这些参数包括波特率、奇偶校验、起始位、结束位以及数据长度。尽管大
多数(但不是全部)设备的物理连接都遵守一个标准,但参数还没有标准化。即使完成了正
确的物理连接,还必须完成正确的逻辑连接。
    目前还没有一个快速和简单的连接方法。串行口的参数指定了在信息传递时每秒传
送的位数;组成字符的位数;是否有奇偶校验位,如果有,校验的方式是什么;以及用来标
识字符结束的终止位的数目。可以用软件的控制流覆盖线路的设置,例如XON/XOFF或
ETX/ACK;或者用特定的线路协议,例如Xmodem或Kermit。因此,不熟练的人很难在第
一次将计算机和电话线连接就获得成功也就不足为奇了。
    第7章将专门解决串行通信的难点,以及怎样对它们编程。还将讨论所有串行口参数

29页
    的含义,以及怎样将这些信息最恰当地与所编的程序相结合。
    2.5.5鼠标
      当设计原始的PC时,鼠标并不是所考虑的重要设备。在BIOS中的程序允许程序员
    控制很多流行的控制杆和光笔。但是,时至今日,只有鼠标才被大量使用。
      一般情况下,鼠标或者通过和用户装在PC内总线上的控制板连接,或者通过串行口
    连接。鼠标的软件驱动程序确定鼠标的位置,并且处理连接到板上的接口。
        鼠标的工作机制
      在一般的形式中,鼠标是在底部安装了一个小球的设备。当在平面上移动鼠标时,传
    感器测量设备在X和Y方向的移动量。鼠标将位置的变化标志的信号传送给计算机系
    统。光电鼠标不使用小球,但它跟踪反射光和移动量,使用什么型号的鼠标并没有关系,计
    算机通过在屏幕上可视的指针来反映鼠标位置的移动。所有这些动作都在驱动程序层处
    理。
      除了移动传感器之外,鼠标通常安装一个、两个或三个开关(称为按钮),可以用它们
    来测试和控制程序的动作。
      当使用标准的鼠标驱动软件时,DOS的Int 33h将控制鼠标。这个中断提供了鼠标及
其移动的信息,并且提交这个数据的控制。即使鼠标是外接到DOS系统上的,也可以通过
    第6章“输入设备”来学习有关它的更多东西。
                      2.6存储设备
    随着DOS的升级,磁盘存储容量也有了很大扩充。表2.4介绍了软盘容量的增加以
    及所支持驱动器型号的数量。
                                      表2.4软盘容量
DOS版本                     软盘                      容量
1.0                        5.25英寸SSDD                       160K
                            5.25英寸DSDD                       320K
2.0                        5.25英寸SSDD                       180K
                            5.25英寸DSDD                       360K
2.1                        5.25英寸DSHD                       1.2M
3.2                        3.5英寸DSDD                        720K
3.3                        3.5英寸DSHD                        1.44M
6.0                        3.5英寸DSHD                        2.88M
2.6.1物理磁盘结构
      磁盘的记录表面,分成了很多同心圆磁道,每个磁道分成多个扇区。磁道和扇区的数
    目随着磁盘的型号(软盘或硬盘;单面或双面;倍密度或高密度;3.5英寸或5.25英寸

30页
等。)不同而变化。图2.8介绍了磁道和扇区在磁盘中的安排。
            图2.8磁盘磁道格式      图2.9固定的磁盘(硬盘)
    因为硬盘驱动器(相对于可移动的媒体,也称为“固定磁盘”)包括多个盘片,硬盘空间
又分成柱面。每个柱面包括每个盘片的每个面上的一个磁道。图2.9介绍了磁道怎样组
成了柱面。
    讨论磁盘结构的第8章将详细讨论磁盘的物理格式。第8章还介绍怎样调用控制低
层次磁道格式化操作的内部格式化程序。
2.6.2逻辑磁盘结构
    FORMAT程序不但建立了磁盘的扇区结构,而且还建立了逻辑结构,即专属于DOS
的控制存储在磁盘上数据的一种方式。图2.10介绍了这个逻辑结构。
      引导扇区  FAT1       FAT2       根目录       数据
                                图2.10磁盘的逻辑结构
    FORMAT程序最关键最常用的任务就是格式化磁盘——将物理磁盘分成逻辑磁盘
和扇区并填入初始值。
    在格式化完磁盘后,FORMAT程序在磁盘上建立了三个区域;引导记录、文件分配
表和根目录。磁盘的保留区(上几部分不在这里)是文件的存储区。
      引导记录。
    引导记录总在每个逻辑磁盘的第一扇区中。从DOS 2.0开始,引导记录便包含磁盘
引导程序(仅几百个字节长)和磁盘特性表。当系统启动时,引导程序被调入内存并且引导
程序从磁盘中调用操作系统文件。如果没有发现这些文件,引导程序将显示出错信息。引
导处理将在第3章“动态的DOS”一章中详细介绍。
      文件分配表
    文件分配表(FAT)是磁盘的映象。它跟踪磁盘的每一部分是否被占用,或不能被占
用(例如,因为格式化错误)。磁盘区域是以簇的形式被文件占用的,每个簇的情况反映到
FAT表中。根据磁盘的大小,簇的大小可以在一到八个或更多的扇区范围内变化。为了适

31页
应硬盘存储容量的扩充,FAT项(最初每个项12位)现在已扩充为每项16位。FAT项的
大小是DOSV2、V3和V4之间最主要的差异之一。
      要强调的是,FAT是DOS中最重要的关系到磁盘的一个特殊功能。FAT可以建立
大于512字节的文件,任何损害FAT的行为都可引起文件和程序被截断。FAT的详细介
绍和讨论,将在第8章“磁盘”中介绍。
      根目录
      在磁盘上最后一部分的系统信息是根目录,它紧接着FAT表。主要包含可操作文件
的以下信息:
      ·一个8字节的文件名
      ·一个3字节的文件扩展名
      ·文件大小(以字节计)
      ·文件的日期时间印记
      ·文件的起始簇号
      ·文件属性码
      每个项有32字节长,剩余的字节留给将来扩充。对给定的磁盘,根目录的大小是固定
的。在160K单面磁盘中,根目录可以包含64个项;在20M硬盘中,可以保留512个项。目
录区的大小是有限制的,因此DOS可以区分数据区是从什么地方开始的。在DOS V2及
其后版本中,该限制是没有问题的,因为可以通过建立子目录来越过这个限制,实际上并
无大小的限制。
      更详细的关于磁盘结构和目录的讨论,请见第8章“磁盘”和第9章“目录和文件”。
                        2.7软    件
      在物理机器之上,提供的软件在PC或兼容机上建立了另一层虚拟机。软件从BIOS
开始,它为隐去已安装的特定设备而建立了一个机器的标准窗口。建立在BIOS之上的
DOS机器是大家很熟悉的形式(以文件和目录为单元)。
2.7.1BIOS
      在虚拟机上的第一个软件层是BIOS(基本输入/输出系统)。这个软件生成经常涉及
的最低层的机器。
      真正的BIOS是由固化在ROM中的,包含很多基本机器功能的程序组成。包含很多
I/O系统软件的描述也作为BIOS的一部分,这些软件,是从磁盘中调入的,它扩充了
BIOS的功能,使得BIOS能处理所有的系统输入/输出要求。 BIOS的目的就在于使高层
软件和计算机中可能发生的硬件变化隔离开;I/O系统的目的在于作为BIOS和DOS的
缓冲接口。BIOS和I/O系统结合起来,为高层软件提供了一个基本的,定义一致的服务程
序集合。
      每个计算机制造商(包括IBM)都为其机器提供了BIOS和自定义的I/O系统。 Mi-

32页
    crosoft公司提供了一个称为SYSINT的模块(见第3章),来管理系统的初始化和DOS的
    装载。 BIOS和I/O系统的结合必须为适应高层软件的调用而符合一定的标准。例如,Mi-
    crosoft的DOS核心,就使用BIOS服务程序来辅助它自己的很多操作。
        PC兼容机经常带着由制造商提供的BIOS ROM版本。没有人能复制IBM BIOS
    ROM中的编码,但他们能提供与IBM相同的处理的中断结构和使用相同的数据表区域
    的BIOS。尽管编码不同,但它提供的服务也是DOS需要的。
      如果通过定义的BIOS中断,存取第三方的BIOS ROM,则可以超出IBM PC服务程
    序提供的方式进行工作。如果依赖未公开BIOS ROM功能知识来编写某个程序去完成某
    件事,所有赌注将会失去。这种编码的一个常见例子就是在多速度兼容情况下转换速度切
    换的这样一个程序;因为IBM从来没有这个特性的类型,没有适用它的接口标准,因此就
    必须反复试验才行。
      在本书后面“BIOS参考手册”一节中将详细介绍BIOS的功能。所有这些功能都在所
    有的IBM兼容计算机提供的BIOS ROM中。
    2.7.2 DOS核心
      Microsoft提供的DOS核心是基于标准BIOS服务程序之上的程序。 DOS核心提供的
    服务程序与硬件无关,它可以被应用程序在各种系统中调用。读者将和这些服务程序渡过
    很大一部份时间(注意:“DOS” 指的是IBM的DOS版本或非特别说明的MS-DOS)。
      DOS服务程序可以按属性分成以下部分:
        ·字符I/O
        ·目录操作
        ·磁盘控制
        ·动态内存分配
        ·出错处理
        ·文件操作
        ·各种系统功能
      ·网络功能
        ·程序初起和终止
        有两种方式调用DOS服务程序。某些服务程序可能通过软件中断直接调用。然而,大
    多数DOS服务程序则是通过将功能号放在寄存器AH中,然后调用运行Int 21h来实现
    的。在本节后面“DOS参考手册”一节中将详细讲述DOS中断功能。这些中断功能适用于
    所有的PC及其兼容机。这节还将指出系统之间的不同点。
    2.7.3命令处理器
        对大多数工作在PC机上的人来说,命令处理器(或外壳)就是操作系统。这些使用者
    认为提示符>是来自操作系统而不是来自程序。仅在几年之前,交互式的操作系统才开
    始创建这种方式。

33页
  今天,外壳的接口已成为标准。外壳不仅改变了处理方式,并且,还因为只改变了操作
系统中的一部分,所以很容易加入新的特性。尽管外壳接口不是UNIX的设计者发明的,
但这种类型的程序的应用(如COMMAND.COM)则是被UNIX操作系统推广开的。
UNIX系统已经有了几种标准的外壳(如csh、ksh和sh等一些名字)。
    COMMAND.COM的结构对它的操作是非常重要的。这个程序有三部分:初始化部
分,驻留部分和暂驻部分。
    当COMMAND.COM启动后,初始化部分和驻留部分首先被从磁盘上调入。初始化
部分设置系统,运行AUTOEXEC.BAT文件,然后调用并把控制传送给驻留部分。正如
其名字所表示的,暂驻部分(按照内存的要求)被调入和调出。“常驻内存”的驻留部分在增
加某些事情时,对重新调入暂驻程序作出相应的反映。
    如果COMMAND.COM的所有功能都编在同一个程序中,这个程序将占相当大的
内存数量(大于20K)。尽管这个内存数量和大多数应用程序所需的内存相比是沧海一粟,
但是,要想利用最后的某些作用来装载文件或将最后一些单元放到离散片中去时,这个数
量就值得考虑了。为了减少COMMAND.COM的内存消耗,COMMAND.COM的常规操
作编码和程序的内部命令的编码放在暂驻部分。因为这个部分有时被其它程序覆盖,
COMMAND.COM的驻留部分查看某个暂驻部分时必须调入,如果需要,则调入该部分。
      COMMAND.COM运行程序可分成三种类型的命令:
      ·内部命令(建立在COMMAND.COM中)
      ·外部命令(存在磁盘上)
      ·批文件(存在磁盘上)
    COMmANd.COM的暂驻部分储存有内部命令的编码。当用户输入一个命令名字
后,COMMAND.COM首先查询是否是其中的一个内部命令。如果COMMAND.COM没
有这个内部命令的名字,则该程序先在当前目录中查找,然后到路径中查找。 COM-
MAND.COM查找外部命令时应先查.COM扩展名命令,然后再查.EXE扩展名的命
令,如果在给定的目录中都没有发现这些命令,COMMAND.COM则继续查找相应的名
字的批文件(扩展名为.BAT)。
    批文件是命令处理器允许的特殊类型的“程序”。这个文件由描述一组给定顺序执行
的命令组成,并可配以参数替换及判定和跳转等简单的控制。 COMMAND.COM逐行地
执行批文件中的命令。每一行都由将要执行的命令组成:或者是一个可执行的命令,或者
是只允许在批文件中使用的内部控制命令,其实际操作很简单。 COMMAND.COM的暂
用部分从批文件中取出一行,处理任何参数的替换,都用DOS EXEC功能执行该命令。当
每一行结束后,COMMAND.COM取出下一行并接着执行。
2.7.4设备驱动程序
    在软件技巧方面,大多数改进都涉及使底层的硬件消失。例如:高级语言一个优点就
是它们不需要让程序员知道寄存器、位以及字节(不是每个人都同意这个观点)。类似的,
操作系统要改进的主要是:当我们要使用某个设备时不得不为自己的设备写驱动程序的

34页
    问题。
      CP/M使用标准的设备来处理终端和打印机。 DOS则已向前走了一步,它使设备有
    了更多的内部可变化性,并在不重编译整个系统的前提下,有可能安装自己的设备。想想
    看!以前,如果要给系统增加一个新的设备,不得不修改操作系统的内部以便使增加的设
    备可以工作。现在,DOS包含了很多灵活的驱动模块允许用户编写设备驱动程序,并在系
    统启动时选择地加入。要理解它是怎样工作的,还得了解设备驱动程序的知识。
      操作系统软件包含一组运行硬件的设备驱动程序(驻留驱动程序)。每个驱动程序按
    照它的特性组织它们的调用接口,因此,DOS在不用知道硬件怎样工作的情况下就可以
    操作硬件设备。
      当启动计算机时,DOS通过标准的初始化入口指针初始化所有的驱动程序(见第3
    章“动态的DOS”)。现在,读者所要知道的操作设备的全部内容是一系列标准入口指针定
    义的功能。需要控制的设备类型决定于入口指针的定义。在第12章“设备驱动程序”中,
    将更详细的了解并实际生成一个简单的设备驱动程序。
      DOS将设备分成字符设备和块设备。字符设备是基于字符到字符操作的设备(例如,
    键盘和显示器);块设备是基于块传送的设备(磁盘和RAM磁盘)。驱动程序的每个类型
    都有相应的处理程序功能的入口指针。
      读者可以编写一个自己的设备驱动程序并把它加到CONFIG.SYS文件中。这个设
    备在下次启动时就被加入到系统中。驱动程序的操作和驻留的驱动程序相同。读者甚至
    可以用全新的编码替换掉已存在的字符驱动程序,例如ANSI.SYS和其它驱动显示器的
    驱动程序。
      可安装驱动程序使用户可以在系统中加入原设计没有考虑到的新的设备(MOUSE
    .SYS加入鼠标;EMM.SYS用来扩充内存)。一句话,DOS已经创造了一个环境,使用户
    安装自己所需的新的设备成为了可能。
                        2.8小      结
      在本章中,读者了解到DOS系统是作为“虚拟计算机”的层次存在的。从最底层硬件
    开始,接着升到BIOS和DOS系统,每个层次都提供了一个兼容的、有补充下一层次计算
    机系统使用的必要功能的逻辑计算机。
      最底层,硬件设备(组成系统的内容的组合)在不同系统之间,可以有很大的差异。在
    下一层,BIOS提供了一个“计算机”,它以其定义的服务程序使用户在不同的系统中可以
    用相同的方式工作。这些基本的输入输出服务程序允许以固定的方式控制系统的设备。
    DOS提供了一个相对于BIOS更高层的服务(高层次的提炼)。 DOS服务程序通常完成一
    些系统操作,例如创建文件和目录等。在这个高层次中,COMMAND.COM提供了一个用
    户接口用以控制不同的服务程

抱歉!评论已关闭.