利用0E820h int 15h 中断获取内存信息********
利用0E820h int 15h 中断获取内存信息
; 得到内存数 //这段代码是在实模式下写的。
mov ebx, 0
mov di, _MemChkBuf
.loop:
mov eax, 0E820h
mov ecx, 20
mov edx, 0534D4150h
int 15h
jc LABEL_MEM_CHK_FAIL //如果产生进位,则跳转。 产生进位表示没有成功。
add di, 20
inc dword [_dwMCRNumber]
cmp ebx, 0 //ebx存放的是下一个ARDS的偏移量,第一个是0,如果ebx重新变为0,说明已经到最后一个ARDS了,遍历结束了。
jne .loop //这样[_dwMCRNumber]就是存放的ARDS的个数。ARDS是地址范围描述符结构,一个ARDS是20个字节。
jmp LABEL_MEM_CHK_OK
LABEL_MEM_CHK_FAIL:
mov dword [_dwMCRNumber], 0 //注意这是在实模式下,所以使用的实地址模式。在32位保护模式下就只能使用偏移地址模式。
LABEL_MEM_CHK_OK: //_这个符号就表示是实模式下的实地址。
~~~~~~~
------------------------------------------------------------------------------------------------------------------
; 实模式下使用这些符号
; 字符串
_szPMMessage: db "In Protect Mode now. ^-^", 0Ah, 0Ah, 0 ; 进入保护模式后显示此字符串
_szMemChkTitle: db "BaseAddrL BaseAddrH LengthLow LengthHigh Type", 0Ah, 0 ; 进入保护模式后显示此字符串
_szRAMSize db "RAM size:", 0
_szReturn db 0Ah, 0
; 变量
_wSPValueInRealMode dw 0
_dwMCRNumber: dd 0 ; Memory Check Result
_dwDispPos: dd (80 * 6 + 0) * 2 ; 屏幕第 6 行, 第 0 列。
_dwMemSize: dd 0
_ARDStruct: ; Address Range Descriptor Structure
_dwBaseAddrLow: dd 0
_dwBaseAddrHigh: dd 0
_dwLengthLow: dd 0
_dwLengthHigh: dd 0
_dwType: dd 0
_MemChkBuf: times 256 db 0
; 保护模式下使用这些符号
szPMMessage equ _szPMMessage - $$
szMemChkTitle equ _szMemChkTitle - $$
szRAMSize equ _szRAMSize - $$
szReturn equ _szReturn - $$
dwDispPos equ _dwDispPos - $$
dwMemSize equ _dwMemSize - $$
dwMCRNumber equ _dwMCRNumber - $$
ARDStruct equ _ARDStruct - $$
dwBaseAddrLow equ _dwBaseAddrLow - $$
dwBaseAddrHigh equ _dwBaseAddrHigh - $$
dwLengthLow equ _dwLengthLow - $$
dwLengthHigh equ _dwLengthHigh - $$
dwType equ _dwType - $$
MemChkBuf equ _MemChkBuf - $$
-------------------------------------------------------------------------------------------------
32位保护模式下的代码:
; 下面显示一个字符串
push szPMMessage
call DispStr
add esp, 4
push szMemChkTitle
call DispStr
add esp, 4
call DispMemSize ; 显示内存信息
call SetupPaging ; 启动分页机制
; 到此停止
jmp SelectorCode16:0
----------------------------------
DispMemSize:
push esi
push edi
push ecx
mov esi, MemChkBuf
mov ecx, [dwMCRNumber] ; for(int i=0;i<[MCRNumber];i++) // 每次得到一个ARDS(Address Range Descriptor Structure)结构
.loop: ; {
mov edx, 5 ; for(int j=0;j<5;j++) // 每次得到一个ARDS中的成员,共5个成员
mov edi, ARDStruct ; { // 依次显示:BaseAddrLow,BaseAddrHigh,LengthLow,LengthHigh,Type的数据,并放到一个ARDS中
.1: ;
push dword [esi] ; //注意Dword是32位,就是把esi所指向的32位,4字节数据压入栈
call DispInt ; DispInt(MemChkBuf[j*4]); 显示一个成员即分别显示一个ARDS的0,4,8,12,16为起点的4个字节的数据
pop eax ;
stosd ; ARDStruct[j*4] = MemChkBuf[j*4];
add esi, 4 ;
dec edx ;
cmp edx, 0 ;
jnz .1 ; } //内循环重复执行五次,依次打印出一个ARDS的5个数据
call DispReturn ; printf("\n"); //然后打印换行
cmp dword [dwType], 1 ; if(Type == AddressRangeMemory) // AddressRangeMemory : 1, AddressRangeReserved : 2
jne .2 ; {
mov eax, [dwBaseAddrLow] ;
add eax, [dwLengthLow] ;
cmp eax, [dwMemSize] ; if(BaseAddrLow + LengthLow > MemSize)
jb .2 ;
mov [dwMemSize], eax ; MemSize = BaseAddrLow + LengthLow;
.2: ; }
loop .loop ; }
;
call DispReturn ;printf("\n");
push szRAMSize ;
call DispStr ;printf("RAM size:");
add esp, 4 ;
;
push dword [dwMemSize] ;
call DispInt ;DispInt(MemSize);
add esp, 4 ;
pop ecx
pop edi
pop esi
ret