本文介绍三种探测内存的方法
探测内存是通过调用 BIOS 中断 0x15 实现的
分别 是 BIOS 中断 0x15 的 3 个子功能
- EAX=OxE820:遍历主机上全部内存。
- AX =OxE801: 分别检测低15MB和 16MB~4GB 的内存,最大支持 4GB。
- AH=Ox88:最多检测出 64MB 内存,实际内存超过此容量也按照 64MB 返回。
一、利用 BIOS 中断 Ox15 子功能 0xE820 获取内存
INT15h BIOS 中断的详细调用参数:
eax:e820h:INT 15 的中断调用参数;
edx:534D4150h (即 4 个 ASCII 字符―SMAP‖) ,这只是一个签名而已;
ebx:如果是第一次调用或内存区域扫描完毕,则为 0。 如果不是,则存放上次调用之后的计数值;
ecx:保存地址范围描述符的内存大小,应该大于等于 20 字节;
es:di:指向保存地址范围描述符结构的缓冲区,BIOS 把信息写入这个结构的起始地址。
此中断的返回值为:
cflags 的 CF 位:若 INT 15 中断执行成功,则不置位,否则置位;
eax:534D4150h ('SMAP') ;
es:di:指向保存地址范围描述符的缓冲区,此时缓冲区内的数据已由 BIOS 填写完毕
ebx:下一个地址范围描述符的计数地址
ecx :返回 BIOS 往 ES:DI 处写的地址范围描述符的字节大小
ah:失败时保存出错代码
通过调用 INT 15h BIOS 中断,递增 di 的值(20 的倍数),让 BIOS 帮我们查找出一个一个的内存布局 entry,并放入到一个 保存 地址范围描述符(见文章 INTEL基础结构) 结构的缓冲区中,供后续使用.
struct e820map {
int nr_map;
struct {
long long addr;
long long size;
long type;
} map[E820MAX];
};
probe_memory:
movl $0, 0x8000
xorl %ebx, %ebx
movw $0x8004, %di
start_probe:
movl $0xE820, %eax
movl $20, %ecx
movl $SMAP, %edx
int $0x15
jnc cont
movw $12345, 0x8000
jmp finish_probe
cont:
addw $20, %di
incl 0x8000
cmpl $0, %ebx
jnz start_probe
finish_probe:
二、利用 BIOS 中断0x15 子功能 0xE801 获取内存
三、利用 BIOS 中断 0x15 子功能 0x88 获取内存
最后一个获取内存的方法也同样是 BIOS 0x15 中断,子功能号是 0x88。
该方法使用最简单,但功能也最简单,简单到只能识别最大 64MB的内存。即使内存容量大于 64MB,也只会显示 63MB。因为此中断只会显示 1MB 之上的内存,不包括1MB。在使用的时候记得加上 1M.
网友评论