32 获取物理内存容量 下

参考

https://blog.51cto.com/13475106/category6.html及狄泰软件相关课程

获取物理内存容量

上面介绍的是基础功能,这里介绍的是高级功能操作系统-获取物理内存容量
参数的设置
操作系统-获取物理内存容量
edx是bios所需要的值,不做深究
地址范围描述结果(ARDS)
操作系统-获取物理内存容量操作系统-获取物理内存容量

代码实验

%include "inc.asm"

org 0x9000

jmp ENTRY_SEGMENT

[section .gdt]

; GDT definition

;                                     段基址,           段界限,       段属性

GDT_ENTRY       :     Descriptor        0,                0,           0

CODE32_DESC     :     Descriptor        0,        Code32SegLen - 1,    DA_C + DA_32

VIDEO_DESC      :     Descriptor     0xB8000,         0x07FFF,         DA_DRWA + DA_32

DATA32_DESC     :     Descriptor        0,        Data32SegLen - 1,    DA_DRW + DA_32

STACK32_DESC    :     Descriptor        0,         TopOfStack32,       DA_DRW + DA_32

; GDT end

GdtLen    equ   $ - GDT_ENTRY

GdtPtr:

          dw   GdtLen - 1

          dd   0

; GDT Selector

Code32Selector   equ (0x0001 << 3) + SA_TIG + SA_RPL0

VideoSelector    equ (0x0002 << 3) + SA_TIG + SA_RPL0

Data32Selector   equ (0x0003 << 3) + SA_TIG + SA_RPL0

Stack32Selector  equ (0x0004 << 3) + SA_TIG + SA_RPL0

; end of [section .gdt]

TopOfStack16    equ 0x7c00

[section .dat]

[bits 32]

DATA32_SEGMENT:

    DTOS               db  "D.T.OS!", 0

    DTOS_OFFSET        equ DTOS - $$

    HELLO_WORLD        db  "Hello World!", 0

    HELLO_WORLD_OFFSET equ HELLO_WORLD - $$

Data32SegLen equ $ - DATA32_SEGMENT

;

MEM_SIZE              times    4      db  0

MEM_ARDS_NUM          times    4      db  0      ; int mem_ards_num = 0;

MEM_ARDS              times 64 * 20   db  0 

[section .s16]

[bits 16]

ENTRY_SEGMENT:

    mov ax, cs

    mov ds, ax

    mov es, ax

    mov ss, ax

    mov sp, TopOfStack16

    ; get InitSysMemBuf  infomation

    call InitSysMemBuf

    ; initialize GDT for 32 bits code segment

    mov esi, CODE32_SEGMENT

    mov edi, CODE32_DESC

    call InitDescItem

    mov esi, DATA32_SEGMENT

    mov edi, DATA32_DESC

    call InitDescItem

    mov esi, STACK32_SEGMENT

    mov edi, STACK32_DESC

    call InitDescItem

    ; initialize GDT pointer struct

    mov eax, 0

    mov ax, ds

    shl eax, 4

    add eax, GDT_ENTRY

    mov dword [GdtPtr + 2], eax

    ; 1. load GDT

    lgdt [GdtPtr]

    ; 2. close interrupt

    cli 

    ; 3. open A20

    in al, 0x92

    or al, 00000010b

    out 0x92, al

    ; 4. enter protect mode

    mov eax, cr0

    or eax, 0x01

    mov cr0, eax

    ; 5. jump to 32 bits code

    jmp dword Code32Selector : 0

; esi    --> code segment label

; edi    --> descriptor label

InitDescItem:

    push eax

    mov eax, 0

    mov ax, cs

    shl eax, 4

    add eax, esi

    mov word [edi + 2], ax

    shr eax, 16

    mov byte [edi + 4], al

    mov byte [edi + 7], ah

    pop eax

    ret

;

;

GetMemSize:

    push eax

    push ebx

    push ecx

    push edx

    mov dword [MEM_SIZE], 0

    xor eax, eax

    mov eax, 0xE801

    int 0x15

    jc geterr

    shl eax, 10   ; eax = eax * 1024;

    shl ebx, 6    ; ebx = ebx * 64;

    shl ebx, 10   ; ebx = ebx * 1024;

    mov ecx, 1

    shl ecx, 20   ; ecx = 1MB

    add dword [MEM_SIZE], eax

    add dword [MEM_SIZE], ebx

    add dword [MEM_SIZE], ecx

    jmp getok

geterr:

    mov dword [MEM_SIZE], 0

getok:

    pop edx

    pop ecx

    pop ebx

    pop eax

    ret

; return 

;    eax  --> 0 : succeed      1 : failed

InitSysMemBuf: 

     push edi

     push ebx

     push ecx

     push edx

     mov edi, MEM_ARDS

     mov ebx, 0

memerr:

     mov dword [MEM_ARDS_NUM], 0

     mov eax, 1

doloop:

     mov eax, 0xE820

     mov edx, 0x534D4150

     mov ecx, 20

     int 0x15

     jc memerr

     add edi, 20

     inc dword [MEM_ARDS_NUM]

     cmp ebx, 0

     jne doloop

     mov eax,0

     jmp memok

memok:   

     pop edx

     pop ecx

     pop ebx

     pop edi

     ret

[section .s32]

[bits 32]

CODE32_SEGMENT:   

    mov ax, VideoSelector

    mov gs, ax

    mov ax, Stack32Selector

    mov ss, ax

    mov eax, TopOfStack32

    mov esp, eax

    mov ax, Data32Selector

    mov ds, ax

    mov ebp, DTOS_OFFSET

    mov bx, 0x0C

    mov dh, 12

    mov dl, 33

    call PrintString

    mov ebp, HELLO_WORLD_OFFSET

    mov bx, 0x0C

    mov dh, 13

    mov dl, 31

    call PrintString

    jmp $

; ds:ebp    --> string address

; bx        --> attribute

; dx        --> dh : row, dl : col

PrintString:

    push ebp

    push eax

    push edi

    push cx

    push dx

print:

    mov cl, [ds:ebp]

    cmp cl, 0

    je end

    mov eax, 80

    mul dh

    add al, dl

    shl eax, 1

    mov edi, eax

    mov ah, bl

    mov al, cl

    mov [gs:edi], ax

    inc ebp

    inc dl

    jmp print

end:

    pop dx

    pop cx

    pop edi

    pop eax

    pop ebp

    ret

Code32SegLen    equ    $ - CODE32_SEGMENT

[section .gs]

[bits 32]

STACK32_SEGMENT:

    times 1024 * 4 db 0

Stack32SegLen equ $ - STACK32_SEGMENT

TopOfStack32  equ Stack32SegLen - 1

 

操作系统-获取物理内存容量

结果分析

首先通反编译找到函数的调用地址,然后对该处设置地址,同时也对下个地址进行设置,同时打上断点,通过书写的函数,找到所需查看的地址,如下图所示
操作系统-获取物理内存容量操作系统-获取物理内存容量操作系统-获取物理内存容量操作系统-获取物理内存容量
首先查看全局函数0x904d的内存,发下为0是我们所需的结果,查看寄存器eax寄存器为0,说明调用成功,再次查看0x904d发现其为6,这次需要查看数组前六个元素,通过数组地址0x9051,发现其有起始地址,长度,类型,通过打印六次之后,所打印的结果为0,说明得到内存信息
操作系统-获取物理内存容量操作系统-获取物理内存容量操作系统-获取物理内存容量

 

原文地址:https://www.cnblogs.com/lh03061238/p/14439588.html