DOS 实方式下直接访问4GB 内存

2023-10-14 01:38
文章标签 访问 内存 方式 直接 dos 4gb

本文主要是介绍DOS 实方式下直接访问4GB 内存,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


十堰市湖北汽车工业学院电气工程系(442002)  陈家祺
摘 要: 分析了80486CPU 的寻址机制, 提出了在实方式下直接访问4GB 内存的策略和C 程序设计方法。

关键词: DO S 程序 扩展内存 程序设计


在高档PC 微机系统中, 如80486CPU 微机系统,应用软件的开发可以基于DO S 系统的实方式, 也可以基于W indow s和O Sö2 系统的保护方式。如何在DO S系统的实方式下开发具有访问扩展内存的应用程序,这是广大软件开发者关心的问题。因为DO S 系统是在PC 机中应用最广泛的操作系统, 经过广大用户长年的应用和面向实际的软件开发, 其接口特性和编程方法被广大软件开发者所熟悉和掌握。然而, 开发基于DO S 系统的实方式应用程序存在一定的局限性, 主要是不能有效地利用高档微机的内存资源, 如扩展内存的访问。尤其在开发实时性很强的大数据量的应用程序中, 高效使用扩展内存是极为重要的。
目前常用的访问扩展内存方法有: (1) 采用“IN T15H”或HTM EM 1SYS 的功能调用; (2) 采用虚拟磁盘。前者只能实现数据块在常规内存与扩展内存之间移动, 这样, 不但还要占用一定的常规内存空间, 而且数据块的移动还需占用程序运行时间, 使程序的运行效率降低。后者可以以文件的形式将数据存储在扩展内存中, 采用文件的访问方式进行数据操作。显然, 这2 种方法只能间接访问扩展内存, 不能直接访问扩展内存, 而且数据的操作效率低, 难以满足实时性要求。

本文将从80486CPU (以下简称CPU ) 的寻址机制研究入手, 讨论在实方式下直接访问4GB 内存的方法和C 程序设计方法。


1 基本原理
1.1 物理地址形成的统一性
无论CPU 在实方式下或保护方式下, 其物理地址的形成都将使用段描述符高速缓冲寄存器。其差别是:在实方式下, 每当向段寄存器赋予新的内容(段地址) 时, 段描述符高速缓冲寄存器的基地址值相应发生改变, 其值为16×SEG, 这是线性基地址; CPU 最终形成的物理地址为某地址值加偏移量。段描述符高速缓冲寄存器的界限值和属性值始终不变。当CPU 复位后, CPU 的工作模式为实方式, 段描述符高速缓冲寄存器的界限值自动设置为FFFFH。因此, CPU 能够访问内存的空间为0~ 10FFEFH ( FFFFH × 16 +FFFFH =1114095) , 每个段的大小为64KB。在保护方式下, 每当向段寄存器赋予新的内容SEL (选择字) 时, 段描述符高速缓冲寄存器的内容将由SEL 对应的段描述符更新; 段描述符高速缓冲寄存器的基地址值、界限值和属性值依据段描述符的设置而发生改变。段的基地址可设置在4GB 内存的任意地址处, 段的最大界限值可达FFFFFFFFH (4GB - 1)。
在不分页的情况下, CPU 最终形成的物理地址同样是基地址值加偏移量。所以, CPU 能够整个访问4GB 内存。

显然, 对于CPU 在形成物理地址时, 在实方式下与在0 特权级不分页的保护方式下是相同的。只是段的基地址和段的大小设置范围不同。工作方式确定是由控制寄存器CR0 的最低位PE 位决定的, 若PE 为0, 则工作在实方式; 若PE 为1, 则工作在保护方式。在通过PE 位的改变时, 就进行了工作方式切换。这种切换只影响段描述符高速缓冲寄存器的基地址值运算方式, 不影响段描述符高速缓冲寄存器的段界限值。


1.2 直接访问4GB 内存
当CPU 复位后, CPU 处于实方式下, 尽管在实方式下可执行诸如“MOV AX,〔ES I〕”指令的32 位寄存器间接寻址操作, 但是ES I 的内容必须在0~ FFFFH范围内, 否则, 将引起13 号异常中断。基于CPU 物理地址形成的统一性, 在实方式下直接访问4GB 内存的关键是扩大段描述符高速缓冲寄存器的界限值。使诸如“MOV AX,〔ES I〕”指令的32位寄存器间接寻址操作实现4GB 内存的访问。然而,CPU 在实方式下并没有提供改变段描述符高速缓冲寄存器的界限值的操作指令。改变段描述符高速缓冲寄存器的内容只能在保护方式下进行, 即向段寄存器赋予段的选择字SEL , 段描述符高速缓冲寄存器的内容将由SEL 对应的段描述符更新。当CPU 从保护方式切换到实方式时, 段描述符高速缓冲寄存器的内容不发生变化。
因此, 在DO S 实方式下直接访问4GB 内存之前,让CPU 进入保护方式下, 通过装载具有4GB 界限的段描述符到段描述符高速缓冲寄存器中去, 然后返回到实方式下, CPU 就可以通过32 位寄存器间接寻址
操作实现4GB 内存的访问。


2 C 程序设计
2.1 编程环境
本文采用Bo rland C+ + 3. 1 程序设计环境, 在程序中使用内嵌汇编方法实现特定的操作, 在O P t ions的“Comp ile”- “A dvanced Code generat ion”中选择386 指令集。由于集成开发环境下的内部编译器不能识别内嵌的386 汇编指令, 对于32 位寄存器和32 位地址操作汇编指令, 可以采用直接在代码前加入操作数前缀0x66 或地址前缀0x67, 以便实现32 位寄存器地址的操作。最好的方法是让集成开发环境调用TA SM 1EXE 进行编译, 即设置O P t ions 中的“Comp ile”- “Code generat ion ”- “ Comp ile via as2sem ler”为ON。这样便可完整地运用386 汇编指令。在以下编程示例中采用了这种编译方法。

本程序是采用基于实方式下的编程方法。它不能在保护方式下和虚拟8086 方式下运行, 不能装载扩充内存EM S 驱动程序(如EMM 3861EXE) , 因为, 它使DO S 系统处于虚拟8086 方式下。


2.2 打开A 20 地址线
CPU 的A 20 地址线受到键盘接口处理器8042 的输出口P21 控制, 如果DO S 系统启动后, 没有装载XM S 驱动程序(如h imem. sys) , 此时A 20 被关闭, 要访问4GB 内存, 必须打开A 20, 是A 20 受到CPU 的控制。
vo id openA 20 ()
{  wh ile ( inp (0x64) & 2) ;   outp (0x64, 0xd1) ;
wh ile ( inp (0x64) & 2) ;   outp (0x60, 0xdf) ;
wh ile ( inp (0x64) & 2) ;   outp (0x64, 0xff) ;

}


2.3 设置数据段的4GB 界限函数
首先, 建立1 个全局描述符表GDT, 即GDT- def,它含有2 个描述符, 第1 个为空描述符(保护方式下系统要求的) , 第2 个是具有4GB 段界限的数据段描述符, 它的选择字为8。再计算出GDT 的基地址和长度存入GDT- A ddr 中。然后, 装载GDT, 进入保护方式,把选择字8 赋给DS 和ES, 此时第2 个是具有4GB 段界限的数据段描述符被装载到DS 和ES 的描述符高速缓冲寄存器中, 最后返回实方式。同理, 也可设置FS和GS 的4GB 界限。
unsigned long GDT2def [ ]= {0, 0, 0x0000FFFF, 0x008F9200};  //全局描述符表GDT
unsigned char GDT- A ddr[ 6 ]= {0};  //存放GDT 的基地址和长度
vo id set4gb ()
{ asm{
 cli
 push ds ;  push es
 mov wo rd p tr GDT- A ddr[ 0 ], (23 8- 1)  //GDT 的长度存入GDT- A ddr 中
 mov eax, ds //计算GDT 描述符表的线性基地址31~ 0
 sh l eax, 4 //段地址eax= ds x 16
 xo r ebx, ebx //ebx 清零
 mov bx, offset GDT- def //b x= GDT 的偏移地址
 add eax, ebx //GDT 的线性基地址= eax+ ebx
 mov dwo rd p tr GDT- A ddr [ 2 ]eax //GDT 的线性基地址存入GDT- A ddr 中
 lgdt fwo rd p tr GDT- A ddr
 mov bx, 8 /设置数据段描述的选择字
 mov eax, cr0
 o r al, 1
 mov cr0, eax
 jmp flush l
 }      //进入保护方式
flush l: asm{
 mov ds, bx //D S 装载具有4GB 界限的数据段描述符
 mov es, bx //ES 装载具有4GB 界限的数据段描述符
 and al, 0feh
 mov cr0, eax
 jmp flush2
 }      //返回实方式
flush2:  asm{
 pop es ; pop ds
 sti
 }

}


2.4 直接访问4GB 内存的基本函数
在DS 和ES 具有4GB 的访问界限后, 通过32 位寄存器间接寻址的指令就可实现4GB 内存的访问。以下仅给出字节的读写函数, 其中, addr 为RAM 的32位线性地址。
1. 读字节函数, 函数的返回值为读出的字节。
unsigned char read- ram (unsigned long addr)
{  asm push ds
asm mov ax, 0
asm mov ds, ax
asm mov esi, addr
asm mov al, [ esi]
asm pop ds
return- AL;
}
2. 写字节函数, ch r 为要写入的字节。
vo id w rite- ram (unsigned long addr, unsigned char ch r)
{  asm push ds
asm mov ax, 0
asm mov ds, ax
asm mov esi, addr
asm mov al, ch r
asm mov [ esi], al
asm pop ds

}


2.5 程序示例
本示例将使用上面所设计的功能函数, 由内嵌汇编程序完成对主机内存的测试和容量的检测任务。在PC386/33、PC486/100 上通过。
# include < do s. h>
# include < stdio. h>
vo id main ()
 {unsigned long addr;
openA 20 () ;
set4gb () ;
asm push ds
asm mov ax, 0
asm mov ds, ax
asm mov esi, 00100000h  //从1M b 开始测试
 N 1: asm mov eax, [ esi]  //暂存esi 地址指定双字单元的内容
asm mov dwo rd p tr [ esi], 0  //向esi 地址指定双字单元写零
asm mov ebx, [ esi]  //读出由esi 地址指定的双字单元的内容给ebx
asm mov dwo rd p tr [ esi], 0ffffffffh//向esi 地址指定双字单元写全1
asm mov ecx, [esi]  //读出由esi 地址指定的双字单元的内容给ecx
asm mov [ esi], eax  //恢复esi 地址指定双字单元的内容
asm inc ecx  //若ecx 的内容为全1, ecx 增1后, ecx= 0
asm cmp ebx, ecx  //比较2次读出的内容
   asm jne N 2  //不相等, 则退出循环检测
   asm add esi, 4  //e si 地址增4
   asm jmp N 1  //继续循环检测
N 2:  asm mov addr, esi
asm pop ds
p rintf ("RAM = % 1d (M b) " , addr > > 20) ;
}


3 与XM S 驱动程序的兼容方法

3.1 基本原理
如果没有装载XM S 驱动程序H imem. sys, 采用上述方法可无限制地使用整个扩展内存。若系统中的某些系统程序和其它应用程序需要使用H imem. sys,通过它分配和访问扩展内存。这样, 扩展内存的部分空间被占据, 用户应用程序所使用的扩展内存空间将受到限制, 否则, 发生冲突。

因此, 在这种情况下, 用户应用程序可通过H imem. sys 的功能调用, 为其分配未使用的扩展内存存储块EMB, 并通过锁定EMB, 得到EMB 的32位线性基址, 便可采用上述方法对存储块进行直接访问。


3.2 H imem. sys 的接口
1.取得安装状态
只有当H imem. sys 已被加载, 才能调用它的功能。当AX= 4300H 时, 执行“IN T2FH”软中断指令后,若AL = 80H, 则已加载; 若AL = 00H, 则未加载。
2.取得入口地址
H imem. sys 的各项功能调用是通过功能调用的入口地址进行的, 当AX= 4310H 时, 执行“IN T2FH”软中断指令后, ES= 入口的段地址,BX= 入口的偏移地址。
3.功能调用
H imem. sys 为用户提供许多XM S 的内存管理功能, 与本文相关的功能和接口如表1所示。

4 结束语
DO S 实方式下直接访问4GB 内存具有一定的特殊性和重要的实际意义。本文提出的方法在图像实时识别系统中得到了成功的应用。该系统需同时采集4幅图像, 每幅图像为512×512的256色点阵, 4幅图像共需1MB 内存空间, 在对图像进行处理时还需要2幅图像的工作缓冲区。显然, 在常规内存中难以进行存储和处理。若采用虚拟磁盘或XM S 驱动程序H imem. sys, 由于图像的数据量大、运算时间长, 影响了实时性要求。
通过采用本文提出的方法, 运用C 程序的内嵌汇编直接对扩展内存进行图像的存储和处理, 发挥了计算机(下转第28页)

这篇关于DOS 实方式下直接访问4GB 内存的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/207236

相关文章

NameNode内存生产配置

Hadoop2.x 系列,配置 NameNode 内存 NameNode 内存默认 2000m ,如果服务器内存 4G , NameNode 内存可以配置 3g 。在 hadoop-env.sh 文件中配置如下。 HADOOP_NAMENODE_OPTS=-Xmx3072m Hadoop3.x 系列,配置 Nam

内核启动时减少log的方式

内核引导选项 内核引导选项大体上可以分为两类:一类与设备无关、另一类与设备有关。与设备有关的引导选项多如牛毛,需要你自己阅读内核中的相应驱动程序源码以获取其能够接受的引导选项。比如,如果你想知道可以向 AHA1542 SCSI 驱动程序传递哪些引导选项,那么就查看 drivers/scsi/aha1542.c 文件,一般在前面 100 行注释里就可以找到所接受的引导选项说明。大多数选项是通过"_

安卓链接正常显示,ios#符被转义%23导致链接访问404

原因分析: url中含有特殊字符 中文未编码 都有可能导致URL转换失败,所以需要对url编码处理  如下: guard let allowUrl = webUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {return} 后面发现当url中有#号时,会被误伤转义为%23,导致链接无法访问

用命令行的方式启动.netcore webapi

用命令行的方式启动.netcore web项目 进入指定的项目文件夹,比如我发布后的代码放在下面文件夹中 在此地址栏中输入“cmd”,打开命令提示符,进入到发布代码目录 命令行启动.netcore项目的命令为:  dotnet 项目启动文件.dll --urls="http://*:对外端口" --ip="本机ip" --port=项目内部端口 例: dotnet Imagine.M

深入理解RxJava:响应式编程的现代方式

在当今的软件开发世界中,异步编程和事件驱动的架构变得越来越重要。RxJava,作为响应式编程(Reactive Programming)的一个流行库,为Java和Android开发者提供了一种强大的方式来处理异步任务和事件流。本文将深入探讨RxJava的核心概念、优势以及如何在实际项目中应用它。 文章目录 💯 什么是RxJava?💯 响应式编程的优势💯 RxJava的核心概念

【即时通讯】轮询方式实现

技术栈 LayUI、jQuery实现前端效果。django4.2、django-ninja实现后端接口。 代码仓 - 后端 代码仓 - 前端 实现功能 首次访问页面并发送消息时需要设置昵称发送内容为空时要提示用户不能发送空消息前端定时获取消息,然后展示在页面上。 效果展示 首次发送需要设置昵称 发送消息与消息展示 提示用户不能发送空消息 后端接口 发送消息 DB = []@ro

两个月冲刺软考——访问位与修改位的题型(淘汰哪一页);内聚的类型;关于码制的知识点;地址映射的相关内容

1.访问位与修改位的题型(淘汰哪一页) 访问位:为1时表示在内存期间被访问过,为0时表示未被访问;修改位:为1时表示该页面自从被装入内存后被修改过,为0时表示未修改过。 置换页面时,最先置换访问位和修改位为00的,其次是01(没被访问但被修改过)的,之后是10(被访问了但没被修改过),最后是11。 2.内聚的类型 功能内聚:完成一个单一功能,各个部分协同工作,缺一不可。 顺序内聚:

脏页的标记方式详解

脏页的标记方式 一、引言 在数据库系统中,脏页是指那些被修改过但还未写入磁盘的数据页。为了有效地管理这些脏页并确保数据的一致性,数据库需要对脏页进行标记。了解脏页的标记方式对于理解数据库的内部工作机制和优化性能至关重要。 二、脏页产生的过程 当数据库中的数据被修改时,这些修改首先会在内存中的缓冲池(Buffer Pool)中进行。例如,执行一条 UPDATE 语句修改了某一行数据,对应的缓

Java 多线程的基本方式

Java 多线程的基本方式 基础实现两种方式: 通过实现Callable 接口方式(可得到返回值):

JVM内存调优原则及几种JVM内存调优方法

JVM内存调优原则及几种JVM内存调优方法 1、堆大小设置。 2、回收器选择。   1、在对JVM内存调优的时候不能只看操作系统级别Java进程所占用的内存,这个数值不能准确的反应堆内存的真实占用情况,因为GC过后这个值是不会变化的,因此内存调优的时候要更多地使用JDK提供的内存查看工具,比如JConsole和Java VisualVM。   2、对JVM内存的系统级的调优主要的目的是减少