mbr_asm/mbr.asm

162 lines
3.4 KiB
NASM

section .boot
bits 16
global boot
boot:
jmp main
display_enable:
push bp
mov bp, sp
mov ah, 0h ; 00h Set Video Mode
mov al, 07h ; Txt, monochrome, 80x25
int 10h
mov sp, bp
pop bp
ret
print:
push bp
mov bp, sp
mov si, [bp + 4]; put first function arg in si. sp is stask pointer
.loop:
lodsb ; load si content into al then inc si
cmp al, 0;
je .end
mov ah, 0eh
mov bx, 0
int 10h
jmp .loop
.end:
mov sp, bp
pop bp
ret
println:
push bp
mov bp, sp
push word [bp + 4]
call print
add sp, 2
mov ah, 03h ; read cursor position
int 10h ; row number in dh. Col in dl
inc dh ; goto next line
mov dl, 0
mov ah, 02h ; Set Cursor Position
int 10h
mov sp, bp
pop bp
ret
hello db 'Booting matOs', 0
main:
sti ; enable virtual interupts
mov [disk],dl ; save disk used to boot by bios
call display_enable
push hello
call println
add sp, 2
; Switch in 32bits Protected mode
; Activate A20 http://wiki.osdev.org/A20_Line to be able to access more than 1Mb memory
mov ah, 0h
mov ax, 0x2401
int 0x15
; Change video mode to display VGA
mov ax, 0x3
int 0x10
; http://www.ctyme.com/intr/rb-0607.htm
; Bios read first 512 bytes, read next disk sector
mov ah, 0x2 ;read sectors
mov al, 15 ;sectors to read
mov ch, 0 ;cylinder idx
mov dh, 0 ;head idx
mov cl, 2 ;sector idx
mov dl, [disk] ;disk idx
mov bx, copy_target;target pointer
int 0x13
cli ; disable interruption when setting GDT
; switch in 32 bits
lgdt [gdt_pointer] ; switch in 32bits here
mov eax, cr0
or eax,0x1; set the protected mode bit on special CPU reg cr0
mov cr0, eax
jmp CODE_SEG:boot2 ; In protected mode we need to add the segment selector
; GDT table desciption could be found http://wiki.osdev.org/Global_Descriptor_Table
; here we define the 3 64bits segment needed: null segment, code segment and data segment
gdt_start: ;null segment
dq 0x0
gdt_code: ;code segment
dw 0xFFFF ; limit [0:15]
dw 0x0 ; base [0:15]
db 0x0 ; base [16:23]
db 10011010b ; access byte: Present(1)| Priv(2) 0 ->kernel 3->userspace | 1 | Executable(1) | Direction/Conformity (1) | RW(1) | Accessed(1)
db 11001111b ; Granularity(1) | Size (1) 0-> 16bit mode 1->32protected mode | 0 | 0 | Limit [16:19]
db 0x0 ; base [24:31]
gdt_data:
dw 0xFFFF
dw 0x0
db 0x0
db 10010010b
db 11001111b
db 0x0
gdt_end:
gdt_pointer:
dw gdt_end - gdt_start
dd gdt_start
disk:
db 0x0
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start
times 510 - ($-$$) db 0
dw 0xaa55
copy_target:
bits 32
boot2:
mov ax, DATA_SEG ; set all segments to point to DATA_SEG https://en.wikipedia.org/wiki/X86_memory_segmentation
mov ds, ax ; Data segment
mov es, ax ; Extra Segment (for string operation)
mov fs, ax ; No Specific use
mov gs, ax ; No Specific use
mov ss, ax ; stack segment
mov esi,hello32
mov ebx,0xb8000 ; Cannot use BIOS anymore, use VGA Text buffer instead
.loop32:
lodsb
or al,al
jz halt
or eax,0x0100 ; blue bg
mov word [ebx], ax
add ebx,2
jmp .loop32
halt:
mov esp,kernel_stack_top
extern kmain
call kmain
cli
hlt
hello32: db "Hello 32 bits world!",0
section .bss
align 4
kernel_stack_bottom: equ $
resb 16384 ; 16 KB
kernel_stack_top: