系统存贮器
分为2部分,低地址部分和高地址部分,其中高地址部分叫做上位存贮器(641k-1024k),地址地部分叫做基本存贮器或者基本内存(0-640k)
基本内存比较重要 :1我们的应用程序就放在该内存,dos命令,TSR驻留部分是受保护空间,系统不重启,他的内容就始终存在,这部分主要由dos的常驻程序占据,用户的驻留程序也在此,另外该内存中还有中断向量表,和bios数据区
高端存贮器中A0000到BFFFF用作显示缓冲区,C0000-DFFFF部分为Rom的扩展部分,它用作存储视频显示器适配器和磁盘的Bios和一些网络控制板,I/O接口板,EMS分页帧,F0000-FFFFF该部分有系统引导程序还有系统基本输入输出系统(Bios)
扩展存储器
首先要说明的是系统存储器在0-1024k 之间 扩展存储器在其之上 也就是FFFFH或1M的那部分存储器
高端地址一般很少用到,Dos5.0以上的版本提供了管理640以上的内存的xms内存管理程序HIMEM.SYS,这样只要在CONFIG.SYS加入下面两行内容:
Divce = c:/Dos/HIMEM.SYS
Dos = HIGH
config.sys他是一个告诉Dos系统配置的的配置文件
内存条(EMS)使用的原理
在高端地址中,也就是在A0000H以上的找个连续64kb的地址空间,作为分页帧,每一页占用16kb,一共分为4页,而EMS也分为许多帧,那么就形成了一一对应的关系,然后通过高端地址不停的刷新4个映射从而将EMS遍历完
现在的计算机采用20位寻址,相对于16位多了4位,因此采用分段来处理,也就是说在原来16位寻址的基础上增加了4位偏移量地址,从表现来说段地址都是低4位全0。然后它的真实地址是:段地址向左移动4位然后和偏移地址相加。
让我们回忆一下:
一个程序,系统怎样给他分配地址。一个程序代码区,一个数据存储区,一个堆栈
这就对应了段寄存器:CS,DS,SS,ES;那系统又是怎么分段的?它是将存储器地址分为很多块,称为段,每一段内包含有64k,很显然段地址就形成了,而这64k也就称为其偏移地址那么可以计算出原来的16位寻址+64k的寻址能力4位寻址一共是20位寻址.
cs该段含有要执行的代码指令集合;但是真正要执行的时候就需要CS的段地址+从*IP寄存器取得偏移量
ss堆栈存储器+SP栈指针寄存器 == 栈数据,BP是在SS中传送数据时保存 数据和栈偏移地址
ES主要存放于目的字符串
ES是一个附加的数据段,如用DS作为数据段段地址,SI作为源地址偏移,将一个字符串从源传送到目的区,这个目的区可设在附加段中DI寄存目的区的偏移地址,ES装附加段地址,DI寄存目的区地址的偏移 ,如果使用附加段,用户程序必须对ES初始化,即设置值,否则ES=DS。
存储器操作类型 约定的段寄存器 另外可用的段寄存器 偏移地址
取指令 CS IP
堆栈操作 SS SP
取数据或者变量 DS CS.ES.SS 有效地址
串操作中取源串 DS CS.ES.SS SI
串操作中写目的串 ES DI
BP被当做基地址 SS CS.ES.SS 有效地址
在包含了<dos.h>的情况下 ,我们可以对段地址和偏移地址以及存储的数据进行操作:
#include<dos.h>
#include<stdio.h>
mian()
{
char far* p;
unsigned seg,offset;
//整合段地址和偏移地址
p = MK_FP(oxb000,0x20);
//又从该整合的真实地址中取出段地址
seg = FP_SEG(p);
off = FP_OFF(p);
printf("far p %p,segment %04x,offset %0x",p,seg,off);
}
result: far p b0000,0020,segment b000,offset 0x20);
他们将写入或者获取一个字节或者一个字到所指出的地址中
char pokeb(unsigned segment,unsigned offset, char value);
int poke(unsigned segment,unsigned offset,int value);
char peekb(unsigned segment,unsigned offset);
int peek(unsigned segment,unsigned offset);