[OS] miniOS-5

๐Ÿ‘‰๏ธ help,clear์ด ์™ธ์— version์„ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ช…๋ น์–ด๋ฅผ ์ถ”๊ฐ€ํ•ด ๋ด…๋‹ˆ๋‹ค.
Let’s add a command to check the version, in addition to help and clear.

๐Ÿ‘‰๏ธ ๊ธฐ์กด ์ฝ”๋“œ์—์„œ ์ถ”๊ฐ€๋˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„๋งŒ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.๋‚˜๋จธ์ง€๋Š” ์ด์ „๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.
Only the parts added to or modified from the existing code are explained here; the rest remains the same.

๐Ÿ‘‰๏ธ ์ปดํŒŒ์ผ ํ•  ํŒŒ์ผ์€ boot.asm๊ณผ sector2.asm ๋‘๊ฐœ์ž…๋‹ˆ๋‹ค.
The files to be compiled are boot.asm and sector2.asm.

๐Ÿ‘‰๏ธ boot.asm๊ธฐ์กด๊ณผ ๋™์ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์„ค๋ช…์„ ์ƒ๋žตํ•ฉ๋‹ˆ๋‹ค.
I will skip the explanation for boot.asm, as it remains the same as before.

๐Ÿ‘‰๏ธ ์ „์ฒด์ฝ”๋“œ / Full code

[org 0x8000]
bits 16

start:
    ; ์›ฐ์ปด ๋ฉ”์‹œ์ง€ ์ถœ๋ ฅ
    ; Print welcome message
    mov si, msg_welcome
    call print_string

; ํ”„๋กฌํ”„ํŠธ(miniOS> )๋ฅผ ์ถœ๋ ฅํ•˜๊ณ  ์ž…๋ ฅ์„ ์ค€๋น„ํ•˜๋Š” ๊ณณ
; The place to print the prompt (miniOS> ) and prepare for input
prompt:
    mov si, msg_prompt
    call print_string

    ; ์ž…๋ ฅ ๋ฒ„ํผ๋ฅผ ๊ฐ€๋ฆฌํ‚ฌ ํฌ์ธํ„ฐ(DI)๋ฅผ ๋ฒ„ํผ์˜ ์‹œ์ž‘ ์ฃผ์†Œ๋กœ ์ดˆ๊ธฐํ™”
    ; Initialize the pointer (DI) pointing to the input buffer with the starting address of the buffer
    mov di, cmd_buffer
    mov cx, 0           ; ์ž…๋ ฅ๋œ ๊ธ€์ž ์ˆ˜๋ฅผ ์„ธ๊ธฐ ์œ„ํ•œ ์นด์šดํ„ฐ
                        ; Counter to count the number of entered characters

; ํ‚ค๋ณด๋“œ ์ž…๋ ฅ์„ ํ•œ ๊ธ€์ž์”ฉ ๋ฐ›๋Š” ๋ฃจํ”„
; A loop that receives keyboard input character by character
key_loop:
    mov ah, 0x00
    int 0x16            ; ํ‚ค๋ณด๋“œ ์ž…๋ ฅ ๋ฐ›๊ธฐ (AL์— ASCII ์ฝ”๋“œ ์ €์žฅ)
                        ; Get keyboard input (Store ASCII code in AL)

    ; ์—”ํ„ฐ ํ‚ค(13)๋ฅผ ๋ˆŒ๋ €๋Š”์ง€ ํ™•์ธ
    ; Check if the Enter key (13) was pressed
    cmp al, 13
    je check_command

    ; ๋ฐฑ์ŠคํŽ˜์ด์Šค ํ‚ค(8) ์ฒ˜๋ฆฌ (๊ธ€์ž ์ง€์šฐ๊ธฐ)
    ; Process Backspace key (8) (Erase character)
    cmp al, 8
    je backspace

    ; ๋ฒ„ํผ ๋„˜์นจ ๋ฐฉ์ง€ (์ตœ๋Œ€ 15๊ธ€์ž๋งŒ ์ž…๋ ฅ ๊ฐ€๋Šฅ)
    ; Prevent buffer overflow (Max 15 characters allowed)
    cmp cx, 15
    je key_loop

    ; ํ™”๋ฉด์— ๊ธ€์ž ์ถœ๋ ฅ (์—์ฝ”)
    ; Output character to screen (Echo)
    mov ah, 0x0e
    int 0x10

    ; ์ž…๋ ฅ๋ฐ›์€ ๋ฌธ์ž๋ฅผ ๋ฒ„ํผ์— ์ €์žฅํ•˜๊ณ  ํฌ์ธํ„ฐ(DI) ์ด๋™
    ; Save the received character to the buffer and move the pointer (DI)
    mov [di], al
    inc di
    inc cx              ; ๊ธ€์ž ์ˆ˜ ์ฆ๊ฐ€
                        ; Increment character count
    jmp key_loop

; ๋ฐฑ์ŠคํŽ˜์ด์Šค ์ฒ˜๋ฆฌ ๋ฃจํ‹ด
; Backspace processing routine
backspace:
    cmp cx, 0           ; ์ž…๋ ฅ๋œ ๊ธ€์ž๊ฐ€ ์—†์œผ๋ฉด ๋ฌด์‹œ
                        ; Ignore if no characters are entered
    je key_loop
    
    ; ํ™”๋ฉด์—์„œ ๊ธ€์ž ์ง€์šฐ๊ธฐ (์™ผ์ชฝ ์ด๋™ -> ๊ณต๋ฐฑ ์ถœ๋ ฅ -> ๋‹ค์‹œ ์™ผ์ชฝ ์ด๋™)
    ; Erase character from screen (Move left -> Output space -> Move left again)
    mov ah, 0x0e
    mov al, 8
    int 0x10
    mov al, ' '
    int 0x10
    mov al, 8
    int 0x10

    dec di              ; ๋ฒ„ํผ ํฌ์ธํ„ฐ 1 ๊ฐ์†Œ
                        ; Decrement buffer pointer by 1
    dec cx              ; ๊ธ€์ž ์ˆ˜ 1 ๊ฐ์†Œ
                        ; Decrement character count by 1
    jmp key_loop

; ์—”ํ„ฐ๋ฅผ ์ณค์„ ๋•Œ ์ž…๋ ฅ๋œ ๋ช…๋ น์–ด๋ฅผ ๋น„๊ตํ•˜๋Š” ๊ณณ
; The place to compare the entered command when Enter is pressed
check_command:
    ; ๋ฌธ์ž์—ด์˜ ๋์„ ํ‘œ์‹œํ•˜๊ธฐ ์œ„ํ•ด ๋ฒ„ํผ์˜ ํ˜„์žฌ ์œ„์น˜์— 0(Null) ์‚ฝ์ž…
    ; Insert 0 (Null) at the current location of the buffer to mark the end of the string
    mov byte [di], 0

    ; ์ค„๋ฐ”๊ฟˆ ์ถœ๋ ฅ
    ; Output newline
    call print_newline

    ; ์ž…๋ ฅ๋œ ๊ธ€์ž๊ฐ€ ์•„์˜ˆ ์—†์œผ๋ฉด ๊ทธ๋ƒฅ ๋‹ค์Œ ํ”„๋กฌํ”„ํŠธ๋กœ
    ; If no characters are entered at all, just go to the next prompt
    cmp cx, 0
    je prompt

    ; 1. 'help' ๋ช…๋ น์–ด ๋น„๊ต
    ; 1. Compare 'help' command
    mov si, cmd_buffer
    mov di, cmd_help
    call compare_string
    je do_help          ; ๊ฐ™์œผ๋ฉด do_help๋กœ ์ ํ”„
                        ; If equal, jump to do_help

    ; 2. 'clear' ๋ช…๋ น์–ด ๋น„๊ต
    ; 2. Compare 'clear' command
    mov si, cmd_buffer
    mov di, cmd_clear
    call compare_string
    je do_clear         ; ๊ฐ™์œผ๋ฉด do_clear๋กœ ์ ํ”„
                        ; If equal, jump to do_clear

    ; ----------------------------------------------------
    ; ๐Ÿ‘ [์ถ”๊ฐ€๋œ ๋ถ€๋ถ„ /] 3. 'version' ๋ช…๋ น์–ด ๋น„๊ต 
    ;     [ Added Part ] 3. 'version' Command Comparison
    ; ----------------------------------------------------
    mov si, cmd_buffer
    mov di, cmd_version
    call compare_string
    je do_version       ; ๊ฐ™์œผ๋ฉด do_version์œผ๋กœ ์ ํ”„
                        ; If equal, jump to do_version
    ; ----------------------------------------------------                    

    ; ์ผ์น˜ํ•˜๋Š” ๋ช…๋ น์–ด๊ฐ€ ์—†์œผ๋ฉด ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ์ถœ๋ ฅ
    ; If no matching command is found, print error message
    mov si, msg_unknown
    call print_string
    jmp prompt

; [๋ช…๋ น์–ด ์ฒ˜๋ฆฌ] help ๊ตฌํ˜„
; [Command Processing] Implement help
do_help:
    mov si, msg_help_text
    call print_string
    jmp prompt

; [๋ช…๋ น์–ด ์ฒ˜๋ฆฌ] clear ๊ตฌํ˜„
; [Command Processing] Implement clear
do_clear:
    ; BIOS ํ™”๋ฉด ์Šคํฌ๋กค ๊ธฐ๋Šฅ์„ ์ด์šฉํ•ด ํ™”๋ฉด ์ง€์šฐ๊ธฐ
    ; Clear screen using BIOS screen scroll function
    mov ah, 0x06        ; ์Šคํฌ๋กค ์—… ๊ธฐ๋Šฅ
                        ; Scroll up function
    mov al, 0           ; 0 = ํ™”๋ฉด ์ „์ฒด ์ง€์šฐ๊ธฐ
                        ; 0 = Clear entire screen
    mov bh, 0x07        ; ๋ฐ”ํƒ•์ƒ‰ ๊ฒ€์ •, ๊ธ€์ž์ƒ‰ ํฐ์ƒ‰
                        ; Background black, Foreground white
    mov ch, 0           ; ์ขŒ์ƒ๋‹จ ํ–‰
                        ; Upper left row
    mov cl, 0           ; ์ขŒ์ƒ๋‹จ ์—ด
                        ; Upper left column
    mov dh, 24          ; ์šฐํ•˜๋‹จ ํ–‰
                        ; Lower right row
    mov dl, 79          ; ์šฐํ•˜๋‹จ ์—ด
                        ; Lower right column
    int 0x10

    ; ์ปค์„œ๋ฅผ ๋งจ ์œ„ ์ขŒ์ƒ๋‹จ(0,0)์œผ๋กœ ์ด๋™
    ; Move cursor to the top-left corner (0,0)
    mov ah, 0x02
    mov bh, 0
    mov dh, 0
    mov dl, 0
    int 0x10

    jmp prompt


; ----------------------------------------------------
; ๐Ÿ‘ [์ถ”๊ฐ€๋œ ๋ถ€๋ถ„] [๋ช…๋ น์–ด ์ฒ˜๋ฆฌ] version ๊ตฌํ˜„
;     [Added Part] [Instruction processing] version implementation
; ----------------------------------------------------
do_version:
    mov si, msg_version_text
    call print_string
    jmp prompt
; ----------------------------------------------------    

; [ํ•จ์ˆ˜] ๋‘ ๋ฌธ์ž์—ด์ด ๊ฐ™์€์ง€ ๋น„๊ต (SI์™€ DI ์ฃผ์†Œ์˜ ๋ฌธ์ž์—ด ๋น„๊ต)
; [Function] Compare if two strings are equal (Compare strings at SI and DI addresses)
compare_string:
.loop:
    mov al, [si]
    mov bl, [di]
    cmp al, bl          ; ๋‘ ๊ธ€์ž๊ฐ€ ๊ฐ™์€์ง€ ๋น„๊ต
                        ; Compare if two characters are equal
    jne .not_equal      ; ๋‹ค๋ฅด๋ฉด ํƒˆ์ถœ
                        ; If not equal, escape
    cmp al, 0           ; ๋ฌธ์ž์—ด์ด ๋๋‚ฌ๋Š”์ง€ ํ™•์ธ (๋‘˜ ๋‹ค 0์ธ ์ƒํ™ฉ)
                        ; Check if the string ended (Both are 0 case)
    je .equal           ; ๋๋‚ฌ์œผ๋ฉด ์™„๋ฒฝํžˆ ์ผ์น˜
                        ; If ended, perfect match
    inc si
    inc di
    jmp .loop
.not_equal:
    clc                 ; Carry Flag ํด๋ฆฌ์–ด (๊ฐ™์ง€ ์•Š์Œ ํ‘œ์‹œ, ์–ต์ง€ flag ์„ธํŒ…์šฉ์œผ๋กœ cmp ํ™œ์šฉ)
                        ; Clear Carry Flag (Indicate not equal, use cmp for forced flag setting)
    mov al, 1
    cmp al, 0           ; Zero Flag๋ฅผ 0์œผ๋กœ ๋งŒ๋“ค์–ด '๋‹ค๋ฆ„'์„ ์•Œ๋ฆผ
                        ; Set Zero Flag to 0 to notify 'Not Equal'
    ret
.equal:
    cmp al, 0           ; Zero Flag๋ฅผ 1๋กœ ๋งŒ๋“ค์–ด '๊ฐ™์Œ'์„ ์•Œ๋ฆผ (AL์ด 0์ด๋ฏ€๋กœ)
                        ; Set Zero Flag to 1 to notify 'Equal' (Since AL is 0)
    ret

; [ํ•จ์ˆ˜] ๋ฌธ์ž์—ด ์ถœ๋ ฅ
; [Function] Print string
print_string:
    lodsb
    cmp al, 0
    je .done
    mov ah, 0x0e
    int 0x10
    jmp print_string
.done:
    ret

; [ํ•จ์ˆ˜] ์ค„๋ฐ”๊ฟˆ ์ถœ๋ ฅ
; [Function] Print newline
print_newline:
    mov ah, 0x0e
    mov al, 13
    int 0x10
    mov al, 10
    int 0x10
    ret

; ----------------------------------------------------
; ๋ฐ์ดํ„ฐ ๋ฐ ๋ณ€์ˆ˜ ์„ ์–ธ ์˜์—ญ (์ „์—ญ ๋ณ€์ˆ˜)
; Data and variable declaration area (Global variables)
; ----------------------------------------------------
msg_welcome   db '3. Hello from Sector 2! miniOS Shell Started.', 13, 10, 0
msg_prompt    db 'miniOS> ', 0
msg_unknown   db 'Unknown command! Type "help".', 13, 10, 0

; ๐Ÿ‘ [์ˆ˜์ •๋œ ๋ถ€๋ถ„] help ํ…์ŠคํŠธ ๋ชฉ๋ก์— version ๋ช…์‹œ
;     [Modified] Specified the version in the help text list.
msg_help_text db 'Available commands: help, clear, version', 13, 10, 0
; ----------------------------------------------------
; ๐Ÿ‘ [์ถ”๊ฐ€๋œ ๋ถ€๋ถ„ ] version ์ถœ๋ ฅ์šฉ ๋ณ€์ˆ˜ ์„ ์–ธ
;     [Added Part] Variable declaration for version output
; ----------------------------------------------------
msg_version_text db 'miniOS version 1.0.0 (Compiled in 2026)', 13, 10, 0
; ----------------------------------------------------

; ๋น„๊ตํ•  ๋ช…๋ น์–ด ๊ธฐ์ค€ ๋ฌธ์ž์—ด (์ƒ์ˆ˜)
; Reference command strings for comparison (Constants)
cmd_help      db 'help', 0
cmd_clear     db 'clear', 0
; ----------------------------------------------------
; ๐Ÿ‘ [ ์ถ”๊ฐ€๋œ ๋ถ€๋ถ„ ] ๋น„๊ตํ•  ๋ช…๋ น์–ด ๊ธฐ์ค€ ๋ณ€์ˆ˜ ์„ ์–ธ
;     [ Added Part ] Declare a variable to serve as the basis for the command comparison.
; ----------------------------------------------------
cmd_version   db 'version', 0
; ----------------------------------------------------

; ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๊ธ€์ž๋“ค์„ ๋‹ด์„ '๋นˆ ๋ณ€์ˆ˜ ๊ณต๊ฐ„' (๋ฒ„ํผ)
; 'Empty variable space' to hold characters entered by the user (Buffer)
; 16๋ฐ”์ดํŠธ ํฌ๊ธฐ๋งŒํผ ๊ณต๊ฐ„์„ ๋ฏธ๋ฆฌ ํ™•๋ณดํ•ด ๋‘ก๋‹ˆ๋‹ค.
; Pre-allocate space of 16 bytes.
cmd_buffer    times 16 db 0

; 512๋ฐ”์ดํŠธ ํฌ๊ธฐ ๋งž์ถ”๊ธฐ
; Fill up to 512 bytes
times 512 - ($ - $$) db 0

๐Ÿ‘‰๏ธ ๋นŒ๋“œ / build

# 1๋ฒˆ ์„นํ„ฐ ์ปดํŒŒ์ผ
# Sector 1 Compilation
# nasm -f bin boot.asm -o boot.bin

# 1. 2๋ฒˆ ์„นํ„ฐ ์ƒˆ๋กœ ์ปดํŒŒ์ผ
# 1. Recompile Sector 2
nasm -f bin sector2.asm -o sector2.bin

# 2. ํ•ฉ์น˜๊ธฐ ๋ฐ 1.44MB ์ด๋ฏธ์ง€ ๊ทœ๊ฒฉํ™”
# 2. Merging and Standardizing to 1.44MB Image Format
cat boot.bin sector2.bin > temp.bin
dd if=temp.bin of=os.img bs=512 count=2880 conv=sync

# 3. QEMU ๋ถ€ํŒ…์ˆœ์„œ ๊ฐ•์ œ ์ง€์ • ์‹คํ–‰
# 3. Running QEMU with a Forced Boot Order
qemu-system-x86_64 -drive file=os.img,format=raw,if=floppy -boot a

๐Ÿ‘‰๏ธ ์ฝ”๋“œ์„ค๋ช… / Code Explanation

โœ”๏ธ cmd_buffer์— ์ž…๋ ค๋œ ๋‚ด์šฉ๊ณผ cmd_version์˜ ๋‚ด์šฉ๊ณผ ๋น„๊ตํ•ด์„œ ์ผ์น˜ํ•˜๋ฉด(compare_string) do_version์œผ๋กœ ์ ํ”„ํ•ฉ๋‹ˆ๋‹ค.
The content entered into cmd_buffer is compared with the content of cmd_version; if they match (via compare_string), the execution jumps to do_version.

    mov si, cmd_buffer
    mov di, cmd_version
    call compare_string
    je do_version       ; ๊ฐ™์œผ๋ฉด do_version์œผ๋กœ ์ ํ”„
                        ; If equal, jump to do_version
cmd_version   db 'version', 0

โœ”๏ธ ํ™”๋ฉด์— ์‹ค์ œ๋กœ ๋ฒ„์ „์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.
It actually displays the version on the screen.

— si๋ ˆ์ง€์Šคํ„ฐ์— msg_version_text ๋ณ€์ˆ˜๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.
Load the msg_version_text variable into the si register.

— print_stringํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•ด์„œํ™”๋ฉด์— ๋ฒ„์ „์„ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.
Execute the print_string function to display the version on the screen.

— prompt๋ผ๋ฒจ๋กœ ์ ํ”„ํ•ฉ๋‹ˆ๋‹ค.
Jump to the prompt label.

do_version:
    mov si, msg_version_text
    call print_string
    jmp prompt
msg_version_text db 'miniOS version 1.0.0 (Compiled in 2026)', 13, 10, 0

โœ”๏ธ ์•„๋ž˜๋Š” help๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ• ๋•Œ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•œ ๋ช…๋ น์–ด๋กœ version์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.
The ‘version’ command has been added to the list of available commands shown when running the ‘help’ command.

msg_help_text db 'Available commands: help, clear, version', 13, 10, 0

Leave a Reply