内存大小的检测

 

在上一篇中,我们已经实现了由引导程序加载FAT16系统上的引导装载程序。从现在开始我们将开始编写这个引导装载程序RMOSLDR。这个程序将由2部分组成。第一部分依然是一个汇编语言的程序。它将会把CPU切换到保护模式,并且设置C++的运行环境。而RMOSLDR的第二部分将由C++编写,这段C++代码将会负责把PE格式的操作系统内核从文件系统中加载到内存。

在编写这段程序之前,我们还是要先了解一下必要的背景知识。首先,我们要做的一件事是内存大小的检测。

在实模式下,我们可以通过BIOS来取得系统内存的大小。系统BIOS INT15功能一共提供了3种方式来读取内存大小。

方式一(88h):

这是最古老的BIOS功能之一,它将通过AX返回扩展内存的大小,以KB为单位。由于返回值在16位的AX寄存器中,当系统中的内存大于64MB的时候,这种方式最多只能返回64MB。更糟糕的是,由于这是一个古老的功能,在某些机器上BIOS最多只返回16MB内存。

使用这个方式的好处是,所有的机器都支持这个功能。

输入:
    AH    88h

输出:
    CF    置位表示出错
    AX    内存大小,以KB为单位


方式二(E801h):

这种方式可以返回多至4G的内存大小。但是这种方式通用性不如88h。在一些古老的机器上,BIOS并不支持这种方式。

输入:
    AX    E801h

输出:
    CF    置位表示出错
    AX    1MB-16MB空间的扩展内存大小,以KB为单位
    BX    16MB-4GB空间的扩展内存大小,以64K位单位
    CX    1MB-16MB空间的Configuration Memory(不知如何翻译)大小,以KB为单位
    DX    16MB-4GB空间的Configuration Memory(不知如何翻译)内存大小,以64K位单位

我不知道Configuraition Memory和扩展内存有什么区别,但是BIOS对它们返回一样的值。



方式三(E820h):

这个功能返回机器上安装的内存以及BIOS保留地址的映射表. 这个功能的调用方式和前两个不太一样。这个功能需要调用这调用多次。每次调用将返回一块被映射的内存空间。返回值表明了那块空间的起始地址和大小以及那块空间的类型(物理内存/BIOS保留)。


输入:
    EAX    E820h
    EBX    第一次调用时必须为0,后续调用必须将EBX设置成前一次的返回的EBX值
    ES:DI    缓冲区指针,返回的数据存放在这里
    ECX    缓冲区大小
    EDX    必须为字符串'SMAP'

输出:
    CF    置位表示错误
    EAX    字符串'SMAP'
    ES:DI    缓冲区指针,和输入一样
    ECX    缓冲区大小
    EBX    为下一次调用使用


返回的数据结构。
每次调用E820h功能时,BIOS将在缓冲区内填入一个数据结构,这个数据结构可以用下面的C++结构表示

#pragma pack(1)
struct
{
    DWORD64    baseAddress;  // 内存区域基地址
    DWORD64    size;         // 内存区域大小
    WORD       type;         // 内存类型, 1表示可用内存,2表示保留空间,其他值没有定义
};

我们可以看到,baseAddress和size都是64位的,也就是说这个功能最多可以报告2的64次方字节的内存。

在上面所说的3种方式中,我们可以看到,E820功能是最强大的。但是支持的机器也是最少的。不过幸好,近年来新出的机器都支持这个功能。我们接下来就打算用这个功能来报告系统中内存的大小。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值