fee43e4a37922f50ac73891a975e64c84d611610
[bootboot] / bb.asm
1 ; org: all instructions from now on start in 7c00h
2 ; 7c00h is where the bios loads the 1st sector
3 ; assembler formatting:
4 ; column 0: labels
5 ; tab: commands
6         org 7c00h
7 ; at boot: real mode (like it's 8086)
8 ; we have to tell assembler that code is 16bit mode
9         bits 16
10
11 start:
12         mov sp, 7c00h
13
14 ; initialize segment registers
15         mov ax, 0
16         mov ds, ax
17         mov es, ax
18         mov ss, ax
19
20 ; save dl value
21 ; bios sets in dl the num of the drive that
22 ; loaded you so if you overwrite dl you can reuse it
23         mov [saved_drive_num], dl
24
25 ; service 0: set videomode ah
26 ; param: which video mode (13h: 320x200, 256 colors) al
27 ; ax: ah (high 8 bits), al (low)
28 ; call 0 = set_videomode it expects the video mode in al
29 ; ah : 0, al: 13, ax:ahal
30         mov ax, 13h
31
32 ; calling video bios
33 ; software interrupt 10h
34 ; what's the value of ah? al=video mode when ah=0
35 ; which set which video mode
36         int 10h
37         mov ax, 3
38         call clearscreen
39
40 ; waiting for keypress
41 ; x86 has 2 special instructions to read/write from I/O
42 ; devices: in and out (because some processors have different
43 ; address spaces for devices and for memory, arm not)
44 .key_wait:
45         in al, 64h      ; 60h = keyb data port, 64h = keyb status port
46         and al, 1       ; 1 = OUTBUF_FULL = the keyb controller out buf is full
47         jz .key_wait
48
49         in al, 60h      ; reads the keyb that was pressed to reset the flag
50
51 ; load 2nd sector from boot device and jump to it
52 ; bios helpers, 13h = disk io
53         mov ax, 0
54         mov ds, ax
55         mov ah, 02h                     ; call 2: read sectors into memory
56         mov al, 1                               ; number of sectors to read
57         mov ch, 0                               ; low 8 bits of cylinder number
58         mov cl, 2                               ; sector number that starts from 1
59         mov dh, 0                               ; head number
60         mov dl, [saved_drive_num]       ; 8bits
61         mov bx, sector_2
62         int 13h
63 ; error check: if carry flag isn't set jump to loaded code
64         jnc     sector_2
65 .inf_loop:
66         jmp .inf_loop
67
68
69 clearscreen:
70 ; video ram is mapped in a0000
71 ; first 64000 bytes appear immediately on screen
72 ; mem addresses in real mode have 2 parts: segment and offset
73 ; bits overlap: segment is shifted by 4 and is added to the
74 ; overlapping offset (20 bits number = x86's addressable space = 1MB)
75 ; segment register for the segment: es, ds, cs, ss (and: fs, gs)
76 ; default register = ds (data segment), es = extra segment
77 ; cs = code segment cs:ip (it points where to read instructions and is
78 ; automatically set to 7c0 (7c00h)
79 ; offset can be paired with any register
80 ; pair the registers
81         push ax
82         mov ax, 0a000h
83         mov ds, ax
84         mov di, 0
85         pop ax
86 ; counter cx
87         mov cx, 64000
88
89 .loop_begin:
90 ; dereferrence[] address
91         mov [di], al
92         inc     di
93         dec cx
94 ; when cx is 0, 0 flag is set
95         jnz .loop_begin
96         ret
97
98 saved_drive_num:
99         db 0 ; declare byte 0
100
101 ; assembler trick: write as many 0 needed to fill 510 bytes
102 ; $ <- means here
103         times 510-($-$$) db 0
104         dw 0aa55h
105
106 sector_2:
107         mov ax, 5
108         call clearscreen
109 .inf_loop:
110         jmp .inf_loop