-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathboot.asm
138 lines (111 loc) · 3.47 KB
/
boot.asm
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
[org 0x7c00]
mov [BOOT_DISK], dl ; after boot drive number stored in dl (where booted)
mov bp, 0x8000 ; mov sp, bp ;
mov bx, 0x9000 ; mov dh, 5 ; mov dl, [BOOT_DRIVE]
mov dh, 2 ; number of sectors to read ('times 256 dw 0xface is a sector')
mov dl, [BOOT_DISK]
call disk_load
; equ is used to set up constants
; defining the offsets
CODE_SEG equ code_descriptor - GDT_Start
DATA_SEG equ data_descriptor - GDT_Start
cli ; disable all interrupt actions (for some 8088 bug)
lgdt[GDT_Descriptor] ; loading the GDT
; change last of bit of a special 32bit reg cr0 to 1
; to make the actual switch
mov eax, cr0
or eax, 1
mov cr0, eax
; cpu is in 32 bit protected mode
; now, far jump (jump to another segment)
jmp CODE_SEG:start_protected_mode
jmp $
%include './utils/print_function.asm'
%include './utils/disk_load.asm'
FAIL_MESSAGE_CARRY: db "Failure: carry flag (cf) is high!",0
FAIL_MESSAGE_SEC_NUM: db "Failure: wrong number of sectors to read!", 0
; define protected after real mode
; GDT (Global Descriptor Table)
; Code Segment Descriptor
; Present = 1 for used segments (if segment is being used)
; Privilage = 00 | 01 | 10 | 11 (00 is highest) (segment hierarchy)
; Type = 1 if code OR data seg (0)
; Flags: 0/1 (single bit)
; Sets of flags:
; - Type flags (4 bits)
; - Other flags (4 bits)
; Type flags = 1010
; a) Code? yes, thus: 1
; b) Conforming: can this code, executed from lower priv segs? no=0
; c) Readable? 1 to read constants
; d) Accessed: is CPU using the segment? 1 : 0 (cpu changes it)
; a2) if NOT code, but Data => 0
; b2) direction = 0 (when 1 segment becomes expend down segment)
; c2) Writable? 1 (0 if read only)
; Other flags = 1100
; Granulatiy 1 => limit *= 0x1000 (so very high limit)
; 32 bits ? 1 : 0
; not using the last bits so its set to 00
; ---------------
; These should be defined in certain order for GDT
; db: defines bytes
; dw: defines words
; dd: defines double words
;----------------
; pres, priv type = 1001 [code][not exacutable from low seg][read consts][1]
;-------------------------;
; base: 0 (32 bit) |
; limit: 0xfffff |
; pres, priv, type = 1001 |
; type flags = 1010 |
; other flags = 1100 |
;-------------------------;
GDT_Start:
null_descriptor:
dd 0x0 ; four times 00000000
dd 0x0 ; four times 00000000
code_descriptor:
dw 0xffff ; define first 16 bits of limit (first four 'f')
; then, first 24 bits of the base
dw 0x0 ; 16 bits +
db 0x0 ; 8 bits = 24
; then: pres,priv,type properties
db 0b10011010
; other + last four bits of limit (the missing f)
db 0b11001111
; and, last 8 bits of the base
db 0x0
data_descriptor:
dw 0xffff
dw 0x0
dw 0x0
db 0b10010010
db 0b11001111
db 0x0
GDT_End:
GDT_Descriptor:
dw GDT_End - GDT_Start - 1 ; size
dd GDT_Start
[bits 32]
VIDEO_MEMORY equ 0xb8000
WHITE_ON_BLACK equ 0x0f
start_protected_mode:
; protected mode code here
; how to print a character:
; videoMemory = 0xb8000
; first byte = character
; second byte = color
mov al, 'A'
mov ah, WHITE_ON_BLACK ; white on black
mov [VIDEO_MEMORY], ax ; move ax to videoMemory
jmp $
BOOT_DISK: db 0
times 510-($-$$) db 0
db 0x55, 0xaa
; We know that BIOS will load only the first 512-byte sector from the disk, ; so if we purposely add a few more sectors to our code by repeating some
; familiar numbers, we can prove to ourselfs that we actually loaded those ; additional two sectors from the disk we booted from.
times 256 dw 0xdada
times 256 dw 0xface
times 256 dw 0xface
times 256 dw 0xface
times 256 dw 0xface