Organizing the kernel code.
This commit is contained in:
55
boot/boot_sect.asm
Normal file
55
boot/boot_sect.asm
Normal file
@ -0,0 +1,55 @@
|
||||
[org 0x7c00]
|
||||
KERNEL_OFFSET: equ 0x1000 ; kernel memory offset
|
||||
mov [BOOT_DRIVE], dl ; store boot drive for later.
|
||||
mov bp, 0x9000 ; setup the stack
|
||||
mov sp, bp
|
||||
|
||||
mov bx, MSG_REAL_MODE
|
||||
call print_string
|
||||
|
||||
call load_kernel ; load our kernel from memory
|
||||
call switch_to_pm ; switch to 32-bit protected mode
|
||||
|
||||
jmp $
|
||||
|
||||
%include "print.asm"
|
||||
%include "print32.asm"
|
||||
%include "disk.asm"
|
||||
%include "gdt.asm"
|
||||
%include "switch_prot.asm"
|
||||
|
||||
[bits 16]
|
||||
|
||||
load_kernel:
|
||||
mov bx, MSG_LOAD_KERNEL
|
||||
call print_string
|
||||
|
||||
mov bx, KERNEL_OFFSET ; address to load the kernel to
|
||||
mov dh, 1 ; number of sectors to load
|
||||
mov dl, [BOOT_DRIVE] ; drive to load from
|
||||
call disk_load
|
||||
|
||||
mov bx, MSG_KERNEL_LOADED
|
||||
call print_string
|
||||
|
||||
ret
|
||||
|
||||
[bits 32]
|
||||
BEGIN_PM:
|
||||
mov ebx, MSG_PROT_MODE
|
||||
call print_string_pm
|
||||
|
||||
call KERNEL_OFFSET
|
||||
|
||||
jmp $
|
||||
|
||||
;;;
|
||||
; Data
|
||||
BOOT_DRIVE: db 0
|
||||
MSG_REAL_MODE: db "Started in 16-bit Real Mode",0
|
||||
MSG_PROT_MODE: db "Successfully landed in 32-bit Protected Mode",0
|
||||
MSG_LOAD_KERNEL: db "Loading kernel into memory...",0
|
||||
MSG_KERNEL_LOADED: db "Successfully loaded kernel into memory",0
|
||||
|
||||
times 510-($-$$) db 0
|
||||
dw 0xaa55
|
43
boot/disk.asm
Normal file
43
boot/disk.asm
Normal file
@ -0,0 +1,43 @@
|
||||
;;;
|
||||
; disk_load
|
||||
; ---------
|
||||
; Load disk sectors into memory.
|
||||
;
|
||||
; Parameters:
|
||||
; - dh: number of sectors to read
|
||||
disk_load:
|
||||
pusha
|
||||
push dx ; store `dx' to check if the appropriate number of
|
||||
; sectors were read later on.
|
||||
mov ah, 0x02 ; BIOS read routine
|
||||
mov al, dh ; read `dh' sectors
|
||||
mov ch, 0x00 ; select cylinder 0
|
||||
mov dh, 0x00 ; select head 0
|
||||
mov cl, 0x02 ; start reading from second sector (after the boot
|
||||
; sector)
|
||||
|
||||
int 0x13 ; BIOS interrupt
|
||||
|
||||
jc disk_load_error ; if `cf' flag has gone off then a read error has
|
||||
; occurred
|
||||
|
||||
pop dx ; restore `dx'
|
||||
cmp dh, al ; were the appropriate amount of sectors read?
|
||||
jne disk_load_unexp ; if not then there was an error
|
||||
popa
|
||||
ret
|
||||
|
||||
disk_load_error:
|
||||
mov bx, DISK_READ_ERROR ; print the error
|
||||
jmp disk_load_print_exit
|
||||
disk_load_unexp:
|
||||
mov bx, DISK_READ_UNEXP
|
||||
disk_load_print_exit:
|
||||
call print_string
|
||||
jmp $ ; lock due to failure
|
||||
|
||||
DISK_READ_UNEXP:
|
||||
db "Unexpected amount of sectors read!",0
|
||||
|
||||
DISK_READ_ERROR:
|
||||
db "Disk read error!",0
|
37
boot/gdt.asm
Normal file
37
boot/gdt.asm
Normal file
@ -0,0 +1,37 @@
|
||||
; GDT
|
||||
gdt_start:
|
||||
|
||||
gdt_null:
|
||||
dd 0x0 ; the mandatory null-descriptor
|
||||
dd 0x0
|
||||
|
||||
gdt_code: ; code segment of descriptor
|
||||
dw 0xFFFF ; Limit (bits 0-15)
|
||||
dw 0x0 ; Base (bits 0-15)
|
||||
db 0x0 ; Base (bits 16-23
|
||||
; 1st flags: (present)1, (privilege)00, (descriptor type)1 -> 1001b
|
||||
; type flags: (code)1, (conforming)0, (readable)1, (accessed)0 -> 1010b
|
||||
; 2nd flags: (granularity)1, (32-bit default)1, (64-bit seg)0, (AVL)0 -> 1100b
|
||||
db 10011010b ; 1st flags and type flags
|
||||
db 11001111b ; 2nd flags and Limit (bits 16-19)
|
||||
db 0x0 ; Base (bits 24-31)
|
||||
|
||||
gdt_data:
|
||||
; type flags: (code)0, (expand down)0, (writable)1, (accessed)0 -> 0010b
|
||||
dw 0xFFFF ; Limit (bits 0-15)
|
||||
dw 0x0 ; Base (bits 0-15)
|
||||
db 0x0 ; Base (bits 16-23)
|
||||
db 10010010b ; 1st flags and type flags
|
||||
db 11001111b ; 2nd flags and Limit (bits 16-19)
|
||||
db 0x0 ; Base (bits 24-31)
|
||||
|
||||
gdt_end: ; for calculating size of the gdt
|
||||
|
||||
gdt_descriptor:
|
||||
dw gdt_end - gdt_start - 1 ; size of our GDT, always decrement true size by one
|
||||
dd gdt_start ; start address of our GDT
|
||||
|
||||
;;;
|
||||
; Constants used for GDT segment offsets
|
||||
GDT_CODE_SEG: equ gdt_code - gdt_start
|
||||
GDT_DATA_SEG: equ gdt_data - gdt_start
|
31
boot/print.asm
Normal file
31
boot/print.asm
Normal file
@ -0,0 +1,31 @@
|
||||
;;;
|
||||
; print_string
|
||||
; ------------
|
||||
; Print a string from memory.
|
||||
;
|
||||
; Parameters:
|
||||
; - bx: pointer to string
|
||||
;
|
||||
; Internal Variables:
|
||||
; - ah: scrolling teletype BIOS routine code
|
||||
; - al: Byte containing character to print
|
||||
; - bx: shifting pointer to string
|
||||
print_string:
|
||||
pusha ; save the state of all registers to the stack
|
||||
|
||||
mov ah, 0x0e ; scrolling teletype BIOS routine code
|
||||
print_string_start:
|
||||
mov al, [bx] ; load first letter into `al'
|
||||
cmp al, 0
|
||||
je print_string_end ; if null-termination then return
|
||||
int 0x10 ; print the letter
|
||||
add bx, 0x1 ; offset to next character
|
||||
jmp print_string_start ; go back to beginning
|
||||
|
||||
print_string_end:
|
||||
mov al, 0xA
|
||||
int 0x10
|
||||
mov al, 0xD
|
||||
int 0x10
|
||||
popa ; return the state of all the registers
|
||||
ret
|
30
boot/print32.asm
Normal file
30
boot/print32.asm
Normal file
@ -0,0 +1,30 @@
|
||||
[bits 32]
|
||||
VIDEO_MEMORY: equ 0xB8000
|
||||
WHITE_ON_BLACK: equ 0x0F
|
||||
|
||||
;;;
|
||||
; print_string_pm
|
||||
; ------------
|
||||
; Print a string stored in memory.
|
||||
;
|
||||
; Parameters:
|
||||
; - ebx: pointer to string in memory
|
||||
print_string_pm:
|
||||
pusha
|
||||
mov edx, VIDEO_MEMORY ; set `edx' to the start of the video memory
|
||||
|
||||
print_string_pm_loop:
|
||||
mov al, [ebx] ; store the char at `ebx' in `al'
|
||||
mov ah, WHITE_ON_BLACK ; store the attributes in `ah'
|
||||
cmp al, 0 ; if null-termination then done
|
||||
je print_string_pm_done
|
||||
|
||||
mov [edx], ax ; store char and attributes
|
||||
add ebx, 1 ; increment ebx to next char
|
||||
add edx, 2 ; increment to next char cell in vidmem
|
||||
|
||||
jmp print_string_pm_loop
|
||||
|
||||
print_string_pm_done:
|
||||
popa
|
||||
ret
|
29
boot/switch_prot.asm
Normal file
29
boot/switch_prot.asm
Normal file
@ -0,0 +1,29 @@
|
||||
[bits 16]
|
||||
switch_to_pm:
|
||||
cli ; turn off all interrupts until we have properly
|
||||
; properly set them up
|
||||
|
||||
lgdt [gdt_descriptor] ; load the global descriptor table defining
|
||||
; protected mode segments
|
||||
|
||||
mov eax, cr0 ; set flag in register to switch to protected mode
|
||||
or eax, 0x1
|
||||
mov cr0, eax
|
||||
|
||||
jmp GDT_CODE_SEG:init_pm ; make a far jump to the 32-bit code forcing a flush
|
||||
; of the pipelining
|
||||
|
||||
[bits 32]
|
||||
; initialize registers and the stack once in protected mode
|
||||
init_pm:
|
||||
mov ax, GDT_DATA_SEG ; point our new segment registers to the data
|
||||
mov ds, ax ; selector defined in the GDT, since we cannot
|
||||
mov ss, ax ; use the old 16-bit code
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
|
||||
mov ebp, 0x90000 ; Update the stack position so it's at the top
|
||||
mov esp, ebp ; of the free space
|
||||
|
||||
call BEGIN_PM
|
Reference in New Issue
Block a user