通过循环遍历指针数组来访问内存位置会返回不需要的结果 - osdev

时间:2017-05-18 07:26:54

标签: c arrays pointers kernel osdev

我正在为我的操作系统开发物理内存管理器。所以,为了获得内存映射,我使用BIOS int 0x15,eax = 0xE820中断来获取内存映射。我将地图存储在一个位置(0x7e00),然后遍历每个条目并尝试将其存储在C结构数组中。但它在循环中不起作用。

包含内存管理器代码的文件是 -

physmm.h

#ifndef __PHYSMM_H
#define __PHYSMM_H

#include <stdint.h>

#define NUM_REGIONS 10

// Structure defining a type to store Memory Map Entry
typedef struct {
    uint32_t base;
    uint32_t length;
    uint32_t type;
    uint32_t ext_attr;
}mmap_t;

mmap_t* physmm_mmap;

uint32_t mem_blocks[NUM_REGIONS];

uint32_t memoryKB;
uint16_t memoryMB;

void get_mem_details();

void initialize_physmm();

void set_block(uint8_t block_num, uint8_t region);
void clear_block(uint8_t block_num, uint8_t region);

uint8_t* malloc();
uint8_t* dump(uint8_t* block);

#endif

physmm.c

#include "physmm.h"

void get_mem_details(){
    if(*((uint8_t*) 0x4ff)==0xff){
        printC("Memory Not Recognized!!", 0x1c);
        return;
    }
    uint16_t conmB =  *((uint16_t*) 0x500);
    uint16_t extmB =  *((uint16_t*) 0x502);
    uint32_t mem1to16 = *((uint32_t*) 0x504);
    uint32_t memgreater16 = *((uint32_t*) 0x508);

    memoryKB = conmB/1024 + extmB/1024 + mem1to16 + memgreater16*64;
    memoryMB = memoryKB/1024;
}

void initialize_physmm(){
    uint16_t i=0, j=0;
    uint64_t y = 0;

    uint16_t no_of_regions = *((uint16_t*)0x50c);

    get_mem_details();

    for(i=0;i<NUM_REGIONS;i++)
    {
        mem_blocks[i] = 0xffffffff;
    }

    uint8_t* entry = (uint8_t*) 0x7e00;

    j=0;
    for(i=0; i < no_of_regions ; i++){
        physmm_mmap[i].base = (uint32_t) entry[j];
        physmm_mmap[i].length = (uint32_t) entry[j+8];
        physmm_mmap[i].type = (uint32_t) entry[j+16];
        physmm_mmap[i].ext_attr = (uint32_t) entry[j+20];
        j += 24;
    }

    for(i=0;i < no_of_regions;i++){
        printfNum(physmm_mmap[i].base, 16);
        printfNum(physmm_mmap[i].length, 16);
        printfNum(physmm_mmap[i].type, 16);
    }
}

这为基数和长度返回零,但可能返回类型的正确值。 当我使用uint32_t* entry指针时,它甚至不会返回type的正确值。返回一些不需要的数字(可能接近地址0x7e00但指向错误)。

我将内存映射存储在0x7e00位置。 如果我逐个手动添加指针的值并存储该值,则会得到正确的值。因此,内存映射位于正确的位置。

根据我的说法,我无法将entry指针指向内存中的正确位置。 任何人都可以帮我解决代码吗?

修改

第1阶段引导程序 -

[org 0x7c00]

mov [BOOT_DRIVE], dl
mov [0x7fe], byte dl

STAGE2 equ 0x800

STAGE2_SECTORS equ 2+1
TRACKS equ 2

mov [BOOT_DRIVE],dl

mov bp,0x9000
mov sp,bp

mov bx, msgReal
call print_string

call load_stage2

call STAGE2

jmp $

%include 'boot/bios.ASM'

[bits 16]
load_stage2:
    mov bx, msgStage2
    call print_string
    mov cl, 2
    mov bx, STAGE2
    mov dh, 1
    mov dl, [BOOT_DRIVE]
load_sector:
    call disk_load
    cmp cl, STAGE2_SECTORS
    je loaded
    cmp cl, 15
    add cl, 1
    add bx, 512
    jmp load_sector
loaded:
    ret

BOOT_DRIVE db 0
msgReal db "Booted in 16-bit mode",0
msgStage2 db "Loading the stage2 boot loader onto memory",0

times 510-($-$$) db 0
dw 0xaa55

第2阶段引导加载程序代码 -

[org 0x800]

KERNEL equ 0x1000
KERNEL_SECTORS equ 25

mov dl, byte[0x7fe]
mov [BOOT_DRIVE], dl

mov bx, msgStage2
call print_string

call load_kernel

mov bx, msg
call print_string

mov [0x4ff], byte 0x00

int 0x12
jc memError
mov [0x500], ax

clc
mov ah, 0x88
int 0x15
jc memError
mov [0x502], ax

xor cx, cx
xor dx, dx
mov eax, 0x0000E801
int 0x15
jc memError
cmp ah, 0x86
je memError
cmp ah, 0x80
je memError
jcxz useax
mov eax, ecx
mov ebx, edx
useax:
mov [0x504], eax
mov [0x508], ebx

jmp memDone

memError:
    mov [0x4ff], byte 0xff

memDone:

mov bx, 0x7e0
mov es, bx
mov di, 0x0
call do_e820
mov bx, bp
mov [0x50C], bx

call switch_to_pm

%include 'boot/bios.ASM'

%include 'boot/gdt.ASM'
%include 'boot/protected_mode.ASM'
%include 'boot/print32.ASM'

[bits 16]

load_kernel:
    mov bx, msgKernel
    call print_string
    mov ax, 3
    mov cl, 4
    mov ch, 0
    mov bx, KERNEL
    mov dl, [BOOT_DRIVE]
    mov dh, 0
    mov ch, 0
load_sector:
    mov ah, 0x02
    mov al, 1
    int 0x13
    jc error1
    cmp al, 1
    jne error2
    push bx
    mov bl, [Sector]
    cmp bl, KERNEL_SECTORS
    pop bx
    je loaded
    push bx
    mov bl, [Sector]
    inc bl
    mov [Sector], bl
    pop bx
    inc cl
    cmp cl, 18
    jne continue
    add ch, 1
    mov cl, 1
continue:
    add bx, BytesPerSector
    jmp load_sector
loaded:
    ret

error1:
    mov bx, errorMsg1
    call print_string
    jmp $

error2:
    mov bx, errorMsg2
    call print_string
    jmp $

; 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 [mmap_ent], bp  ; store the entry count
    clc         ; there is "jc" on end of list to this point, so the carry must be cleared
    ret
.failed:
    stc         ; "function unsupported" error exit
    ret


[bits 32]

BEGIN_PM:
    mov ebx, msgProt
    call print_string32
    call KERNEL
    jmp $

BytesPerSector equ 512
NumHeads equ 2
SectorsPerTrack equ 18

Sector db 0

mmap_ent dw 0

BOOT_DRIVE db 0

msgStage2 db "Stage 2 reched!", 0
msgProt db "Successfully switched to 32-bit mode",0
msgKernel db "Loading the kernel onto memory",0
msg db "Loaded!!", 0
errorMsg1 db "Error1", 0
errorMsg2 db "Error2", 0

times 1024-($-$$) db 0

内核代码 -

#include <stdint.h>
#include <stddef.h>
#include "../physmm/physmm.h"

void print_menu(uint8_t n);

void main()
{
    /*Declarations*/
    #ifdef DEBUG
        char* status = "MOS V2.0 Copyright 2017 | Welcome Anish Sharma | Development Build";
    #else
        char* status = "Welcome Anish Sharma";
    #endif

    fillScreen();

    hal_initialize();

    clrscr();

    initialize_physmm();

    write_status(status);

    showNumber("Total Memory (in KB):", memoryKB, 10, 0x1e);
    showNumber("Total Memory (in MB):", memoryMB, 10, 0x1e);
    showNumber("Number of Regions:", *((uint16_t*)0x50c), 10, 0x1e);
    print("Hello");

    for(;;){
        write_string_line(0x0f, "Current Tick Count : ", 23);
        printNum(get_tick(), 21, 23, 0x0f, 10);
        if(get_tick() % 10 == 0)
            update_cursor(0,getCLine());
    }
}

makefile -

DIRECTORIES = boot kernel drivers HALx86 dataman physmm

C_SOURCES = $(wildcard drivers/*.c HALx86/*.c dataman/*.c physmm/*.c)
ASM_SOURCES = $(wildcard HALx86/*.asm)

CC = gcc
CFLAGS = -DDEBUG -m32 -ffreestanding -c -nostdlib -lgcc

KERNEL = kernel/kernel_start.o kernel/kernel.o

ASM = nasm
AOFLAGS = -f elf32 -o
ABINFLAGS = -f bin -o

OBJ = ${C_SOURCES:.c=.o}
ASMOBJ = ${ASM_SOURCES:.asm=.o}

all: os-image.img

os-image.img: boot/boot_sector.bin boot/boot_stage2.bin kernel/kernel.bin
    cat $^ > $@
    echo "OS Image size:"
    wc -c os-image.img

kernel/kernel.bin: $(KERNEL) ${OBJ} ${ASMOBJ}
    ld -melf_i386 -o $@ -Ttext 0x1000 $^ --oformat binary

%.o : %.c
    $(CC) $(CFLAGS) $< -o $@

%.o : %.asm
    $(ASM) $< $(AOFLAGS) $@

%.bin : %.asm 
    nasm $< $(ABINFLAGS) $@

clean:
    rm -fr kernel/*.o
    rm -fr drivers/*.o
    rm -fr HALx86/*.o
    rm -fr dataman/*.o
    rm -fr physmm/*.o
    rm -fr boot/*.bin
    rm -fr os-image.img *.bin *.o

rebuild:
    make clean
    make

backup:
    make clean
    zip -r backups/BACKUP_DATE-`date +%d-%m-%Y_%H-%M-%S`.zip $(DIRECTORIES) README.txt makefile
    make

0 个答案:

没有答案