int 0x15 探测内存

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,并放入到一个 保存 地址范围描述符 结构的缓冲区中,供后续.
struct e820map {
int nr_map;
struct {
long long addr;
long long size;
long type;
} map[E820MAX];
};

probe_memory:
//对 0x8000 处的 32 位单元清零,即给位于 0x8000 处的
//struct e820map 的结构域 nr_map 清零
movl $0, 0x8000
xorl %ebx, %ebx
//表示设置调用 INT 15h BIOS 中断后,BIOS 返回的映射地址描述符的起始地址
movw $0x8004, %di
start_probe:
movl $0xE820, %eax // INT 15 的中断调用参数
//设置地址范围描述符的大小为 20 字节,其大小等于 struct e820map 的结构域 map 的大
小
movl $20, %ecx
//设置 edx 为 534D4150h (即 4 个 ASCII 字符“SMAP”),这是一个约定
movl $SMAP, %edx
//调用 int 0x15 中断,要求 BIOS 返回一个用地址范围描述符表示的内存段信息
int $0x15
//如果 eflags 的 CF 位为 0,则表示还有内存段需要探测
jnc cont
//探测有问题,结束探测
movw $12345, 0x8000
jmp finish_probe
cont:
//设置下一个 BIOS 返回的映射地址描述符的起始地址
addw $20, %di
//递增 struct e820map 的结构域 nr_map
incl 0x8000
//如果 INT0x15 返回的 ebx 为零,表示探测结束,否则继续探测
cmpl $0, %ebx
jnz start_probe
finish_probe :

上述代码正常执行完毕后,在 0x8000 地址处保存了从 BIOS 中获得的内存分布信息,此信息按照 struct e820map 的设置来进行填充。这部分信息将在 bootloader 启动 ucore 后,由ucore 的 page_init 函数来根据 struct 820map 的 memmap(定义了起始地址为 0x8000)来完成对整个机器中的物理内存的总体管理。

你可能感兴趣的:(int 0x15 探测内存)