注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

DOS编程技术

讨论在纯DOS下的编程技术

 
 
 

日志

 
 
关于我

1984年大学毕业,1985年底有机会开始接触PC机,1986年开始在PC机上做开发工作,曾接触过MS-DOS、CP/M、UNIX、VMS、LINUX、iRMX等众多的操作系统并在上面从事技术开发,擅长做底层与硬件相关的软件开发,目前主要在DOS和LINUX平台下工作,主要从事软件,在硬件开发上也有一定造诣,亦有在8051系列、6502系列(凌阳)、z80系列、ARM、X86等各类平台下开发软硬件的经历。更详细情况可以参考http://resume.whowin.net

网易考拉推荐

旧文回顾之一:AT机扩存的使用方法  

2008-08-17 22:43:12|  分类: 旧文回顾 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
    由于近来有一些事要忙,加上我本来要写的《USB系列》文章遇到了一些麻烦,本来我应该正式写一个U盘的驱动程序了,我原来的计划是:1、介绍DOSUSB的使用;2、借助DOSUSB写一个U盘的驱动程序;3、回过头来完成DOSUSB的功能。但在写U盘驱动这个环节上遇到了困难,主要是因为驱动程序是在config.sys中加载的,而DOSUSB是一个内存驻留的可执行程序,要在config.sys后才能加载,这就造成在驱动程序加载时还没有可以使用的DOSUSB,这样会使驱动程序的初始化部分不能完成,尽管有办法可以回避一下,等实际加载完DOSUSB后再做U盘驱动程序的初始化,但显然这样的做法很不规范,使得我们整个的过程不够完美,为此,我准备先编写一个虚拟驱动程序实现DOSUSB的功能,但这一步相对复杂,需要花费一定的时间,所以可能要等一段时间后才能继续《USB系列》的文章。
    在空下来的这段时间里,我想把我年轻时当时为了评职称写的几篇文章,最早的那篇文章距现在已经有近20年,前几天,我在GOOGLE里输入我的名字做了一个搜索,不想这几篇文章都被搜了出来,好像是被个什么数据库给收录了,可恶的是不能免费浏览全文,要花点钱才行,这不是我喜欢的方式,所以那个时候我就想找机会把这几篇文章公布,翻找以前的旧书旧杂志,还真让我找到了,这几篇文章分别是:
    1、AT机扩存的使用方法 ---- 发表在1989年第5期中国软件行业协会会刊《电脑》杂志上
    2、程序到运行的实现方法 ---- 发表在1991年第2期中国软件行业协会会刊《电脑》杂志上
    3、PC机实时时钟及其应用 ---- 发表在1993年第1期中国软件行业协会会刊《电脑》杂志上
    就找到了这三篇,从下篇文章起,逐一登载出来,做一个《旧文回顾》系列。

AT机扩存的使用方法


    时代背景(这一段不是原文,是我新加的,标成蓝色):
    在1989年,我印象中把以8086做CPU的PC机叫做PC/XT,把80286做CPU的PC机叫做PC/AT,所以有XT机和AT机的叫法,AT机当时是很高档的机器,正好我有一个给民航的项目使用的AT机,使我有机会接触这种新的CPU,当时还没有互联网,资料及其匮乏,既然我有了一个新机型,自然是希望能够尽量地发挥这个机器的作用,记不得当时从哪里得到了一本很薄的16开的书,好像是红皮的,印刷质量很差,错字也很多,可惜这本书我现在已经找不到了,这本书主要介绍80286保护模式的机制以及内存管理的方式,记得当时我做了大量的试验,终于可以驾驭AT机比XT机多出来的那384K内存,欣喜之余发现十分孤独,因为没有第二个人觉得这件事很重要,只好写了一篇文章发了出去,这大概就是这篇文章的创作过程。

    特别要说明的是,这篇文章发表在19年前,那个时候80286的机器还是比较好的机器,我记得当时我们从一家叫做“海华”的公司(不知道这家公司现在还在不在)买的机器,当时它在设计上好像是软驱与其它地方还有冲突,还是我们帮助他们发现这个问题,好像还讨论过如何解决,总之他们后来的机器里就没有这个问题了,所以那个时候关于保护方式、扩充内存等的资料是非常非常少的,但现在很多了,如果这篇文章还能帮助你的话,也请你翻阅一下现在有关这方面的资料,以便弥补文中的缺陷,谢谢!以下是原文,原文中的程序同样写于19年前,回顾之际,我并没有再次验证,如果有什么问题请与我联系。

    AT机,一般都装有1MB的RAM,但AT机单用户系统的用户,实际能使用的只有640KB,这是由于MS-DOS只有20位地址,最大寻址能力为1MB,但DOS给各类ROM留了384KB的地址,因而能用的RAM就只有640KB了。当然可以用虚拟磁盘的方法使用其余的384KB RAM,但这种方法显然不是最有效的,其实,DOS 3.0以上的版本中已经提供了使用扩充内存的方法,本文将通过一个实例介绍这种方法。
    通常情况下,AT机工作在实际方式(抱歉,那个时候对real mode这个词还没有统一的翻译方法)下,在这种方式下,CPU80286实际上可以说是一个增强型的8086,物理地址为20位,以段地址:偏移地址的方法表示;但AT机还有一种保护方式,在该方式下,物理地址已不再是段:偏移地址的形式,物理地址可达24位,因此能在主存16MB空间寻址,为了使用方便,AT机BIOS中断15H服务可以使用24位地址在扩存中来回传送数据,下面介绍这一功能的使用方法:
    AH = 87H
    ES:SI -- 以段:偏移地址的方式指向全局描述符表GDT
    CX -- 要传送的字数
    执行15H中断,便可以从源缓冲区到目的缓冲区传送数据,返回时,AH含有如下状态码:
    AH      状态
    -----------------
    0    传送成功
    1    RAM奇偶错
    2    异常错误
    3    地址线失效
    那么什么是全局描述符表GDT,并且如何建立呢?
    在保护方式下,80286要用到两个专用寄存器,成为局部描述符寄存器LDTR和全局描述附表寄存器GDTR,用这两个寄存器可以查找两个表,分别叫做局部描述附表LDT和全局描述附表GDT,其中LDT是和任务有关的,而GDT是和任务无关的,在我们讨论的课题中,只是要进行数据的传送,因而,只使用GDT,GDT的每个描述符由8个字节组成,如下:
    字节7:保留备用           字节6:保留备用
    字节5:访问权字节         字节4:物理地址的高8位
    字节3:物理地址的中8位    字节2:物理地址的低8位
    字节1:段长度的高8位      字节0:段长度的低8位
    其它字节较易理解,下面我们讨论访问权字节:
    bit 7    6 5    4    3    2    1    0
    ----------------------------------------
        P    DPL    1    0    1    1    A
    在我们的讨论中,位3必须为0,表示该段为数据段而不是代码段;位4为1表示该描述符是段描述符而不是系统描述符;位1为1表示该段可写;位2为1表示该段以描述符物理地址为起点向下扩展而不是向上扩展;A=1表示该段可被访问;P=1表示该段在RAM中,由于本文未引入虚拟内存的概念,因此我们使用的段总在RAM中,因而P总应为1;DPL为访问权限,可分为四级:00、01、10、11。
    下面我们举一个例子,字这个例子中,我们把主存中的200个字节写入20组0--9的ASCII码,然后把这200个字节移入地址100000H(扩存的起始点)起始的200个字节中,由于扩存无法直接访问,所以我们把贮存中的200个字节全部填充上0的ASCII码,最后,再从阔村中把这200个字节移回主存,看是否和以前的一致,文章最后附有这段程序,为了说明方便,程序中加了行号,程序用汇编语言写成。
    在执行15H类中断之前,程序为BIOS建立GDT表,它由6个描述符组成,限于篇幅,不能一一讨论,只给出结果,第1和第2个描述符要求全为0,即程序的第2行;第3个为源缓冲区描述符,程序第3--9行建立该描述符,其中GDT_S_L1、GDT_S_M1、GDT_S_H1分别为源缓冲区的低、中、高8位地址,其内容将在第56-58行填写;第4个为目的缓冲区描述符,第10-15行建立该描述符;第5和第6个描述符要求全为0;程序中,GDT1为向扩存传送数据的描述符表;GDT2为从扩存向主存传送数据的描述符表;第15行和第30行分别为GDT1和GDT2的访问权字节,93h的意义如下:

旧文回顾之一:AT机扩存的使用方法 - whowin - DOS编程技术    GDT1的目标缓冲区24位地址和GDT2的源缓冲区24位地址均为100000H为扩存的起点;BUFFER为主存中的缓冲区;第39-42行使DS=ES=CS;第43-55行把BUFFER的段:偏移地址换算成所需的24位地址;第62-76行把转换好的地址放入GDT1和GDT2中的适当位置;第62-76行把BUFFER中填充20组0-9的ASCII码,并显示之;第77-80行进行第一次移动,把BUFFER中的200个字节移入100000H起始的扩存中;第81-90行把BUFFER清0并显示之;第91-94行进行第2此移动,从100000H起始的扩存中把200个字节移入BUFFER中;第95-98行显示BUFFER中内容并退出。该程序的DISP子程序用于显示DX指向的字符串和BUFFER中的内容。注意,在执行15H中断前CX中为要传送的字数而不是字符数,因此,传送200个字节,CX应为100.另外,本程序为了简洁,没有错误处理,读者在实际使用中应加入。

    读者可以用该例介绍的方法灵活用于自己的程序中,这样也许会提高你的程序的运行速度,本方法已在PC/AT机上,在MS-DOS 3.3版,宏汇编5.0版支持下通过。

1    CODE          SEGMENT
2    GDT1          DB 16 DUP(0)
3                  DB 230
4                  DB 00H
5    GDT_S_L1      DB 00H
6    GDT_S_M1      DB 00H
7    GDT_S_H1      DB 00H
8                  DB 93H
9                  DB 2 DUP(0)
10                 DB 230
11                 DB 00H
12   GDT_T_L1      DB 00H
13   GDT_T_M1      DB 00H
14   GDT_T_H1      DB 00H
15                 DB 93H
16                 DB 18 DUP(0)
17   GDT2          DB 16 DUP(0)
18                 DB 230
19                 DB 00H
20   GDT_S_L2      DB 00H
21   GDT_S_M2      DB 00H
22   GDT_S_H2      DB 00H
23                 DB 93H
24                 DB 2 DUP(0)
25                 DB 230
26                 DB 00H
27   GDT_T_L2      DB 00H
28   GDT_T_M2      DB 00H
29   GDT_T_H2      DB 00H
30                 DB 93H
31                 DB 18 DUP(0)
32                 ASSUME CS:CODE
33   BGN:          JMP START
34   BUFFER        DB 200 DUP(0)
35   DISPLAY1      DB 0AH, 0DH, "现在显示主存中的内容:", 0AH, 0DH, "$"
36   DISPLAY2      DB 0AH, 0DH, "现在显示扩存中的内容:", 0AH, 0DH, "$"
37   DISPLAY3      DB 0AH, 0DH, "现在主存中缓冲区已清0,请看:", 0AH, 0DH, "$"
38   START:
39                 PUSH CS
40                 POP DS
41                 PUSH CS
42                 POP ES
43                 MOV CX, ES
44                 MOV BX, 0
45                 MOV DX, OFFSET BUFFER
46                 MOV AX, 4
47   CONTINUE0:
48                 CLC
49                 RCL CX, 1
50                 RCL BX, 1
51                 DEC AX
52                 JNZ CONTINUE0
53                 ADD DX,CX
54                 JNC CONTINUE1
55                 INC BX
56   CONTINUE1:    MOV GDT_S_L1, DL
57                 MOV GDT_S_M1, DH
58                 MOV GDT_S_H1, BL
59                 MOV GDT_T_L2, DL
60                 MOV GDT_T_M2, DH
61                 MOV GDT_T_H2, BL
62                 MOV SI, OFFSET BUFFER
63                 MOV CX, 0
64   CONTINUE2:
65                 MOV AL, 30H
66   CONTINUE3:
67                 MOV [SI], AL
68                 INC SI
69                 INC AL
70                 CMP AL, 3AH
71                 JNZ CONTINUE3
72                 INC CX
73                 CMP CX, 20
74                 JNZ CONTINUE2
75                 MOV DX, OFFSET DISPLAY1
76                 CALL DISP
77                 MOV SI, OFFSET GDT1
78                 MOV CX, 100
79                 MOV AH, 87H
80                 INT 15H
81                 MOV AL, 30H
82                 MOV SI, OFFSET BUFFER
83                 MOV CX, 200
84   CONTINUE4:
85                 MOV [SI], AL
86                 INC SI
87                 DEC CX
88                 JNZ CONTINUE4
89                 MOV DX, OFFSET DISPLAY3
90                 CALL DISP
91                 MOV SI, OFFSET GDT2
92                 MOV CX, 100
93                 MOV AH, 87H
94                 INT 15H
95                 MOV DX, OFFSET DISPLAY2
96                 CALL DISP
97                 MOV AH, 4CH
98                 INT 21H
99   DISP          PROC
100                MOV AH, 09H
101                INT 21H
102                MOV SI, OFFSET BUFFER
103                MOV CX, 200
104  CONTINUE:
105                MOV DL, [SI]
106                MOV AH, 06H
107                INT 21H
108                INC SI
109                DEC CX
110                JNZ CONTINUE
111                RET
112  DISP          ENDP
113  CODE          ENDS
114                END BGN

(此文发表在1989年第5期《电脑》杂志上)

  评论这张
 
阅读(1796)| 评论(2)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018