OS Dosent由于某种原因显示上下内存。正如您在Detecting Memory Wiki中所见:http://wiki.osdev.org/Detecting_Memory_(x86)#Memory_Map_Via_GRUB,它说
有关常规内存(例如物理内存),请参阅mbd-> mem_lower 地址介于0到640KB之间)和mbd-> mem_upper为高 记忆(例如1MB)。两者都以kibibytes给出
我正好这样做:
kernel.c ++:
#include "types.h"
#include "gdt.h"
#include "stdio.h"
#include "serial.h"
#include "mem.h"
#include "idt.h"
#include "timer.h"
#include "isr.h"
#include "kbd.h"
#include "mouse.h"
#include "irq.h"
#include "string.h"
#include "terminal.h"
#include "multiboot.h"
#include "pmm.h"
#include "heap.h"
//Call all class constructor
//for global objects before
//calling the kernel
typedef void (*constructor)();
extern "C" constructor start_ctors;
extern "C" constructor end_ctors;
extern "C" void callConstructors()
{
for(constructor* i = &start_ctors; i != &end_ctors; i++)
(*i)();
}
extern "C" void kernelMain(uint32_t kernel_virtual_end,
uint32_t placeholder,
uint32_t kernel_physical_end,
uint32_t kernel_physical_start, uint32_t kernel_virtual_start,
multiboot_info_t multiboot_structure,uint32_t magicnumber
)
{
cls();
printf("******KERNEL INFO********\n");
printf("KERNEL START VIRTUAL 0x%x\n" , kernel_virtual_start);
printf("KERNEL START PHYSICAL 0x%x\n" , kernel_physical_start);
printf("KERNEL END VIRTUAL 0x%x\n" , kernel_virtual_end);
printf("KERNEL END PHYSICAL 0x%x\n" , kernel_physical_end);
printf("*************************\n\n");
printf("********RAM INFO*********\n");
printf("LOWER MEMORY : %x \n" , (uint32_t)multiboot_structure.mem_lower);
printf("UPPER MEMORY : %x \n" , (uint32_t)multiboot_structure.mem_upper);
printf("*************************\n");
gdt gt;
IDT idt;
ISR isr;
IRQ irq;
SerialPort sp;
isr.install_isrs();
irq.install_irqs();
Timer timer;
timer.install_timer();
KBD kbd;
kbd.install_kbd_driver();
MOUSE mouse;
mouse.install_mouse_driver();
__asm__ __volatile__ ("sti");
while(1);
err:
while(1);
}
boot.asm:
;Global MultiBoot Kernel Recongnzatio
; setting up the Multiboot header - see GRUB docs for details
MODULEALIGN equ 1<<0 ; align loaded modules on page boundaries
MEMINFO equ 1<<1 ; provide memory map
FLAGS equ MODULEALIGN | MEMINFO ; this is the Multiboot 'flag' field
MAGIC equ 0x1BADB002 ; 'magic number' lets bootloader find the header
CHECKSUM equ -(MAGIC + FLAGS) ; checksum required
;Putting in object file
section .multiboot
dd MAGIC
dd FLAGS
dd CHECKSUM
section .data
KERNEL_VIRTUAL_BASE equ 0xC0000000 ; 3GB
KERNEL_PAGE_NUMBER equ (KERNEL_VIRTUAL_BASE >> 22) ; Page directory index of kernel's 4MB PTE.
align 0x1000
BootPageDirectory:
; This page directory entry identity-maps the first 4MB of the 32-bit physical address space.
; All bits are clear except the following:
; bit 7: PS The kernel page is 4MB.
; bit 1: RW The kernel page is read/write.
; bit 0: P The kernel page is present.
; This entry must be here -- otherwise the kernel will crash immediately after paging is
; enabled because it can't fetch the next instruction! It's ok to unmap this page later.
dd 0x00000083
times (KERNEL_PAGE_NUMBER - 1) dd 0 ; Pages before kernel space.
; This page directory entry defines a 4MB page containing the kernel.
dd 0x00000083
times (1024 - KERNEL_PAGE_NUMBER - 1) dd 0 ; Pages after the kernel image.
section .text
; reserve initial kernel stack space -- that's 16k.
STACKSIZE equ 0x4000
global loader
global BootPageDirectory
loader:
;Enable Paging START
; NOTE: Until paging is set up, the code must be position-independent and use physical
; addresses, not virtual ones!
mov ecx, (BootPageDirectory - KERNEL_VIRTUAL_BASE)
mov cr3, ecx ; Load Page Directory Base Register.
mov ecx, cr4
or ecx, 0x00000010 ; Set PSE bit in CR4 to enable 4MB pages.
mov cr4, ecx
mov ecx, cr0
or ecx, 0x80000000 ; Set PG bit in CR0 to enable paging.
mov cr0, ecx
lea ebx, [higherhalf]
jmp ebx ; Absolute Jump
higherhalf:
extern kernelMain
extern callConstructors
; Unmap the identity-mapped first 4MB of physical address space. It should not be needed
; anymore.
mov dword [BootPageDirectory], 0
invlpg [0]
mov esp, stack + STACKSIZE ; set up the stack
call callConstructors
extern kernel_virtual_start
extern kernel_virtual_end
extern kernel_physical_start
extern kernel_physical_end
push kernel_virtual_end ; 2
push 5
push kernel_virtual_start ; 1
push kernel_physical_start ; 3
push kernel_physical_end ; 4
push eax ; 5
push ebx ; 6
call kernelMain
jmp _eof
_eof:
cli
hlt
jmp _eof
section .bss
align 32
stack:
resb STACKSIZE ; reserve 16k stack on a uint64_t boundary
当我在上面完成时,当我打印低内存和高内存(给你)时,我会得到这些奇怪的字符,正如你在这里看到的那样:https://www.youtube.com/watch?v=nDxSOkKd_NI。你可以在这里看到完整的源代码: https://raw.githubusercontent.com/amanuel2/OS_Mirror。帮助会得到赞赏。
答案 0 :(得分:-1)
您的代码似乎有多处错误 -
<强> 1。在调用静态对象构造函数时销毁寄存器值 - 执行以下代码时 -
MOV ESP, stack + STACKSIZE
CALL callConstructors
然后你需要保存你所依赖的寄存器值,这里是EAX&amp; EBX对于保持多引导相关值至关重要。如果在通话之前使用任何其他寄存器,则应保存它们。你应该阅读你的呼叫者/被呼叫者保存的寄存器的ABI规范。
<强> 2。按相反顺序推送的参数 - 对于
的参数,这可能看起来很尴尬push kernel_virtual_end ; 2
push 5
push kernel_virtual_start ; 1
push kernel_physical_start ; 3
push kernel_physical_end ; 4
push eax ; 5
push ebx ; 6
call kernelMain
调用kernelMain的顺序是相反的,尽管你直接在代码中看到它们。您应该将汇编代码编写为
push ebx ;6
push eax ; 5
push kernel_physical_end ; 4
push kernel_physical_start ; 3
push kernel_virtual_start ; 1
push 5
push kernel_virtual_end ; 2
call kernelMain
要理解为什么需要这样做,你应该知道IA32堆栈向下增长。这意味着ESP中的值(处理器堆栈的地址)在每个
上减少4(对于32位平台,在64位平台中为8)push <REG>
但是在C中,第一个参数是最低地址的那个,或者是最后推送的那个。因此,您必须在汇编代码中以反向方式推送参数。