; mybios2.asm [BITS 16] [ORG 0] bios_start: ; 1. 세그먼트 초기화 mov ax, 0xF000 mov ds, ax mov es, ax xor ax, ax mov ss, ax mov sp, 0x7C00 ; ========================================================== ; [VGA BIOS (Option ROM) 실행하기] ; QEMU는 0xC0000 번지에 표준 VGA BIOS를 올려둡니다. ; 이걸 실행해야 화면이 켜지고 curses가 작동합니다. ; ========================================================== ; 2-1. VGA BIOS가 있는지 확인 (Signature Check) ; 0xC000:0000 = 0x55, 0xC000:0001 = 0xAA 여야 함 mov ax, 0xC000 mov es, ax cmp byte [es:0], 0x55 jne no_vga cmp byte [es:1], 0xAA jne no_vga ; 2-2. VGA BIOS 실행 (Far Call) ; 보통 3번째 바이트부터 코드가 시작됩니다. ; PUSH CS, PUSH IP 방식으로 돌아올 주소를 저장하고 점프합니다. push cs ; 돌아올 세그먼트 (0xF000) push word .vga_ret ; 돌아올 오프셋 (Label 주소) ; 0xC000:0003 으로 점프! push 0xC000 ; VGA Segment push 0x0003 ; VGA Entry Point retf ; (Far Return을 이용한 점프 기법) .vga_ret: ; 여기까지 오면 VGA BIOS가 화면을 초기화하고 돌아온 상태입니다! ; 이제 다시 우리의 세그먼트 복구 mov ax, 0xF000 mov ds, ax mov es, ax ; 3. 화면 파란색으로 칠하기 (이제 먹힘!) mov ax, 0xB800 mov es, ax xor di, di mov cx, 2000 mov ax, 0x1F20 ; 파란바탕 + 공백 rep stosw ; 4. 메시지 출력 mov si, msg_title mov di, 0 call print_vga mov si, msg_menu mov di, 160 call print_vga ; 5. 메인 루프 (키보드 0x60) main_loop: in al, 0x64 test al, 1 jz main_loop in al, 0x60 cmp al, 0x02 ; '1' je action_shutdown cmp al, 0x03 ; '2' je action_reboot jmp main_loop ; --- 에러 처리: VGA BIOS가 없을 때 --- no_vga: ; 시리얼로 에러 메시지라도 보내야 함 (여기선 생략하고 무한루프) cli hlt jmp $ ; =========================================================== ; [Actions] (이전과 동일) ; =========================================================== action_shutdown: mov si, msg_bye mov di, 320 call print_vga ; ACPI PIIX4 Shutdown mov dx, 0xCF8 mov eax, 0x80000B04 out dx, eax mov dx, 0xCFC mov eax, 0x0001 out dx, eax mov dx, 0xCF8 mov eax, 0x80000B40 out dx, eax mov dx, 0xCFC mov eax, 0x0000B001 out dx, eax mov dx, 0xCF8 mov eax, 0x80000B80 out dx, eax mov dx, 0xCFC mov eax, 0x00000001 out dx, eax mov dx, 0xB004 mov ax, 0x2000 out dx, ax hlt jmp $ action_reboot: mov si, msg_reboot mov di, 320 call print_vga mov dx, 0x64 mov al, 0xFE out dx, al hlt jmp $ ; =========================================================== ; [Drivers] ; =========================================================== print_vga: mov ah, 0x1F .loop: lodsb cmp al, 0 je .done stosw jmp .loop .done: ret ; =========================================================== ; [Data] ; =========================================================== msg_title db "=== REAL BIOS (VGA Initialized) ===", 0 msg_menu db "Press [1] to Shutdown, [2] to Reboot", 0 msg_bye db "System Halted.", 0 msg_reboot db "Rebooting...", 0 ; --- BIOS 크기 맞추기 (64KB) --- times 65520-($-$$) db 0 reset_vector: jmp 0xF000:0x0000 times 16-($-reset_vector) db 0