Reputation: 17
I made this simple bootloader in asm and kernel in C. Below are the code
boot.asm
[org 0x7C00] ; Set the origin to 0x7C00 (default for bootloader)
; --- Initial Setup ---
mov bp, 0x9000 ; Set up the base pointer for the stack
mov sp, bp ; Set the stack pointer to the base pointer
cli ; Clear interrupts to avoid unexpected IRQs during setup
; --- Set up the Global Descriptor Table (GDT) ---
lgdt [gdt_descriptor] ; Load the GDT descriptor
; --- Enter Protected Mode ---
mov eax, cr0 ; Load CR0 register
or eax, 0x1 ; Set the PE bit in CR0 to enable Protected Mode
mov cr0, eax ; Write it back to CR0
jmp 0x08:init_pm ; Jump to protected mode code, using the code selector (0x08)
[bits 32] ; Start using 32-bit mode
; --- Protected Mode Initialization ---
init_pm:
; Set up segment registers
mov ax, 0x10 ; 0x10 is the selector for the code segment in the GDT
mov ds, ax ; Set DS to the code segment
mov es, ax ; Set ES to the code segment
mov fs, ax ; Set FS to the code segment
mov gs, ax ; Set GS to the code segment
mov ss, ax ; Set SS to the code segment (this is where stack starts)
; Set up the stack in protected mode
mov esp, 0x9000 ; Set up the stack pointer to a safe location in protected mode
; --- Load Kernel from Disk ---
; Assuming the kernel is located at sector 2 and its size is less than 1MB.
mov eax, 0x10000 ; Destination address to load the kernel (0x10000)
mov cx, 1 ; Number of sectors to read (1 sector at a time)
mov bx, 0x00 ; Drive 0 (floppy or hard disk)
mov dl, 0x80 ; The first hard disk (if booting from hard disk)
load_kernel:
; BIOS interrupt to read a sector from the disk
; AH = 0x02 (read sectors), AL = number of sectors (1), CH = track (0), CL = sector (2), DH = head, DL = drive
mov ah, 0x02 ; BIOS read sectors function
mov al, 1 ; Read 1 sector
mov ch, 0 ; Track 0
mov cl, 2 ; Read sector 2
mov dh, 0 ; Head 0
mov dl, 0x80 ; Drive 0x80 (hard disk)
int 0x13 ; Call BIOS interrupt
jc disk_error ; Jump to disk error if carry flag is set (error)
; Kernel loaded successfully, copy to the specified address
; The data is already at memory location 0x7E00, now copy it to 0x10000
mov si, 0x7E00 ; Source address of the kernel data (after read)
mov di, 0x10000 ; Destination address to load the kernel
mov cx, 512 ; Number of bytes (1 sector = 512 bytes)
rep movsb ; Copy 512 bytes from source to destination
; --- Jump to the Kernel Entry Point ---
jmp 0x08:0x10000 ; Jump to the kernel's entry point
disk_error:
; Handle disk read error (e.g., infinite loop to indicate failure)
hlt ; Halt the system
[bits 16] ; Return to 16-bit mode for the GDT definition
; --- Global Descriptor Table (GDT) ---
GDT:
; Null descriptor
dd 0x0
dd 0x0
; Code descriptor (32-bit)
dw 0xffff ; Limit
dw 0x0 ; Base (low 16 bits)
db 0x0 ; Base (next 8 bits)
db 0b10011010 ; Type and flags (code, executable, read/write, etc.)
db 0b11001111 ; Limit (high 4 bits, flags)
db 0x0 ; Base (high 8 bits)
; Data descriptor (32-bit)
dw 0xffff ; Limit
dw 0x0 ; Base (low 16 bits)
db 0x0 ; Base (next 8 bits)
db 0b10010010 ; Type and flags (data, read/write, etc.)
db 0b11001111 ; Limit (high 4 bits, flags)
db 0x0 ; Base (high 8 bits)
; --- GDT Descriptor ---
gdt_descriptor:
dw $ - GDT - 1 ; Size of the GDT (16-bit)
dd GDT ; Address of the GDT
; --- Bootloader Padding ---
times 510 - ($ - $$) db 0 ; Fill the boot sector with zeroes
dw 0xAA55 ; Boot signature
kernel.c
void _start() {
// Basic initialization or a test message
char *str = "Hello from the kernel!";
unsigned short *video = (unsigned short*)0xB8000;
// Print the string at the start of the video memory
while (*str) {
*video = *str | 0x0F00; // White text on black background
str++;
video++;
}
while (1); // Halt execution
}
Could like someone help me, and give me the reason why its causing this? My assumption is the VGA memory write is causing this. Everytime i try to run, my vbox goes into guru meditation, its very frustrating, Please help me. My log is attached here.
Upvotes: 0
Views: 64