赞
踩
机器启动后有2种方式探测物理内存:直接探测、通过BIOS中断探测。
这里我们关注如何通过BIOS的0x15中断探测物理内存。
由于BIOS中断需要在实模式下调用,所以我们在bootloader中探测物理内存比较合适。
BIOS的0x15中断有3个子功能:e820h、e801h、88h。这三个子功能区别是:
这是功能最强大的子功能,使用也最复杂。
系统内存分为很多内存块,这些内存块加起来才构成系统的总内存。而这些内存块有不同的类型:有的OS可以使用、有的OS不能使用。
每次调用这个中断都会得到一块内存的描述,要通过多次调用才能得到系统所有内存块的描述。
e820将物理内存探测的结果以地址范围描述符的格式放在内存中。地址范围描述符共计20字节,格式是:
字节范围 | 描述 |
---|---|
0~7 | 内存块基地址 |
8~15 | 这块内存的大小 |
16~20 | 这块内存的类型 |
我们将在内存中开辟一个数组来存放所有地址范围描述符。
在c语言中可以这样定义:
struct {
uint64_t addr;
uint64_t size;
uint32_t type;
};
显然在保护模式下用int $0x15
来调用15h中断。
但在这之前我们要将参数放置在寄存器中:
int $0x15
,ebx会加1。当ebx为0表示所有内存块检测完毕。(重要!看后面的案例会明白如何使用)中断的返回值如下:
约定在bootloader中将内存探测结果放到0x8000地址处。
数据存放的格式在c中定义了:
struct e820map {
int nr_map; // 表示数组元素个数,该字段是为了方便后续OS,不是BIOS访问的
struct {
uint64_t addr;
uint64_t size;
uint32_t type;
} map[E820MAX];
};
通过int $0x15
调用中断。如果发生错误,CF位为1。那么可以尝试使用其它子功能进行探测,或者就直接关机(连内存容量都没探测肯定无法启动OS了)
根据ebx判断是否完成所有内存块的探测,如果没有则继续int $0x15
探测下一个内存块,如此反复直到所有内存块探测完毕。
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。