-
Notifications
You must be signed in to change notification settings - Fork 1
/
boot0.asm
132 lines (105 loc) · 3.18 KB
/
boot0.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
;-------------------------------------------------------------------------------
; First Stage Bootloader
; Jorge Rinaldi <jrg.rinaldi@gmail.com>
;-------------------------------------------------------------------------------
; TODO use value the BIOS returns in DL (drive number) instead of DRIVE_NUM
bits 16
%include "boot.inc"
FIRST_SECTOR2LOAD equ 2 ; sectors start counting from 1, not 0
NUM_SECTORS2LOAD equ 8
SECTOR_NUM_MAX equ (NUM_SECTORS2LOAD+FIRST_SECTOR2LOAD-1)
SECTOR_SIZE equ 512
BUF_SEG equ (BL_STAGE1_ADDR/16)
; this code will be loaded by the BIOS at address 0x7c00
org 0x7c00
; some BIOS's set CS:IP to 0x07c0:0x0000
; some other BIOS's set them to 0x0000:0x7c00
; both of them map to the same physical address
; in x86 there are three types of JMP instructions:
; 1) short (relative to current IP)
; 2) near (within the current segement determined by CS, only IP is given)
; 3) far (it additionally includes the CS)
; for this code to work with near jumps:
; a) CS:IP = 0x0000:0x7c00 and ORG 0x7c00
; b) CS:IP = 0x07c0:0x0000 and no ORG present
; we have chosen the first approach
; we set the CS:IP by means of a long jump
jmp 0x0000:_
_:
xor ax, ax
mov ds, ax
; set up the stack
mov ss, ax
mov sp, stack_top
stack_top:
push welcome_str
call bios_print
add sp, 2
; intialize floppy/HDD
push init_drive_str
call bios_print
add sp, 2
mov al, 0
mov dl, DRIVE_NUM
int 0x13
jc error
push ok_str
call bios_print
add sp, 2
; read sectors from floppy to main memory
repeat_sector_read:
push read_sector_str
call bios_print
add sp, 2
call read_sector
push ok_str
call bios_print
add sp, 2
mov al, [sector_num]
cmp al, SECTOR_NUM_MAX
jle repeat_sector_read
; jump to the just loaded code
jmp BUF_SEG:0x0000
jmp hang
read_sector:
mov ah, 0x02 ; BIOS service
mov al, 1 ; number of sectors to read
mov ch, 0 ; cylinder number
mov cl, [sector_num] ; sector number
mov dh, 0 ; head number
mov dl, DRIVE_NUM ; drive number
mov bx, BUF_SEG ; buffer segment
mov es, bx
mov bx, [buf_off]
int 0x13
jc error
; update sector number
inc cl
mov [sector_num], cl
mov [sector_num_str], cl
mov al, '0'
add [sector_num_str], al
; update the buffer offset
add bx, SECTOR_SIZE
mov [buf_off], bx
ret
%include "bios_print.inc"
error:
push error_str
call bios_print
add sp, 2
hang:
jmp hang
welcome_str db '1st Stage Bootloader', 10, 13, 0
init_drive_str db ' Initializating drive...', 0
ok_str db 'OK', 10, 13, 0
error_str db 'error', 10, 13, 0
read_sector_str db ' loading sector no. '
sector_num_str db (FIRST_SECTOR2LOAD+'0'), '...', 0
sector_num db FIRST_SECTOR2LOAD
buf_off dw 0
; fill up the rest with zeroes
times 510-($-$$) db 0
; bootable disk signature
db 0x55
db 0xaa