๐๏ธ ๊ทธ๋ํฝ ๋ชจ๋ ์ ํ๋ก ์ ํํ๊ณ ํ๋ฉด์ ๋
ธ๋์ ์ฌ๊ฐํ์ ํ์ํฉ๋๋ค.
Switch to graphics mode and display a yellow rectangle on the screen.
๐๏ธ ์ ์ฒด์ฝ๋ / full code
โ๏ธ boot.asm
[org 0x7c00]
bits 16
start:
; ๋ฐ์ดํฐ ์ธ๊ทธ๋จผํธ ๋ ์ง์คํฐ ์ด๊ธฐํ
; Initialize data segment registers
mov ax, 0
mov ds, ax
mov es, ax
; ----------------------------------------------------
; BIOS ์ธํฐ๋ฝํธ๋ฅผ ์ด์ฉํด 320x200 256์ ๊ทธ๋ํฝ ๋ชจ๋๋ก ์ ํ
; Switch to 320x200 256-color graphic mode using BIOS interrupt
; ----------------------------------------------------
mov ah, 0x00 ; ํ๋ฉด ๋ชจ๋ ์ค์ ๊ธฐ๋ฅ ์ ํ
; Select screen mode set function
mov al, 0x13 ; 320x200 256์ ๊ทธ๋ํฝ ๋ชจ๋ ๋ฒํธ (Mode 13h)
; 320x200 256-color graphic mode number (Mode 13h)
int 0x10 ; ๋น๋์ค ์ธํฐ๋ฝํธ ํธ์ถ -> ํ๋ฉด์ด ๊ฒ์์ ๊ทธ๋ํฝ ์ฐฝ์ผ๋ก ์ ํ๋จ
; Call video interrupt -> Screen switches to a black graphic window
; ๋์คํฌ ์ฝ๊ธฐ (2๋ฒ ์นํฐ๋ถํฐ 1๊ฐ ์นํฐ๋ฅผ 0x8000์ ๋ก๋)
; Disk read (Load 1 sector from sector 2 into memory 0x8000)
mov ah, 0x02
mov al, 1
mov ch, 0
mov cl, 2
mov dh, 0
mov bx, 0x8000
int 0x13
; ๋์คํฌ ์ฝ๊ธฐ ์คํจ ์ ์๋ฌ ์ฒ๋ฆฌ
; Error handling if disk read fails
jc disk_error
; ๋ก๋๋ 2๋ฒ ์นํฐ ์ฝ๋๋ก ์ ํํ์ฌ ์คํ
; Jump to the loaded sector 2 code and execute
jmp 0x8000
disk_error:
; ์๋ฌ ๋ฐ์ ์ ์์คํ
๋ฉ์ถค (๊ทธ๋ํฝ ๋ชจ๋์ด๋ฏ๋ก ํ
์คํธ ์ถ๋ ฅ์ ์ผ๋จ ์๋ต)
; System hang on error (Text print is omitted for now since it is in graphic mode)
jmp hang
hang:
jmp $
; 1๋ฒ ์นํฐ(MBR) ๋น ๊ณต๊ฐ์ 0์ผ๋ก ์ฑ์ฐ๊ณ ๋ถํธ ์๊ทธ๋์ฒ ์ถ๊ฐ
; Fill remaining space of sector 1 (MBR) with 0 and add boot signature
times 510 - ($ - $$) db 0
dw 0xaa55
โ๏ธ sector2.asm
[org 0x8000]
bits 16
start:
; ----------------------------------------------------
; ๋ฃจํ(๋ฐ๋ณต๋ฌธ)๋ฅผ ์ฌ์ฉํ์ฌ ํ๋ฉด์ ํผ์งํ ์ฌ๊ฐํ ๊ทธ๋ฆฌ๊ธฐ
; Draw a large rectangle on the screen using loops
; ----------------------------------------------------
; ์ฌ๊ฐํ์ ๊ทธ๋ฆฌ๊ธฐ ์ํ ์์ ์ขํ ๋ฐ ํฌ๊ธฐ ์ค์
; Set starting coordinates and size for drawing the rectangle
; ์์ ์์น(Starting position): X=100, Y=50
; ์ฌ๊ฐํ ํฌ๊ธฐ(Size): ๊ฐ๋ก(Width)=50, ์ธ๋ก(Height)=30
mov dx, 50 ; Y ์ขํ์ ์์๊ฐ ์ค์ (์ธ๋ก)
; Set the starting value of the Y coordinate (Row)
draw_row_loop:
mov cx, 100 ; ์ ํ(Row)์ ์์ํ ๋๋ง๋ค X ์ขํ๋ฅผ ๋ค์ 100์ผ๋ก ์ด๊ธฐํ (๊ฐ๋ก)
; Reset X coordinate to 100 whenever starting a new row (Column)
draw_col_loop:
; BIOS ์ธํฐ๋ฝํธ๋ฅผ ์ฌ์ฉํด ํ์ฌ CX, DX ์์น์ ์ ์ฐ๊ธฐ
; Draw a pixel at the current CX, DX position using BIOS interrupt
mov ah, 0x0c ; ํฝ์
์ฐ๊ธฐ ๊ธฐ๋ฅ
; Write graphics pixel function
mov al, 14 ; ์์ ๋ฒํธ (14 = ๋
ธ๋์)
; Color number (14 = Yellow)
mov bh, 0 ; ํ์ด์ง ๋ฒํธ 0
; Page number 0
int 0x10 ; ํฝ์
์ถ๋ ฅ
; Output pixel
inc cx ; X ์ขํ๋ฅผ ์ค๋ฅธ์ชฝ์ผ๋ก 1์นธ ์ด๋
; Move X coordinate 1 pixel to the right
cmp cx, 150 ; ๊ฐ๋ก ๊ธธ์ด๊ฐ 50ํฝ์
์ด ๋์๋์ง ํ์ธ (100 + 50)
; Check if the width reached 50 pixels (100 + 50)
jl draw_col_loop ; 150๋ณด๋ค ์์ผ๋ฉด ๊ณ์ ๊ฐ๋ก๋ก ์ ์ฐ๊ธฐ
; If less than 150, keep drawing pixels horizontally
; ๊ฐ๋ก ํ ์ค์ ๋ค ์ฑ์ ์ผ๋ฉด ๋ค์ ์ค(์ธ๋ก)๋ก ์ด๋
; Move to the next line (vertically) once a horizontal row is fully drawn
inc dx ; Y ์ขํ๋ฅผ ์๋๋ก 1์นธ ์ด๋
; Move Y coordinate 1 pixel down
cmp dx, 80 ; ์ธ๋ก ๋์ด๊ฐ 30ํฝ์
์ด ๋์๋์ง ํ์ธ (50 + 30)
; Check if the height reached 30 pixels (50 + 30)
jl draw_row_loop ; 80๋ณด๋ค ์์ผ๋ฉด ๋ค์ ์ค๋ก ๋์ด๊ฐ์ ๋ค์ ๊ฐ๋ก ๋ฃจํ ์คํ
; If less than 80, go to the next row and run the horizontal loop again
; ์ฌ๊ฐํ ๊ทธ๋ฆฌ๊ธฐ๊ฐ ๋๋๋ฉด ๋ฌดํ ๋ฃจํ๋ก ๋๊ธฐ
; Infinite loop waiting after rectangle drawing is finished
jmp $
; 512๋ฐ์ดํธ ํฌ๊ธฐ ๋ง์ถ๊ธฐ
; Fill up to 512 bytes
times 512 - ($ - $$) db 0
๐๏ธ ์ปดํ์ผ / compiling
nasm -f bin boot.asm -o boot.bin
nasm -f bin sector2.asm -o sector2.bin
cat boot.bin sector2.bin > temp.bin
dd if=temp.bin of=os.img bs=512 count=2880 conv=sync
qemu-system-x86_64 -drive file=os.img,format=raw,if=floppy -boot a

๐๏ธ ์ฝ๋์ค๋ช / Code Explanation
โ๏ธ boot.asm
–๋ฐ์ดํฐ ์ธ๊ทธ๋จผํธ ๋ ์ง์คํฐ ์ด๊ธฐํ
Initialize data segment registers
start:
; ๋ฐ์ดํฐ ์ธ๊ทธ๋จผํธ ๋ ์ง์คํฐ ์ด๊ธฐํ
; Initialize data segment registers
mov ax, 0
mov ds, ax
mov es, ax
1) ์์ ์ฝ๋๋ ์ด๊ธฐํ๋ง ํ๊ณ ์ฝ๋๊ฐ ์ฌ์ฉ๋๋ ๋ถ๋ถ์ด ์์ต๋๋ค.
The code above only performs initialization; there is no part of the code where it is actually used.
2) ํ์ง๋ง ์ด ์ด๊ธฐํ ์ฝ๋๊ฐ ์์ผ๋ฉด ๋ฐ๋ก ์๋์ ์๋ ๋์คํฌ ์ฝ๊ธฐ ๋ช
๋ น์ด(int 0x13)๊ฐ ์๋ํ์ง ์๊ณ ์๋ฌ๊ฐ ๋ฐ์ํ๊ฒ ๋ฉ๋๋ค.
However, without this initialization code, the disk read command (int 0x13) immediately below it will not work and will result in an error.
3) ์๋ ์ฝ๋์์ ๋ฐ์ดํฐ๋ฅผ ๋ฉ๋ชจ๋ฆฌ 0x8000์ ์ ์ฅํ๋ผ๊ณ bx ๋ ์ง์คํฐ๋ง ์ค์ ํด ์ฃผ์์ต๋๋ค.
In the code below, I only configured the bx register to store data at memory address 0x8000.
4) ํ์ง๋ง BIOS์ ๋์คํฌ ์ฝ๊ธฐ ๊ธฐ๋ฅ์ ๋ฌด์กฐ๊ฑด es์ bx ๋ ๋ ์ง์คํฐ๋ฅผ ํฉ์น ์ฃผ์(es:bx)๋ฅผ ๋ชฉ์ ์ง๋ก ์ธ์ํ๋๋ก ํ๋์จ์ด ๊ท์น์ด ์ ํด์ ธ ์์ต๋๋ค.
However, hardware rules dictate that the BIOS disk read function must treat the address formed by combining the es and bx registers (es:bx) as the destination.
5) ๊ทธ๋์ ์ฐ๋ ๊ธฐ ๊ฐ์ด ๋ค์ด์์ง ์๊ฒ ์ด๊ธฐํ๊ฐ ๋ฐ๋์ ํ์ํฉ๋๋ค.
Therefore, initialization is essential to ensure it does not contain garbage values.
1) ์์ ์ฝ๋๋ ์ด๊ธฐํ๋ง ํ๊ณ ์ฝ๋๊ฐ ์ฌ์ฉ๋๋ ๋ถ๋ถ์ด ์์ต๋๋ค.
The code above only performs initialization; there is no part of the code where it is actually used.
2) ํ์ง๋ง ์ด ์ด๊ธฐํ ์ฝ๋๊ฐ ์์ผ๋ฉด ๋ฐ๋ก ์๋์ ์๋ ๋์คํฌ ์ฝ๊ธฐ ๋ช
๋ น์ด(int 0x13)๊ฐ ์๋ํ์ง ์๊ณ ์๋ฌ๊ฐ ๋ฐ์ํ๊ฒ ๋ฉ๋๋ค.
However, without this initialization code, the disk read command (int 0x13) immediately below it will not work and will result in an error.
3) ์๋ ์ฝ๋์์ ๋ฐ์ดํฐ๋ฅผ ๋ฉ๋ชจ๋ฆฌ 0x8000์ ์ ์ฅํ๋ผ๊ณ bx ๋ ์ง์คํฐ๋ง ์ค์ ํด ์ฃผ์์ต๋๋ค.
In the code below, I only configured the bx register to store data at memory address 0x8000.
4) ํ์ง๋ง BIOS์ ๋์คํฌ ์ฝ๊ธฐ ๊ธฐ๋ฅ์ ๋ฌด์กฐ๊ฑด es์ bx ๋ ๋ ์ง์คํฐ๋ฅผ ํฉ์น ์ฃผ์(es:bx)๋ฅผ ๋ชฉ์ ์ง๋ก ์ธ์ํ๋๋ก ํ๋์จ์ด ๊ท์น์ด ์ ํด์ ธ ์์ต๋๋ค.
However, hardware rules dictate that the BIOS disk read function must treat the address formed by combining the es and bx registers (es:bx) as the destination.
5) ๊ทธ๋์ ์ฐ๋ ๊ธฐ ๊ฐ์ด ๋ค์ด์์ง ์๊ฒ ์ด๊ธฐํ๊ฐ ๋ฐ๋์ ํ์ํฉ๋๋ค.
Therefore, initialization is essential to ensure it does not contain garbage values.
mov bx, 0x8000
int 0x13
— ๊ทธ๋ํฝ ๋ชจ๋ ์ ํ
Switch Graphics Mode
1) ์ด ๋ถ๋ถ์ด ์ค์ ๋ก ๊ทธ๋ํฝ ๋ชจ๋๋ก ์ ํํ๋ ๋ถ๋ถ์
๋๋ค.
This is the part where it actually switches to graphics mode.
mov ah, 0x00 ; ํ๋ฉด ๋ชจ๋ ์ค์ ๊ธฐ๋ฅ ์ ํ
; Select screen mode set function
mov al, 0x13 ; 320x200 256์ ๊ทธ๋ํฝ ๋ชจ๋ ๋ฒํธ (Mode 13h)
; 320x200 256-color graphic mode number (Mode 13h)
int 0x10 ; ๋น๋์ค ์ธํฐ๋ฝํธ ํธ์ถ -> ํ๋ฉด์ด ๊ฒ์์ ๊ทธ๋ํฝ ์ฐฝ์ผ๋ก ์ ํ๋จ
; Call video interrupt -> Screen switches to a black graphic window
— ๋๋จธ์ง ์ฝ๋๋ ๊ธฐ์กด ์ฝ๋์ ๋์ผํฉ๋๋ค.
The rest of the code is identical to the existing code.
— ๋ฐ์ดํฐ ์ฝ์ด์ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํ๊ธฐ,์๋ฌ์ฒ๋ฆฌ,๋ถํธ์๊ทธ๋์ฒ ์ถ๊ฐ
Reading data and storing it in memory, error handling, and adding a boot signature.
โ๏ธ sector2.asm
๐ ๋ชจ๋ํฐ ์ขํ๋ ์ข์ธก ์๋จ์ด 0.0์ด๊ณ ์ค๋ฅธ์ชฝ์ผ๋ก ์ด๋ํ ์๋ก ์๋๋ก ์ด๋ํ ์๋ก ๊ฐ์ด ์ปค์ง๋๋ค.
For monitor coordinates, the top-left corner is (0, 0), and the values โโincrease as you move to the right or downward.
— ์์์ ์๋๋ก 50๋ฒ์งธ ํฝ์
(์ ) ์์น์ ์ค์ ์๋ฏธํฉ๋๋ค.
It refers to the line located at the 50th pixel (dot) position from the top.
mov dx, 50 ; Y ์ขํ์ ์์๊ฐ ์ค์ (์ธ๋ก)
; Set the starting value of the Y coordinate (Row)
— ์ผ์ชฝ์์ ์ค๋ฅธ์ชฝ์ผ๋ก 100ํฝ์
๋จ์ด์ง ์์น๋ฅผ ์๋ฏธํฉ๋๋ค.
It refers to a position 100 pixels away from the left.
draw_row_loop:
mov cx, 100 ; ์ ํ(Row)์ ์์ํ ๋๋ง๋ค X ์ขํ๋ฅผ ๋ค์ 100์ผ๋ก ์ด๊ธฐํ (๊ฐ๋ก)
; Reset X coordinate to 100 whenever starting a new row (Column)
— 1ํฝ์
์ฉ ์ ์ ์ฐ์ต๋๋ค.
Place dots one pixel at a time.
— 50ํฝ์
์ ์ ์ 1ํฝ์
์ฉ ๋ค ์ฐ์ผ๋ฉด ๋ค์ ์ค๋ก ์ด๋ํฉ๋๋ค.
After plotting 50 dots one pixel at a time, it moves to the next line.
draw_col_loop:
; BIOS ์ธํฐ๋ฝํธ๋ฅผ ์ฌ์ฉํด ํ์ฌ CX, DX ์์น์ ์ ์ฐ๊ธฐ
; Draw a pixel at the current CX, DX position using BIOS interrupt
mov ah, 0x0c ; ํฝ์
์ฐ๊ธฐ ๊ธฐ๋ฅ
; Write graphics pixel function
mov al, 14 ; ์์ ๋ฒํธ (14 = ๋
ธ๋์)
; Color number (14 = Yellow)
mov bh, 0 ; ํ์ด์ง ๋ฒํธ 0
; Page number 0
int 0x10 ; ํฝ์
์ถ๋ ฅ
; Output pixel
inc cx ; X ์ขํ๋ฅผ ์ค๋ฅธ์ชฝ์ผ๋ก 1์นธ ์ด๋
; Move X coordinate 1 pixel to the right
cmp cx, 150 ; ๊ฐ๋ก ๊ธธ์ด๊ฐ 50ํฝ์
์ด ๋์๋์ง ํ์ธ (100 + 50)
; Check if the width reached 50 pixels (100 + 50)
jl draw_col_loop ; 150๋ณด๋ค ์์ผ๋ฉด ๊ณ์ ๊ฐ๋ก๋ก ์ ์ฐ๊ธฐ
; If less than 150, keep drawing pixels horizontally
— dx50์์ 1ํฝ์
์ด ์ฆ๊ฐ(inc dx)ํ๋ฉด Y๊ฐ์ด 51์ด ๋ฉ๋๋ค.
If dx50 increases by 1 pixel (inc dx), the Y value becomes 51.
— ์ฆ ๋ค์ ์ค๋ถํฐ ์ ์ ์ฐ์ต๋๋ค.(X:100,Y:51)
In other words, start plotting points from the next line (X:100, Y:51).
— ์ธ๋ก ํฌ๊ธฐ๊ฐ 30ํฝ์
์ธ ์ฌ๊ฐํ์ ์ ์ ๋ค ์ฐ์ผ๋ฉด ๋ฃจํ๋ฅผ ๋น ์ ธ๋๊ฐ๋๋ค.
The loop exits once all the points of the 30-pixel-high rectangle have been plotted.
— ๊ทธ๋ผ ๊ฐ๋ก 50ํฝ์
์ธ๋ก 30ํฝ์
์ธ ๋
ธ๋์ ์ฌ๊ฐํ์ ๋ณผ ์ ์์ต๋๋ค.
Then, you will see a yellow rectangle that is 50 pixels wide and 30 pixels high.
— dx50์์ 1ํฝ์
์ด ์ฆ๊ฐ(inc dx)ํ๋ฉด Y๊ฐ์ด 51์ด ๋ฉ๋๋ค.
If dx50 increases by 1 pixel (inc dx), the Y value becomes 51.
— ์ฆ ๋ค์ ์ค๋ถํฐ ์ ์ ์ฐ์ต๋๋ค.(X:100,Y:51)
In other words, start plotting points from the next line (X:100, Y:51).
— ์ธ๋ก ํฌ๊ธฐ๊ฐ 30ํฝ์
์ธ ์ฌ๊ฐํ์ ์ ์ ๋ค ์ฐ์ผ๋ฉด ๋ฃจํ๋ฅผ ๋น ์ ธ๋๊ฐ๋๋ค.
The loop exits once all the points of the 30-pixel-high rectangle have been plotted.
— ๊ทธ๋ผ ๊ฐ๋ก 50ํฝ์
์ธ๋ก 30ํฝ์
์ธ ๋
ธ๋์ ์ฌ๊ฐํ์ ๋ณผ ์ ์์ต๋๋ค.
Then, you will see a yellow rectangle that is 50 pixels wide and 30 pixels high.
; ๊ฐ๋ก ํ ์ค์ ๋ค ์ฑ์ ์ผ๋ฉด ๋ค์ ์ค(์ธ๋ก)๋ก ์ด๋
; Move to the next line (vertically) once a horizontal row is fully drawn
inc dx ; Y ์ขํ๋ฅผ ์๋๋ก 1์นธ ์ด๋
; Move Y coordinate 1 pixel down
cmp dx, 80 ; ์ธ๋ก ๋์ด๊ฐ 30ํฝ์
์ด ๋์๋์ง ํ์ธ (50 + 30)
; Check if the height reached 30 pixels (50 + 30)
jl draw_row_loop ; 80๋ณด๋ค ์์ผ๋ฉด ๋ค์ ์ค๋ก ๋์ด๊ฐ์ ๋ค์ ๊ฐ๋ก ๋ฃจํ ์คํ
; If less than 80, go to the next row and run the horizontal loop again
; ์ฌ๊ฐํ ๊ทธ๋ฆฌ๊ธฐ๊ฐ ๋๋๋ฉด ๋ฌดํ ๋ฃจํ๋ก ๋๊ธฐ
; Infinite loop waiting after rectangle drawing is finished
jmp $