我正在为我的操作系统开发物理内存管理器。所以,为了获得内存映射,我使用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