1.linux获取物理内存的方法
0xE820 方法1
总共有三种,我们只需要了解一种,因为它一般不会出错
2.注意
实际物理内存 和 检测出来的结果 之间总是相差1MB的,原因是因为有些老的ISA设备要用到地址15MB以上的内存作为缓冲区,也就是说此缓冲区的大小为1MB,操作系统不可以访问这段内存
3.代码
Total_Memory_Bytes dd 0 ;以字节形式表示的内存大小 存放在此处
MemoryBuf times 244 db 0 ; 获取到的全部的信息 存放在此处
ARDS_Count dw 0 ;获取到了几个ARDS结构
;/*******Loader_Start***********/
; /*******int 0x15 EAX=0x0000E820 ***/
Loader_Start:
MOV EBX, 0x0 ;ARDS的后续值 第一次必须为0
MOV EDX, 0x534d4150 ; 固定的签名标记
MOV DI, MemoryBuf ;ES:DI 的地址 存放获取到的信息
.E820_MemGetLoop: ;方法1的循环
MOV EAX, 0x0000E820 ; 功能号
MOV ECX, 0x14 ; 指定ARDS结构体的大小
INT 0x15 ;执行中断
JC .E820_Fail_Try_E801 ;若C位为1 用另外一种方式去读取
;若读取成功
Add DI, 0x14; ;偏移到下一个保存ARDS结构的位置
INC word [ARDS_Count] ;ARDS的个数++
CMP EBX, 0 ; EBX = 0 表示全部的读取 结束了
JNZ .E820_MemGetLoop ; 没结束 继续读取
;下面就是全部读取完成 判断出最大的那个内存
MOV CX, [ARDS_Count] ;
MOV EBX, MemoryBuf
MOV EDX, 0x0 ;EDX 保存最大的那个内存 先清0
.Find_Max_Memory:
MOV EAX, [EBX] ;BaseAddLow + LengthLow
ADD EAX, [EBX+8]
CMP EDX, EAX ; 比较前一次的最大值 和 这次的
JGE .Next_ARDS
MOV EDX, EAX ;EDX 保存了 Total Memory
.Next_ARDS:
ADD EBX, 0x14 ;继续判断下一个
LOOP .Find_Max_Memory
JMP .Memory_Get_OK ;比较完成了 跳转到OK
;/*******************************/
;/**********INT15 AX= 0xe801****/
.E820_Fail_Try_E801:
MOV AX, 0xe801
INT 0x15
JC .E801_Fail_Try_88 ;fail
;LOW 15MB
MOV CX, 0x400 ;1KB
MUL CX ;AX *= CX 高16位在DX中 低16位在AX中
SHL EDX, 16 ;*result High 16
AND EAX, 0x0000FFFF
OR EDX, EAX
ADD EDX, 0x10000 ;+1MB
MOV ESI, EDX
;MoreThan 16MB
MOV EAX, 0x0
MOV AX, BX
MOV ECX, 0x10000 ;64kb
MUL ECX
MOV EDX, ESI
JMP .Memory_Get_OK
;/****************************/
;/***********INT15 AX = 0x88**/
.E801_Fail_Try_88:
MOV AH, 0x88
INT 0x15
JC .Error_HLT ;Error
AND EAX, 0x0000FFFF
MOV CX, 0x400 ;1kb
MUL CX
SHL EDX, 16 ;result high 16
OR EDX, EAX
ADD EDX, 0x10000 ;1MB
;/****************************/
.Memory_Get_OK:
MOV [Total_Memory_Bytes], EDX
.Error_HLT:
HLT
4.获取到的内存的大小
可以看到获取到的内存的大小是32MB,和我们配置的环境一模一样