forked from hse-cs-ami/yabloko-public
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mbr.S
70 lines (53 loc) · 1.39 KB
/
mbr.S
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
#include "cpu/gdt.h"
.code16
.global _start
_start:
mov $banner, %si
call print_string
call switch_to_32bit
hlt
jmp . // loop forever
switch_to_32bit:
mov $2, %al
out %al, $0x92 // enable A20
cli // 1. disable interrupts
lgdt gdt_descriptor // 2. load GDT descriptor
mov %cr0, %eax
or $1, %eax // 3. enable protected mode
mov %eax, %cr0
ljmp $SEG_KCODE << 3, $init_32bit // 4. far jump
.code32
init_32bit:
mov $SEG_KDATA << 3, %ax // 5. update segment registers
mov %ax, %ds
mov %ax, %ss
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov $KERN_STACK_BASE, %ebp // 6. setup stack
mov %ebp, %esp
call bootmain // 7. load and run kernel
jmp . // 8. loop forever
.code16
print_string:
mov $0x0e, %ah // "teletype output"
repeat:
lodsb // equivalent to mov (%si), %al; inc %si
test %al, %al
je done
int $0x10 // bios interrupt
jmp repeat
done:
ret
banner:
.asciz "Loader \n"
.balign 4
gdt_start:
.quad 0x0 // null descriptor
SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) # code seg
SEG_ASM(STA_W, 0x0, 0xffffffff) # data seg
gdt_end:
// GDT descriptor
gdt_descriptor:
.word gdt_end - gdt_start - 1 // size (16 bit)
.int gdt_start // address (32 bit)