1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
ORG 0x0
BITS 16
_start:
jmp short start
nop
; Setup dummy BIOS Parameter block so a dumb BIOS does not corrupt us
; if it starts messing up with the parameter block
times 33 db 0
start:
; Set CS to 0x07c0 with label step2 as its beginning offset
jmp 0x07c0:step2
step2:
; Setup segments
cli ; Disable interrupts
mov ax, 0x07c0
mov ds, ax
mov es, ax
mov ax, 0x00
mov ss, ax
mov sp, 0x7c00 ; Stack segment starts right before ds
; and grows down to 0x0. This works because
; Intel implements a full descending stack
; Setup and test interrupt vector table and interrupts
mov word[ss:0x00], handle_zerodiv_intr ; first 2 bytes, mem offset for int
; 0 location
; Use SS here because it already starts
; at 0x0
mov word[ss:0x02], 0x7c0 ; Data segment our interrupt is
sti ; Enable interrupts
; Test interrupts
; mov ax, 0x00
; div ax
mov si, load_msg
call print
; Load sector from disk
mov ah, 2 ; Read sector into memory
mov al, 1 ; Read 1 sector
mov ch, 0 ; Cylinder number
mov cl, 2 ; Sector number to start reading from
mov dh, 0 ; Head number
;DL ; Drive number (Already set by bios)
; Sector will be loaded at ES:BX. We already have ES set,
; just set the BX to an address after the end of the bootloader. This
; avoids the risk of corrupting any data from our bootloader.
mov bx, kbuf_sector
int 0x13
; Jump if CF is set
jc kload_failure ; On I/O error, CF is set
; Kernel loaded succesfully (hopefully)
mov si, kbuf_sector
call print
jmp $
kload_failure:
mov si, err_msg
call print
jmp $
print:
mov bx, 0
.loop
lodsb
cmp al, 0
je .done
call print_char
jmp .loop
.done:
ret
print_char:
mov ah, 0x0e
int 0x10
ret
; Interrupt handlers
handle_zerodiv_intr:
mov si, divzero_msg
call print
iret
; Static data
load_msg: db 'Starting bootloader...', 0x0A, 0x0D, 0
divzero_msg: db 'Interrupts working properly...', 0x0A, 0x0D, 0
err_msg: db 'Failed to load kernel...', 0x0A, 0x0D, 0
; Fill in to the end and add bootloader signature
times 510 - ($ - $$) db 0
dw 0xAA55
; This just labels an address after the bootloader. Just makes it easier
; to refer to the loaded sector from int 0x13.
kbuf_sector:
|