内存管理的第一步是要知道内存的容量大小,也就是内存终了地址。检测内存容量的方法之一是从BIOS获取数据,但是使用BIOS的版本不同,获取的方式也大不相同。因此操作系统开发时采用另一种方法,就是检测内存地址是否有效。
首先,如果是486CPU,要先把缓存(Cache)屏蔽。为了提高CPU和内存之间数据交换的速度,CPU内的缓存会保留内存中刚被访问的数据。例如在CPU第一次访问0x18地址的数据54时,先会将54拷贝到缓存中,第二次访问0x18地址的数据时,就可以直接得到缓存中的54了。再例如for(i=0;i<100;i++)语句里的i的值被更新了100次,其实内存中的i值更新了1次,也就是第100次更新时,i才被写入内存,而前99次i的值只是在缓存里更新。
386时代,CPU内没有缓存,486时代,有8-16KB的缓存,性能就提高了6倍以上。缓存虽然可以提高性能,但给内存容量的检测带来了不便,内存容量检测可以用一下的方式:先在一个地址中写入一个数值,然后再读取,如果读取的数值和写入的相等,则表示有个地址是内存中的有效地址。但是如果CPU里有缓存,这个方法就无效了,因此我们事先要把CPU的缓存屏蔽。
屏蔽CPU缓存的程序如下:
#define EFLAGS_AC_BIT 0x00040000
#define CR0_CACHE_DISABLE 0x60000000
unsigned int memtest(unsigned int start,unsigned int end)
{
char flg486=0;
unsigned int eflg,cr0,i;
/*386 or 486*/
eflg=io_load_eflags();
eflg |= EFLAGS_AC_BIT; /*AC-bit=1,区分386和486*/
io_store_eflags(eflg);
eflg=io_load_eflags();
if((eflg & EFLAGS_AC_BIT)!=0){
flg486=1;
}
eflg&=~EFLAGS_AC_BIT; /*AC-bit=0*/
io_store_eflags(eflg);
if(flg486!=0){
cr0=load_cr0();/*是486,需要屏蔽缓存*/
cr0!=CR0_CACHE_DISABLE; /*ban cache*/
store_cr0(cr0);
}
i=memtest_sub(start,end);
if(flg486!=0){
cr0=load_cr0();
cr0&=~CR0_CACHE_DISABLE; /*cache permit*/
store_cr0(cr0);
}
return i;
}
其中
_load_cr0: ;int load_cr0(void)
mov eax,cr0
ret
_store_cr0: ;void store_cr0(int cr0);
mov eax,[esp+4]
mov cr0,eax
ret
函数unsigned int memtest_sub(unsigned int start,unsigned int end)完成内存容量的检测。start,end是要检测的初始地址和结束地址。循环检测该范围内的每个地址是否有效。检测的方式是:
1.把地址的值保存;
2.向该地址写入一个值;
3.取该地址值得异或(XOR);
4.如果取得的异或值与正确的不一致,则表示该地址无效,结束测试,返回循环次数;
如果一致,则去5;
5.再次取该值得异或,结果如果和原值不等,则去4;
如果值相等,则表示该地址有效,去6;
6.恢复该地址的值,继续检测下一个地址,去1。
注意,以上的测试方法如果用C语言实现,编译时,不能使用优化参数。因为GCC编译器会认为1,2,3,4,5步都是冗余操作,自作主张的把它删掉。最后会变成只循环,不做任何处理。为了避免GCC的优化处理,本文使用汇编来实现。每次检测0x1000(4KB)个地址。
_memtest_sub: ;unsigned int memtest_sub(unsigned int start,unsigned int end)
push edi ;
push esi
push ebx
mov esi,0xaa55aa55 ;pat0=0xaa55aa55;
mov edi,0x55aa55aa ;pat1=0x55aa55aa;
mov eax,[esp+12+4] ;i=start;
mts_loop:
mov ebx,eax
add ebx,0xffc ;p=i+0xffc,检测末尾4个Bytes的地址。
mov edx,[ebx] ;old=*p;
mov [ebx],esi ;*p=pat0;
xor dword [ebx],0xffffffff ;*p^=0xffffffff; 异或
cmp edi,[ebx] ;if(*p!=pat1) goto fin; 不等则是无效
jne mts_fin
xor dword [ebx],0xffffffff; *p^=0xffffffff; 异或
cmp esi,[ebx] ;if(*p!=pat0) goto fin; 不等则是无效
jne mts_fin
mov [ebx],edx ;*p=old; 有效,继续下4KB地址的检测
add eax,0x1000 ;i+=0x1000;
cmp eax,[esp+12+8]
jbe mts_loop
pop ebx
pop esi
pop edi
ret
mts_fin:
mov [ebx],edx ;*p=old;
pop ebx
pop esi
pop edi
ret
检测结果显示:
在bootpack.c中加入如下语句:
i=memtest(0x00400000,0xbfffffff)/(1024*1024); /*检测范围为3GB,结果以兆为单位*/
sprintf(s,"memory %dmb",i);
drawstring(binfo->vram, binfo->scrnx,10, binfo->scrny-50, COL8_FFFFFF, s);
如图:
<shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></path><lock aspectratio="t" v:ext="edit"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 270pt; HEIGHT: 177.75pt" type="#_x0000_t75"><imagedata o:title="" src="file:///C:%5CDOCUME~1%5C%E8%B6%99%E7%A3%8A%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.png"></imagedata></shape>
为什么只有32MB?
因为虚拟机QEMU设定了内存的大小
qemu.exe -L . -m 32 -localtime -std-vga -fda boot.bin
将32改为64后,运行结果则为:
<shape id="_x0000_i1026" style="WIDTH: 270pt; HEIGHT: 177.75pt" type="#_x0000_t75"><imagedata o:title="" src="file:///C:%5CDOCUME~1%5C%E8%B6%99%E7%A3%8A%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image003.png"></imagedata></shape>
分享到:
相关推荐
以上知识点涵盖了从操作系统的基本概念到具体实现细节的多个方面,对于理解操作系统的工作原理和开发实践具有重要意义。通过深入研究这些知识点,可以帮助学生更好地掌握操作系统的设计与开发技能。
统信操作系统互认测试报告模板是用来评估和验证统信操作系统(UOS)与其他软硬件产品兼容性和互操作性的标准化文档。这份报告旨在确保统信操作系统能够无缝地与各种产品协同工作,提供稳定、高效和安全的用户体验。...
在Windows CE操作系统中,内存管理是其核心功能之一,尤其对于需要处理大量数据或运行大型应用的设备,分配大容量内存是一项挑战。由于Windows CE(简称WCE)的设计特性,每个进程默认拥有32MB的私有地址空间,并且...
内存管理是操作系统的核心功能之一。`GlobalMemoryStatusEx`或`GetPerformanceInfo` API能够提供系统的总内存、已用内存、空闲内存以及交换空间等详细信息。这些信息对于分析系统性能、内存泄漏检测至关重要。 3. ...
内存管理机制是嵌入式系统研究...本文以开源的嵌入式操作系统RTEMS为例,分析了嵌入式系统内存管理所面临的问题,研究了其底层实现的解决方案。一般的嵌入式系统中最基本的内存管理方案有两种——静态分配和动态分配。
内存管理是操作系统设计的核心部分之一,涉及内存分配、释放、保护等多个方面。 - **动态内存分配**:在操作系统中,动态内存分配通常通过堆栈(stack)和堆(heap)来实现。堆栈用于存储函数调用时的局部变量和...
本篇文章将详细讲解如何利用C++编程语言在Windows XP操作系统上获取CPU、内存大小、硬盘空间、操作系统版本、打印机名称以及显卡名称等关键系统信息。 首先,获取CPU信息通常涉及读取性能计数器(Performance ...
1. **操作系统详情**:包括操作系统名称、版本、内核版本、架构等,帮助用户识别当前运行的操作系统环境。 2. **进程信息**:展示正在运行的进程列表,包括进程ID、名称、状态、CPU和内存使用情况等,这对于系统性能...
易语言是一种专为中国人设计的编程语言,它以简体中文...通过学习和使用这个压缩包中的源码,开发者不仅可以掌握易语言的基本用法,还能深入理解操作系统内存管理的机制,对于提高编程技能和解决实际问题具有积极意义。
1. 进程管理:操作系统如何创建、调度、同步和通信进程,以及处理进程间的相互制约关系。这涉及到进程的状态转换、调度算法(如FCFS、SJF、优先级调度、多级反馈队列等)以及死锁的预防和检测。 2. 内存管理:包括...
操作系统是计算机系统的核心组成部分,它管理着系统的硬件资源和软件资源,为用户提供高效、便捷的服务。本篇复习笔记主要涵盖了操作系统...通常,使用高级编程语言编写操作系统,可以降低开发难度,增强跨平台兼容性。
操作系统是计算机科学中的核心课程,它管理着计算机的硬件资源,包括内存、处理器以及输入输出设备,为用户提供高效、安全的环境。这份"20操作系统课件.zip"包含的资源显然是针对操作系统课程的教学材料,主要涵盖了...
虚拟内存技术则允许程序使用超过物理内存容量的地址空间,通过磁盘交换来实现。 在实验中,你可能会设计一个简单的内存管理系统,实现诸如最佳适配、最差适配、首次适配等内存分配策略,并考虑内存碎片问题。同时,...
操作系统是计算机科学中的核心组成部分,它管理着计算机的硬件资源,并为用户提供服务,使得软件开发和使用变得更为简便。"os操作系统原理.rar"这个压缩包文件显然包含了关于操作系统原理的详细资料,很可能是PPT...
- **分类**:根据不同的标准,操作系统可以分为批处理系统、分时系统、实时系统、网络操作系统和个人操作系统等多种类型。 #### 二、操作系统的主要功能 - **处理机管理**:包括进程控制、调度算法的选择与实施、...
操作系统使计算机更易于使用,允许以更有效的方式使用计算机系统资源,並在构造操作系统时,应该允许在不妨碍服务的前提下有效地开发、测试和引进新的系统功能。 操作系统概述 操作系统的内核是操作系统最常使用的...
DOS(Disk Operating System,磁盘操作系统)是个人计算机上早期广泛使用的一种操作系统,由微软公司为IBM PC及其兼容机开发。DOS以其简洁的命令行界面和对硬件的直接控制能力,在20世纪80年代至90年代初期占据了...
从给定的文件信息中,我们可以提取并生成一系列与操作系统相关的知识点,具体如下: ### 操作系统概述 操作系统是计算机系统中的核心软件,它管理和控制计算机硬件与软件资源,为其他应用程序提供服务。根据其作用...