作为系统资源的管理者,操作系统需要知道系统的所有可用内存,这一般通过BIOS中断服务int 15h,AX=0xE820获得。
这个中断服务的资料请参见:
http://www.ctyme.com/intr/rb-1741.htm
http://wiki.osdev.org/Detecting_Memory_(x86)
这个中断调用的输入参数:
EAX=0E820h
EBX=(第一次调用时设为0,否则沿用BIOS返回的值)
ECX=可以存放内存表项的大小(字节),至少20,也可能是24
EDX=‘SMAP’(534D4150h)
ES:DI=存放内存表项的内存位置
返回参数:
进位标志CF=0成功,CF=1失败(AH为错误码)
EAX=‘SMAP’(534D4150h)
EBX=0获取完成,否则用于获取下一项
ECX=实际填充的字节数
ES:DI指向的内存被填充一个表项,其格式为
| 偏移 | 字节数 | 内容 |
| 0 | 8 | 内存区域首地址 |
| 8 | 8 | 内存区域大小(字节) |
| 16 | 4 | 内存区域类型(1为可用,其余为不可用) |
| 20 | 4 | (可能不返回)ACPI内存区域类型(参考ACPI规范) |
可以看到,调用这个中断服务需要用到32位寄存器。不用担心,386之后的CPU在实模式下也可使用32位寄存器的(这样的指令的机器码会有改变默认操作数大小的前缀0x66)。
但是获得的系统内存表可以放在什么内存位置呢,一般来说,现在的电脑的0x200到0x90000的内存都是可供操作系统使用的。电脑的0~0x1FF被实模式的中断向量表IVT占用。
关于实模式可寻址的低1MB内存的可用性(availability)及用途,可参考http://wiki.osdev.org/Memory_Map_(x86)
OSDEV论坛(http://f.osdev.org/viewtopic.php?f=1&t=7136)有人发现E820可能在极少数机器上不可用,这个时候我们可以学Windows那样用E881或E801作为后备方法。
int 15h, AX=0E801h: Phoenix BIOS v4.0 - GET MEMORY SIZE FOR >64M CONFIGURATIONS: http://www.ctyme.com/intr/rb-1739.htm
int 15h, AX=0E881h: Phoenix BIOS v4.0 - GET MEMORY SIZE FOR >64M CONFIGURATIONS (32-bit): http://www.ctyme.com/intr/rb-1742.htm