๐๏ธ 32๋นํธ ๋ณดํธ๋ชจ๋๋ก ์ ํํ๋ ๋ถ๋ถ์
๋๋ค.
This is the part where the system switches to 32-bit protected mode.
๐๏ธ 16๋นํธ์์ ๊ทธ๋ํฝ ๋ชจ๋๋ก ์ค์ ํ๊ณ 32๋นํธ ๋ณดํธ๋ชจ๋๋ก ์ ํํ์ ํ๋ฉด์ ํํฌ์ ์ฌ๊ฐํ์ ๊ทธ๋ฆฌ๋ ์ฝ๋์
๋๋ค.
This code sets the system to 16-bit graphics mode, switches to 32-bit protected mode, and then draws a pink rectangle on the screen.
๐๏ธ ์ ์ฒด ์ฝ๋ / Full Code
โ๏ธ boot.asm
— jmp 0x8000 ์ด ์ฝ๋๋ฅผ ์๋์ฒ๋ผ ์์ ํ์ต๋๋ค.
I modified the jmp 0x8000 code as shown below.
— ๋๋จธ์ง๋ ์ด ์ ๊ณผ ๊ฐ์ ์ค๋ช
์ ์๋ตํฉ๋๋ค.
The rest is the same as before, so I will omit the explanation.
jmp 0x0000:0x8000
โ๏ธ sector2.asm
[org 0x8000]
bits 16
start:
; --------------------------------โโโโโโโโโโโโโโโโ----
; 1. A20 ๊ฒ์ดํธ ํ์ฑํ (ํค๋ณด๋ ์ปจํธ๋กค๋ฌ ์ด์ฉํ ํ์ค ๋ฐฉ์)
; 1. Enable A20 Gate (Standard method using keyboard controller)
; --------------------------------โโโโโโโโโโโโโโโโ----
in al, 0x92
or al, 2
out 0x92, al
; ----------------------------------------------------
; 2. GDT(Global Descriptor Table) ์ ๋ณด๋ฅผ CPU์ ๋ก๋
; 2. Load GDT (Global Descriptor Table) information into CPU
; ----------------------------------------------------
cli ; 32๋นํธ ์ ํ ์ค ๋ฐฉํด๋ฐ์ง ์๋๋ก ํ๋์จ์ด ์ธํฐ๋ฝํธ ๊ธ์ง
; Disable hardware interrupts to avoid interruption during 32-bit transition
lgdt [gdt_pointer] ; GDT ๊ตฌ์กฐ์ฒด์ ์ฃผ์๋ฅผ CPU์ ๋ก๋
; Load the address of the GDT structure into the CPU
; ----------------------------------------------------
; 3. CR0 ๋ ์ง์คํฐ๋ฅผ ์ค์ ํ์ฌ 32๋นํธ ๋ณดํธ ๋ชจ๋ ํ์ฑํ
; 3. Set CR0 register to enable 32-bit Protected Mode
; ----------------------------------------------------
mov eax, cr0 ; CR0 ๋ ์ง์คํฐ ๊ฐ์ ์ผ๋ฐ ๋ ์ง์คํฐ๋ก ๊ฐ์ ธ์ด
; Load the CR0 register value into a general-purpose register.
or eax, 0x00000001 ; 0๋ฒ์งธ ๋นํธ(PE: Protection Enable)๋ฅผ 1๋ก ์ค์
; Set the 0th bit (PE: Protection Enable) to 1.
mov cr0, eax ; ๋ณ๊ฒฝ๋ ๊ฐ์ ๋ค์ CR0์ ์ ์ฉ (์ด ์๊ฐ 32๋นํธ ๋ชจ๋ ํ์ฑํ!)
; Apply the modified value back to CR0 (32-bit mode is activated at this moment!)
; ----------------------------------------------------
; 4. 32๋นํธ ์ธ๊ทธ๋จผํธ ์์ญ์ผ๋ก ๋ฉ๋ฆฌ๋ฐ๊ธฐ(Far Jump)
; 4. Far Jump into 32-bit segment region
; ----------------------------------------------------
; 0x08์ ์๋ GDT์์ ์ ์ํ 32๋นํธ ์ฝ๋ ์ธ๊ทธ๋จผํธ์ ์์น(์คํ์
)์
๋๋ค.
; 0x08 is the offset of the 32-bit code segment defined in the GDT below.
jmp 0x08:protected_start
; ====================================================
; ์ฌ๊ธฐ์๋ถํฐ๋ ์์ ํ 32๋นํธ ๊ธฐ๊ณ์ด๋ก ์คํ๋๋ ๊ตฌ์ญ์
๋๋ค!
; From here, the code executes completely in 32-bit machine code!
; ====================================================
bits 32
protected_start:
; 32๋นํธ์ฉ ๋ฐ์ดํฐ ์ธ๊ทธ๋จผํธ ๋ ์ง์คํฐ๋ค ์ด๊ธฐํ (GDT์ 0x10 ์คํ์
์ฌ์ฉ)
; Initialize 32-bit data segment registers (Using 0x10 offset from GDT)
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
; ----------------------------------------------------
; 5. [32๋นํธ C์ธ์ด ์คํ์ผ ํ
์คํธ] ๋น๋์ค ๋ฉ๋ชจ๋ฆฌ์ ์ง์ ์ฌ๊ฐํ ๊ทธ๋ฆฌ๊ธฐ
; 5. [32-bit C-style Test] Draw a rectangle directly to Video Memory
; ----------------------------------------------------
; BIOS๋ฅผ ๋ชป ์ฐ๋ฏ๋ก ๊ทธ๋ํฝ ๋ชจ๋(VRAM) ์ฃผ์์ธ 0xA0000์ ํฌ์ธํฐ์ฒ๋ผ ์ง์ ๋ฐ์ดํฐ๋ฅผ ์๋๋ค.
; Since BIOS is unavailable, write data directly to 0xA0000 (VRAM address) like a pointer.
mov edi, 0xA0000 ; ๋น๋์ค ๋ฉ๋ชจ๋ฆฌ ์์ ๋ฌผ๋ฆฌ ์ฃผ์
; Video memory starting physical address
; ๊ฐ๋ก 100, ์ธ๋ก 50 ์์น ๊ณ์ฐ: (50 * 320) + 100 = 16100
; Calculate position for X=100, Y=50: (50 * 320) + 100 = 16100
add edi, 16100
mov edx, 0 ; Y ๋ฃจํ ์นด์ดํฐ (์ธ๋ก 30์ค)
; Y loop counter (30 rows)
draw_32bit_row:
mov ecx, 0 ; X ๋ฃจํ ์นด์ดํฐ (๊ฐ๋ก 50์นธ)
; X loop counter (50 columns)
draw_32bit_col:
mov byte [edi], 12 ; ์์ ๋ฒํธ ๋์
(12 = ๋นจ๊ฐ์)
; Assign color number (12 = Red)
inc edi ; ๋ค์ ํฝ์
์ฃผ์๋ก ์ด๋
; Move to the next pixel address
inc ecx
cmp ecx, 50
jl draw_32bit_col
; ๊ฐ๋ก ํ ์ค์ ๋ค ๊ทธ๋ ธ์ผ๋ฉด, ๋ค์ ์ค์ ์์์ ์ผ๋ก EDI ํฌ์ธํฐ ๊ฑด๋๋ฐ๊ธฐ
; After drawing one row, skip EDI pointer to the start of the next row
; ํ ์ค์ด 320ํฝ์
์ธ๋ฐ ๋ฐฉ๊ธ 50ํฝ์
์ ์ ์งํ์ผ๋ฏ๋ก, ๋จ์ 270ํฝ์
๋งํผ ๋ํด์ค๋๋ค.
; Since a single line is 320 pixels and we have just advanced 50 pixels, we add the remaining 270 pixels.
add edi, 270
inc edx
cmp edx, 30
jl draw_32bit_row
; ์์
์๋ฃ ํ ๋ฌดํ ๋๊ธฐ
; Infinite loop after work completion
jmp $
; ----------------------------------------------------
; ๋ฐ์ดํฐ ์์ญ: GDT(Global Descriptor Table) ๊ตฌ์กฐ ์ ์
; Data Area: Define GDT (Global Descriptor Table) Structure
; ----------------------------------------------------
align 4
gdt_start:
; 1. ๋ ๋์คํฌ๋ฆฝํฐ (ํ๋์จ์ด ๊ท๊ฒฉ์ ํ์์ ์ธ ๋น ์ฌ๋กฏ)
; 1. Null Descriptor (Mandatory empty slot by hardware specification)
dd 0, 0
; 2. ์ฝ๋ ์ธ๊ทธ๋จผํธ ๋์คํฌ๋ฆฝํฐ (์คํ์
0x08): ์ ์ฒด 4GB ์์ญ, ์ฝ๊ธฐ/์คํ ๊ฐ๋ฅ
; 2. Code Segment Descriptor (Offset 0x08): Full 4GB range, Read/Execute allowed
dw 0xFFFF, 0x0000
db 0x00, 0x9A, 0xCF, 0x00
; 3. ๋ฐ์ดํฐ ์ธ๊ทธ๋จผํธ ๋์คํฌ๋ฆฝํฐ (์คํ์
0x10): ์ ์ฒด 4GB ์์ญ, ์ฝ๊ธฐ/์ฐ๊ธฐ ๊ฐ๋ฅ
; 3. Data Segment Descriptor (Offset 0x10): Full 4GB range, Read/Write allowed
dw 0xFFFF, 0x0000
db 0x00, 0x92, 0xCF, 0x00
gdt_end:
; CPU์ GDT ์์น๋ฅผ ์ ๋ฌํ๊ธฐ ์ํ ํฌ์ธํฐ ๊ตฌ์กฐ์ฒด (6๋ฐ์ดํธ ํฌ๊ธฐ)
; Pointer structure to deliver GDT position to CPU (6 bytes size)
gdt_pointer:
dw gdt_end - gdt_start - 1 ; GDT์ ํฌ๊ธฐ (Size of GDT)
dd gdt_start ; GDT์ ์์ ์ฃผ์ (Starting address of GDT)
; 512๋ฐ์ดํธ ํฌ๊ธฐ ๋ง์ถ๊ธฐ
; Pad 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
โ๏ธ 1MB ์ด์์ ์์ ๋ฉ๋ชจ๋ฆฌ ์์ญ(System Memory)์ ์ฌ์ฉํ๊ธฐ ์ํด ‘A20 ๊ฒ์ดํธ(A20 Gate)’๋ผ๋ ํ๋์จ์ด ๋น์ฅ์ ํธ๋ ์ฝ๋์
๋๋ค.
This is code that unlocks the hardware mechanism known as the ‘A20 Gate’ to enable the use of memory areas (system memory) above the 1MB mark.
in al, 0x92
or al, 2
out 0x92, al
— ์ด ์ค์ ์ผ๋ก 1MB์ด์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.(์ต๋ 4๊ธฐ๊ฐ ๋ฐ์ดํธ๊น์ง ์ฌ์ฉ๊ฐ๋ฅ)
With this setting, you can use more than 1 MB of memory (up to a maximum of 4 GB).
— 32๋นํธ ๋ณดํธ ๋ชจ๋์์ ์ฌ์ฉํ ์ ์๋ ์ต๋ ๋ฉ๋ชจ๋ฆฌ๊ฐ 4๊ธฐ๊ฐ๋ฐ์ดํธ(4GB)์ธ ์ด์ ๋, 32๋นํธ CPU๊ฐ ํ ๋ฒ์ ๊ฐ๋ฆฌํฌ ์ ์๋ ๋ฐฉ ๋ฒํธ(๋ฉ๋ชจ๋ฆฌ ์ฃผ์)์ ์ด๊ฐ์๊ฐ ๋ฑ 4,294,967,296๊ฐ์ด๊ธฐ ๋๋ฌธ์
๋๋ค.
The reason the maximum memory available in 32-bit protected mode is 4 gigabytes (4GB) is that the total number of room numbers (memory addresses) a 32-bit CPU can reference at once is exactly 4,294,967,296.
— 32๋นํธ๊ฐ ๋ํ๋ผ ์ ์๋ ์ฃผ์: 2ยณยฒ = 4,294,967,296๊ฐ
Addresses representable by 32 bits: 2ยณยฒ = 4,294,967,296
— in al, 0x92
์์คํ
์ ์ด ํฌํธ(0x92)์์ ํ์ฌ ์ค์ ์ํ๋ฅผ 1๋ฐ์ดํธ ์ฝ์ด AL ๋ ์ง์คํฐ์ ์ ์ฅํฉ๋๋ค.
Read the current setting status (1 byte) from system control port 0x92 and store it in the AL register.
— or al, 2
AL ๋ ์ง์คํฐ์ ๊ฐ ์ค ‘2๋ฒ์งธ ๋นํธ'(์ด์ง์๋ก 00000010)๋ฅผ 1๋ก ๊ฐ์ ์ ํํฉ๋๋ค.
Force the ‘second bit’ (00000010 in binary) of the AL register’s value to 1.
1) al๊ณผ 2์๊ฐ์ or์ฐ์ฐ ํฉ๋๋ค.(์)
Perform an OR operation on the values โโof AL and 2. (Example)
0x92 ํฌํธ(port) = 00101001
AL 00101001
2 00000010
-------------------
๊ฒฐ๊ณผ(result)00101011
— out 0x92, al
๋ณ๊ฒฝ๋ ์ค์ ๊ฐ์ ๋ค์ ํฌํธ 0x92์ ๋ณด๋ด์ ํ๋์จ์ด์ ์ ์ฉํฉ๋๋ค.
The modified setting values โโare sent back to port 0x92 to apply them to the hardware.
out 0x92, al
โ๏ธ GDT(Global Descriptor Table) ์ ๋ณด๋ฅผ CPU์ ๋ก๋
Load GDT (Global Descriptor Table) information into CPU
cli ; 32๋นํธ ์ ํ ์ค ๋ฐฉํด๋ฐ์ง ์๋๋ก ํ๋์จ์ด ์ธํฐ๋ฝํธ ๊ธ์ง
; Disable hardware interrupts to avoid interruption during 32-bit transition
lgdt [gdt_pointer] ; GDT ๊ตฌ์กฐ์ฒด์ ์ฃผ์๋ฅผ CPU์ ๋ก๋
; Load the address of the GDT structure into the CPU
— cli : Clear Interrupt Flag
CPU๊ฐ ํ๋์จ์ด ์ธํฐ๋ฝํธ๋ฅผ ๋ฐ์ง ์๋๋ก ์ค์ ํ๋ ๋ช
๋ น์
๋๋ค.
This is a command that configures the CPU not to accept hardware interrupts.
— lgdt [gdt_pointer]
1)32๋นํธ ๋ชจ๋(๋ณดํธ๋ชจ๋)์์๋ ๋ณดํธ ๋ชจ๋์์๋ ์ธ๊ทธ๋จผํธ ๋ ์ง์คํฐ์ ๊ฐ์ด GDT์ ์ํธ๋ฆฌ๋ฅผ ๊ฐ๋ฆฌํค๋ ์ ํ์(Selector)๊ฐ ๋๋ฉฐ, CPU๋ GDT์์ ์ค์ ๋ฉ๋ชจ๋ฆฌ ์์ ์ฃผ์(Base), ํฌ๊ธฐ(Limit), ์ ๊ทผ ๊ถํ ๋ฑ์ ์ฐพ์ ์ฌ์ฉํฉ๋๋ค.
2)์ธ๊ทธ๋จผํธ ๋ ์ง์คํฐ(CS, DS, SS ๋ฑ)๋ ์ด GDT๋ฅผ ๊ธฐ์ค์ผ๋ก ํด์๋ผ๊ณ ์๋ ค์ฃผ๋ ๊ฒ์
๋๋ค.
Segment registers (such as CS, DS, and SS) are configured to be interpreted based on this GDT.
โ๏ธ CR0 ๋ ์ง์คํฐ๋ฅผ ์ค์ ํ์ฌ 32๋นํธ ๋ณดํธ ๋ชจ๋ ํ์ฑํ
Set CR0 register to enable 32-bit Protected Mode
— CS(Code Segment) :
๊ธฐ๊ณ์ด๊ฐ ์ ์ฅ๋ ๋ฉ๋ชจ๋ฆฌ์ ์์น๋ฅผ ์ฐพ๋ ๋ฐ ์ฌ์ฉ๋๋ ๋ ์ง์คํฐ
A register used to locate the memory address where machine code is stored.
— cr0์ ์ง์ ๊ฐ์ ์
๋ ฅ ํ ์ ์์ต๋๋ค.
You cannot directly assign a value to cr0.
— cr0๋ ์ ์ด๋ ์ง์คํธ๋ก ๋ค๋ฅธ ๋นํธ๋ค์ด ๋ค์ด ์๊ธฐ ๋๋ฌธ์ ๊ธฐ์กด ๊ฐ์ ์ฝ์ด์์ 0๋ฒ์งธ ๋นํธ (PE:Protection Enable)๊ฐ๋ง ๋ฐ๊ฟ๋๋ค.
Since cr0 is a control register containing other bits, you must read the existing value and modify only the 0th bit (PE: Protection Enable).
mov eax, cr0 ; CR0 ๋ ์ง์คํฐ ๊ฐ์ ์ผ๋ฐ ๋ ์ง์คํฐ๋ก ๊ฐ์ ธ์ด
; Load the CR0 register value into a general-purpose register.
or eax, 0x00000001 ; 0๋ฒ์งธ ๋นํธ(PE: Protection Enable)๋ฅผ 1๋ก ์ค์
; Set the 0th bit (PE: Protection Enable) to 1.
mov cr0, eax ; ๋ณ๊ฒฝ๋ ๊ฐ์ ๋ค์ CR0์ ์ ์ฉ (์ด ์๊ฐ 32๋นํธ ๋ชจ๋ ํ์ฑํ!)
; Apply the modified value back to CR0 (32-bit mode is activated at this moment!)
โ๏ธ protected_start๋ผ๋ฒจ๋ก far jumpํฉ๋๋ค.
Perform a far jump to protected_start.
jmp 0x08:protected_start
— BIOS(๋ฆฌ์ผ ๋ชจ๋)์์ ์ฌ์ฉํ๋ ์ธ๊ทธ๋จผํธ ์ฃผ์ ๊ณ์ฐ ๋ฐฉ์์ด ๋ณดํธ ๋ชจ๋์์๋ ๋ ์ด์ ์ฌ์ฉ๋์ง ์๊ธฐ ๋๋ฌธ์, CPU๊ฐ ์ฌ์ฉํ ์๋ก์ด ์ธ๊ทธ๋จผํธ ์ ๋ณด(GDT)๋ฅผ lgdt๋ก ๋ฑ๋กํฉ๋๋ค.
Since the segment address calculation method used in BIOS (real mode) is no longer employed in protected mode, the lgdt instruction is used to register the new segment information (GDT) for the CPU.
— 0x08๋ ๋ฆฌ์ผ๋ชจ๋์์ ์ฌ์ฉํ๋ cs๊ฐ์ GDT์ ์ ํ์๋ก ๋ฐ๊ฟ๋๋ค.
0x08 replaces the CS value used in real mode with a GDT selector.
— 0x08๋๋ ์ด์ ์ฃผ์ ๊ฐ์ด ์๋ GDT์ ์ ํ์๊ฐ ๋ฉ๋๋ค.
0x08 is no longer an address value but becomes a GDT selector.
— ๋ฆฌ์ผ๋ชจ๋(16๋นํธ) : CS = ์ค์ ์ธ๊ทธ๋จผํธ ์ฃผ์
Real Mode (16-bit): CS = Actual segment address
— ๋ณดํธ๋ชจ๋(32๋นํธ) : CS = GDT์ ์ฝ๋ ์ธ๊ทธ๋จผํธ ์ ํ์
Protected Mode (32-bit): CS = Code segment selector from the GDT
— GDT์ ๊ตฌ์กฐ
Structure of the GDT
- GDT๊ตฌ์กฐ / GDT Structure
Entry0
Null Descriptor
์ฃผ์ / Address
0x00
Entry1
Code Segment
์ฃผ์ / Address
0x08
Entry2
Data Segment
์ฃผ์ / Address
0x10
- GDT ๊ทธ๋ฆผ / GDT diagram
+----------------+
|0x00 Null |
+----------------+
|0x08 Code | โโโโโ CS
+----------------+
|0x10 Data |
+----------------+
โ
๋ค์ ํฌ์คํธ์์ ๊ณ์๋ฉ๋๋ค.
To be continued in the next post.