BIOS功能e820始终返回相同的结果

时间:2016-06-07 10:33:50

标签: c gcc assembly x86 osdev

我一直在使用我的操作系统。要检测内存映射,我使用BIOS函数e820但它总是返回相同的值。

我首先在Assembly中编写代码,我实际上是从OSDev wiki复制的,所以我确信代码中没有错误,然后通过指向ES:DI的指针将代码连接到C代码。这是我的汇编代码:

mov bx,7c4h;  Starting address of memory map array
mov es,bx;
mov di,0h;

; use the INT 0x15, eax= 0xE820 BIOS function to get a memory map
; inputs: es:di -> destination buffer for 24 byte entries
; outputs: bp = entry count, trashes all registers except esi

do_e820:
    xor ebx, ebx        ; ebx must be 0 to start
    xor bp, bp      ; keep an entry count in bp
    mov edx, 0x0534D4150    ; Place "SMAP" into edx
    mov eax, 0xe820
    mov [es:di + 20], dword 1   ; force a valid ACPI 3.X entry
    mov ecx, 24     ; ask for 24 bytes
    int 0x15
    jc short .failed    ; carry set on first call means "unsupported function"
    mov edx, 0x0534D4150    ; Some BIOSes apparently trash this register?
    cmp eax, edx        ; on success, eax must have been reset to "SMAP"
    jne short .failed
    test ebx, ebx       ; ebx = 0 implies list is only 1 entry long (worthless)
    je short .failed
    jmp short .jmpin
.e820lp:
    mov eax, 0xe820     ; eax, ecx get trashed on every int 0x15 call
    mov [es:di + 20], dword 1   ; force a valid ACPI 3.X entry
    mov ecx, 24     ; ask for 24 bytes again
    int 0x15
    jc short .e820f     ; carry set means "end of list already reached"
    mov edx, 0x0534D4150    ; repair potentially trashed register
.jmpin:
    jcxz .skipent       ; skip any 0 length entries
    cmp cl, 20      ; got a 24 byte ACPI 3.X response?
    jbe short .notext
    test byte [es:di + 20], 1   ; if so: is the "ignore this data" bit clear?
    je short .skipent
.notext:
    mov ecx, [es:di + 8]    ; get lower uint32_t of memory region length
    or ecx, [es:di + 12]    ; "or" it with upper uint32_t to test for zero
    jz .skipent     ; if length uint64_t is 0, skip entry
    inc bp          ; got a good entry: ++count, move to next storage spot
    add di, 24
.skipent:
    test ebx, ebx       ; if ebx resets to 0, list is complete
    jne short .e820lp
.e820f:
    mov [memMapLength], bp  ; store the entry count
    clc         ; there is "jc" on end of list to this point, so the carry must be cleared
    jmp .done
.failed:
    ;stc            ; "function unsupported" error exit 
    hlt
    ret
.done:  

我的代码继续并设置IDT和GDT然后切换到保护模式。这是C代码:

short memMapLength=0;
unsigned long availableMemBytes=0;

typedef struct memoryMapEntry{
    unsigned int baseLow;
    unsigned int baseHigh;
    unsigned long length;   
    unsigned int type;
    unsigned int acpi_null; 
    } memoryMapEntry;

memoryMapEntry* memMapArr=0; 

void DetectMem(){
    memMapArr= (memoryMapEntry*)(0x00007c40);
    int i;
    for(i=0;i<memMapLength;i++){
            if(memMapArr[i].type==1){           
                availableMemBytes += memMapArr[i].length;               
            }               
    }
}

在Assembly中,我将返回缓冲区地址ES:DI设置为0x7c4:0,并通过指向0x00007c40在C中捕获它。这可能是错的吗?当我将程序集和C与objconv组合在一起并在NASM中将它们编译为二进制时,生成的内核告诉我在VirtualBox上运行时有1个字节的可用内存。我该如何解决我的问题?有什么建议吗?

0 个答案:

没有答案