๐๏ธ 32๋นํธ ๋ณดํธ๋ชจ๋(๊ทธ๋ํฝ๋ชจ๋)์์ ํ๋ฉด์ ์ฌ๊ฐํ์ ๋ณด์ฌ์ฃผ๋ ์ฝ๋์
๋๋ค.
This is code that displays a rectangle on the screen in 32-bit protected mode (graphics mode).
๐๐ป ์ด์ miniOS-7์์ ์ฝ๋์์ ๋ฐ๋ ๋ถ๋ถ๋ง ์ค๋ช
ํฉ๋๋ค.
This section explains only the changes made to the code from the previous miniOS-7.
๐๐ป ์ฝ๋ / Code
โ๏ธ boot.asm
— boot.asm์์ 2๋ฒ ์นํฐ ์ฝ๋๋ฅผ 1์์ 10์ผ๋ก ์์ ํฉ๋๋ค.
In boot.asm, change the sector code from 1 to 10.
mov al, 10 ; โ
1์์ 10์ผ๋ก ์์ (๋๋ํ๊ฒ ์ฝ์ด์ด)
; Adjusted from 1 to 10 (read with a generous margin)
1)๊ธฐ์กด ์ด์
๋ธ๋ฆฌ ์ฝ๋์ธ์ c์ธ์ด ์ฝ๋๋ฅผ ์ถ๊ฐํ๋ฉด ์ฉ๋์ด ์ฆ๊ฐํ๊ธฐ ๋๋ฌธ์ c์ธ์ด ์ฝ๋์ฉ๋๊น์ง ๊ณ ๋ คํด์ 10์นํฐ๊น์ง ์ฝ์ด ์ค๋๋ก ํฉ๋๋ค.
Since adding C code alongside the existing assembly code increases the total size, the system is configured to read up to 10 sectors to accommodate the C code.
10๊ฐ ์นํฐ ํฌ๊ธฐ: 512๋ฐ์ดํธ ร 10 = 5,120๋ฐ์ดํธ (์ฝ 5KB)
Size of 10 sectors: 512 bytes ร 10 = 5,120 bytes (approx. 5 KB)
2) 10๊ฐ ์นํฐ๋ก ๋๋ํ๊ฒ ์ง์ ํด ๋๋ฉด ์ฝ๋๊ฐ ์๋ฆฌ๋ ์ผ ์์ด ์์ ์ ์ผ๋ก ๋ฉ๋ชจ๋ฆฌ์ ๋ค ๋ก๋๋ฉ๋๋ค.
By generously allocating 10 sectors, the code loads reliably into memory in its entirety without being truncated.
โ๏ธ sector2.asm
— [org 0x8000]๋ฅผ ์ฃผ์์ฒ๋ฆฌ ํ๊ฑฐ๋ ์ ๊ฑฐํฉ๋๋ค.
Comment out or remove [org 0x8000].
; โ
์ฝ๋ ์ ๊ฑฐ / Remove code
;[org 0x8000]
1)[org 0x8000] ์ด ์ฝ๋๋ ์์ ๋ฐ์ด๋๋ฆฌ์ฉ ์
๋๋ค.
[org 0x8000] This code is for a raw binary.
2) ๊ทธ๋์ ์ฝ๋ ์์ ์๋ ๋ณ์๋ ํจ์๋ค์ ์ฃผ์๋ฅผ ๋ฏธ๋ฆฌ 0x8000 ๊ธฐ์ค์ผ๋ก ์ ๋ถ ๊ณ ์ ํด์ ํ๋์ ์์ฑ๋ ๋ฐ์ด๋๋ฆฌ(.bin) ํ์ผ๋ก ์ปดํ์ผํฉ๋๋ค.
Therefore, the addresses of all variables and functions within the code are fixed in advance based on the 0x8000 address, and the code is compiled into a single, complete binary (.bin) file.
3)C์ธ์ด๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ฉด C์ธ์ด ํ์ผ(kernel.c)๊ณผ ์ด์
๋ธ๋ฆฌ ํ์ผ(sector2.asm)์ ํจ๊ป ๋ฌถ์ด์ผ ํฉ๋๋ค.
When using the C language, you must combine the C source file (kernel.c) and the assembly file (sector2.asm).
4)๊ทธ๋์ ์์ ๋ฐ์ด๋๋ฆฌ๊ฐ ์๋, ์กฐ๋ฆฝ์ฉ ๋ถํ ์ํ์ธ ์ค๋ธ์ ํธ ํ์ผ(.o)๋ก ์ปดํ์ผํ๊ฒ ๋ฉ๋๋ค.
Therefore, instead of a pure binary, it is compiled into object files (.o)โcomponents intended for assembly.
5) ๊ทธ๋ฌ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์ปดํ์ผ์ ์คํํฉ๋๋ค.
Then, run the compilation as follows.
ld -m elf_i386 -Ttext 0x8000 -o sector2.bin sector2.o kernel.o --oformat binary
6)์ด๋ ์ด๋ฏธ ์ปดํ์ผํ๋ sector2.o์ kernel.o๋ฅผ ๋ฌถ์ด์ sector2.binํ์ผ์ ์์ฑํ๋ฉฐ text ์น์
0x8000 ์ฃผ์๋ก ์ ๋ ฌํฉ๋๋ค.
At this stage, the previously compiled sector2.o and kernel.o are linked to generate the sector2.bin file, with the text section aligned to address 0x8000.
— text ์น์
์ sector2.bin์์ฑ์ -Ttext 0x8000 ์ด๋ถ๋ถ์์ text๋ก ์น์
๋ค์์ ์ง์ ํ๊ธฐ ๋๋ฌธ์
๋๋ค.
The ‘text’ section is named as such because ‘text’ was specified as the section name using -Ttext 0x8000 when generating sector2.bin.
section .text ; ELF ํฌ๋งท ์ปดํ์ผ์ ์ํด ์ฝ๋ ์น์
์์ ๋ช
์ํฉ๋๋ค.
; Specifies that it is a code section for ELF format compilation.
— ld๋ช
๋ น์ ์ฌ์ฉํ ๋ ๋ง์ปค๊ฐ ์ธ์ํ๊ฒ ํ๋ ค๋ฉด global๋ก ์ ์ธํด์ ์ธ๋ถ์ ๊ณต๊ฐํด์ผ ํฉ๋๋ค.
To ensure the linker recognizes it when using the ld command, you must declare it as global to make it externally visible.
global start ; ๋ง์ปค๊ฐ ์ธ์ํ ์ ์๋๋ก start ๋ ์ด๋ธ์ ์ธ๋ถ์ ๊ณต๊ฐํฉ๋๋ค.
; Expose the `start` label so that the linker can recognize it.
global protected_start ; ๋ฉ๋ฆฌ๋ฐ๊ธฐ ๋ชฉ์ ์ง ๋ ์ด๋ธ๋ ์ธ๋ถ์ ๊ณต๊ฐํฉ๋๋ค.
; We are also making the long-jump destination labels publicly available
— C์ธ์ด ๋ณ์ ๋ฐ ํจ์ ํธ์ถ์ ์ํ ์คํ์์ญ์ ์ง์ ํฉ๋๋ค.
It designates the stack area for C language variables and function calls.
mov esp, 0x90000
— C์ธ์ด์ kernel_mainํจ์๋ฅผ ํธ์ถํฉ๋๋ค.
It calls the C language’s kernel_main function.
call kernel_main ; โ
kernel_main์ผ๋ก ์ ํ!
; Jump to kernel_main!
โ๏ธ kernel.c
–์ด ์ฝ๋์์ ์ค์ ๋ก ์ฌ๊ฐํ์ ๊ทธ๋ฆฝ๋๋ค.
This code actually draws the rectangle.
typedef unsigned char byte;
// 1. ์ํ๋ ์์น(x, y)์ ์ํ๋ ์์(color)์ ์ ์ ์ฐ๋ ํจ์
// 1. A function that plots a point of a specified color at a desired location (x, y).
void draw_pixel(int x, int y, byte color) {
byte *vram = (byte *)0xA0000;
// 320x200 ํด์๋์ 1์ฐจ์ ๋ฐฐ์ด ์์น ๊ณ์ฐ: (y * 320) + x
// Calculation of 1D array position for 320x200 resolution: (y * 320) + x
vram[(y * 320) + x] = color;
}
// 2. ์ํ๋ ์์น, ํฌ๊ธฐ, ์์์ผ๋ก ์ฌ๊ฐํ์ ๊ทธ๋ฆฌ๋ ํจ์
// 2. Function to draw a rectangle at a desired position, size, and color
void draw_rect(int start_x, int start_y, int width, int height, byte color) {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
// ์์์ ๋ง๋ ์ ์ฐ๊ธฐ ํจ์๋ฅผ ํ์ฉ
// Utilize the point-plotting function created above
draw_pixel(start_x + x, start_y + y, color);
}
}
}
// 3. ์ปค๋ ๋ฉ์ธ ํจ์
// 3. Kernel main function
void kernel_main(void) {
// ์์ 1: X=100, Y=50 ์์น์ ๊ฐ๋ก 50, ์ธ๋ก 30 ํฌ๊ธฐ์ ๊ฐ์(6) ์ฌ๊ฐํ
// Example 1: A brown (6) rectangle with a width of 50 and a height of 30 at position X=100, Y=50
draw_rect(100, 50, 50, 30, 6);
// ์์ 2: ๋ค๋ฅธ ์์น์ ํ๋์(9) ์ฌ๊ฐํ ์ถ๊ฐ๋ก ๊ทธ๋ฆฌ๊ธฐ (์์ ๋ณ๊ฒฝ ํ
์คํธ)
// Example 2: Draw an additional blue (9) rectangle at a different location (color change test)
draw_rect(200, 100, 40, 40, 9);
// ์์ 3: ๋ค๋ฅธ ์์น์ ์ด๋ก์(10) ์ฌ๊ฐํ ์ถ๊ฐ๋ก ๊ทธ๋ฆฌ๊ธฐ
// Example 3: Draw an additional green (10) rectangle at a different location.
draw_rect(30, 120, 60, 20, 10);
// ์์
์๋ฃ ํ CPU ๋๊ธฐ
// Wait for CPU after task completion
while (1) {
__asm__ __volatile__("hlt");
}
}
๐๏ธ ์ปดํ์ผ / Compiling
# 1. 1๋ฒ ์นํฐ ๋ถํธ๋ก๋ ์ปดํ์ผ
# Compile Sector 1 Bootloader
nasm -f bin boot.asm -o boot.bin
# 2. 2๋ฒ ์นํฐ ๋ณดํธ๋ชจ๋ ์ง์
๋ถ ์ปดํ์ผ
# Compiling the Sector 2 protection mode entry section
nasm -f elf32 sector2.asm -o sector2.o
# 3. GCC ์ปดํ์ผ ์ ์์น ๋
๋ฆฝ์ ์ฝ๋(PIC)๋ฅผ ์์ฑํ์ง ์๋๋ก ์ต์
์ถ๊ฐ
# Add an option to prevent the generation of position-independent code (PIC) when compiling with GCC.
gcc -m32 -c kernel.c -o kernel.o -nostdlib -fno-builtin -fno-stack-protector -fno-pic -fno-PIE
# 4. ๋ง์ปค(ld)์๊ฒ ์ฝ๋์ ์์์ (Entry)์ด '_start'๊ฐ ์๋๋ผ 'start' ์์ ๋ช
์
# Specify to the linker (ld) that the code entry point is 'start' instead of '_start'
ld -m elf_i386 -Ttext 0x8000 -e start -o sector2.bin sector2.o kernel.o --oformat binary
# 5. ๊ธฐ์กด ๋ฐฉ์๋๋ก ๋์คํฌ ์ด๋ฏธ์ง ๋ณํฉ ๋ฐ QEMU ์คํ
# # 5. Merging Disk Images and Running QEMU Using the Existing Method
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
