step 2: load 2nd sector and jump into it
[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 dx value
21         mov [saved_drive_num], dl
22
23 ; service 0: set videomode ah
24 ; param: which video mode (13h: 320x200, 256 colors) al
25 ; ax: ah (high 8 bits), al (low)
26         mov ax, 13h
27
28 ; calling video bios
29 ; software interrupt 10h
30         int 10h
31         mov ax, 3
32         call clearscreen
33
34 ; load 2nd sector from boot device and jump to it
35 ; bios helpers, 13h = disk io
36         mov ax, 0
37         mov ds, ax
38         mov ah, 02h                     ; call 2: read sectors into memory
39         mov al, 1                               ; number of sectors to read
40         mov ch, 0                               ; low 8 bits of cylinder number
41         mov cl, 2                               ; sector number that starts from 1
42         mov dh, 0                               ; head number
43         mov dl, [saved_drive_num]       ; 8bits
44         mov bx, sector_2
45         int 13h
46 ; error check: if carry flag isn't set jump to loaded code
47         jnc     sector_2
48 .inf_loop:
49         jmp .inf_loop
50
51
52 clearscreen:
53 ; video ram is mapped in a0000
54 ; first 64000 bytes appear immediately on screen
55 ; mem addresses in real mode have 2 parts: segment and offset
56 ; bits overlap: segment is shifted by 4 and is added to the
57 ; overlapping offset (20 bits number = x86's addressable space = 1MB)
58 ; segment register for the segment: es, ds, cs, ss (and: fs, gs)
59 ; default register = ds (data segment), es = extra segment
60 ; cs = code segment cs:ip (it points where to read instructions and is
61 ; automatically set to 7c0 (7c00h)
62 ; offset can be paired with any register
63 ; pair the registers
64         push ax
65         mov ax, 0a000h
66         mov ds, ax
67         mov di, 0
68         pop ax
69 ; counter cx
70         mov cx, 64000
71
72 .loop_begin:
73 ; dereferrence[] address
74         mov [di], al
75         inc     di
76         dec cx
77 ; when cx is 0, 0 flag is set
78         jnz .loop_begin
79         ret
80
81 saved_drive_num:
82         db 0 ; declare byte 0
83
84 ; assembler trick: write as many 0 needed to fill 510 bytes
85 ; $ <- means here
86         times 510-($-$$) db 0
87         dw 0aa55h
88
89 sector_2:
90         mov ax, 5
91         call clearscreen
92 .inf_loop:
93         jmp .inf_loop