I'm trying to write a simple hello world bios for Qemu as an academic exercise, and I've gotten Qemu to believe the display is initialized. I see a black screen upon boot, but writing to character video memory 0xb8000 does nothing. I configured the PCI slot, set the VGA registers for 80x25 text mode, and enabled the display. Am I missing something? why is video memory not producing results on screen?
NASM Assembly I have so far below:
[BITS 16]
times 4194304 - 2000 db 0x00
_jmpTo:
;Configure the VGA's PCI slot (hardcoded for now)
mov eax, 0x80001004
mov dx, 0x0CF8
out dx, eax
mov dx, 0x0CFC
in eax, dx
or eax, 0x0000037F
and eax, 0xFFFFFFFE
or eax, 0x00000002
mov dx, 0x0CFC
out dx, eax
mov eax, 0x80001008
mov dx, 0x0CF8
out dx, eax
mov dx, 0x0CFC
in eax, dx
and eax, 0x0000FFFF
or eax, 0x03000000
out dx, eax
;map BARS
mov eax, 0x80001010
mov dx, 0x0CF8
out dx, eax
mov dx, 0x0CFC
in eax, dx
or eax, 0xe0000000
out dx, eax
mov eax, 0x80001018
mov dx, 0x0CF8
out dx, eax
mov dx, 0x0CFC
in eax, dx
or eax, 0xe1000000
out dx, eax
mov eax, 0x80001030
mov dx, 0x0CF8
out dx, eax
mov dx, 0x0CFC
in eax, dx
or eax, 0xB0000001
out dx, eax
;Set VGA Config Registers via I/O
mov dx, 0x03DA
in eax, dx
mov dx, 0x03C0
mov al, 0x10
out dx, al
mov al, 0x0C
out dx, al
mov dx, 0x03DA
in eax, dx
mov dx, 0x03C0
mov al, 0x11
out dx, al
mov al, 0x00
out dx, al
mov dx, 0x03DA
in eax, dx
mov dx, 0x03C0
mov al, 0x12
out dx, al
mov al, 0x0F
out dx, al
mov dx, 0x03DA
in eax, dx
mov dx, 0x03C0
mov al, 0x13
out dx, al
mov al, 0x08
out dx, al
mov dx, 0x03DA
in eax, dx
mov dx, 0x03C0
mov al, 0x14
out dx, al
mov al, 0x00
out dx, al
mov dx, 0x03C2
mov al, 0x67
out dx, al
mov dx, 0x03C4
mov al, 0x00
out dx, al
mov dx, 0x03C5
mov al, 0x01
out dx, al
mov dx, 0x03C4
mov al, 0x01
out dx, al
mov dx, 0x03C5
mov al, 0x00
out dx, al
mov dx, 0x03C4
mov al, 0x02
out dx, al
mov dx, 0x03C5
mov al, 0x03
out dx, al
mov dx, 0x03C4
mov al, 0x04
out dx, al
mov dx, 0x03C5
mov al, 0x0A
out dx, al
mov dx, 0x03C4
mov al, 0x00
out dx, al
mov dx, 0x03C5
mov al, 0x03
out dx, al
mov dx, 0x03CE
mov al, 0x05
out dx, al
mov dx, 0x03CF
mov al, 0x00
out dx, al
mov dx, 0x03CE
mov al, 0x06
out dx, al
mov dx, 0x03CF
mov al, 0x03
out dx, al
;disable write protect
mov dx, 0x03D4
mov al, 0x11
out dx, al
mov dx, 0x03D5
mov al, 0x00
out dx, al
;crct
mov dx, 0x03D4
mov al, 0x00
out dx, al
mov dx, 0x03D5
mov al, 0x5F
out dx, al
mov dx, 0x03D4
mov al, 0x01
out dx, al
mov dx, 0x03D5
mov al, 0x4F
out dx, al
mov dx, 0x03D4
mov al, 0x02
out dx, al
mov dx, 0x03D5
mov al, 0x50
out dx, al
mov dx, 0x03D4
mov al, 0x03
out dx, al
mov dx, 0x03D5
mov al, 0x82
out dx, al
mov dx, 0x03D4
mov al, 0x04
out dx, al
mov dx, 0x03D5
mov al, 0x55
out dx, al
mov dx, 0x03D4
mov al, 0x06
out dx, al
mov dx, 0x03D5
mov al, 0xB5
out dx, al
mov dx, 0x03D4
mov al, 0x07
out dx, al
mov dx, 0x03D5
mov al, 0x0D
out dx, al
mov dx, 0x03D4
mov al, 0x08
out dx, al
mov dx, 0x03D5
mov al, 0x00
out dx, al
mov dx, 0x03D4
mov al, 0x09
out dx, al
mov dx, 0x03D5
mov al, 0x0F
out dx, al
mov dx, 0x03D4
mov al, 0x0A
out dx, al
mov dx, 0x03D5
mov al, 0x0E
out dx, al
mov dx, 0x03D4
mov al, 0x0B
out dx, al
mov dx, 0x03D5
mov al, 0x0F
out dx, al
mov dx, 0x03D4
mov al, 0x0C
out dx, al
mov dx, 0x03D5
mov al, 0x00
out dx, al
mov dx, 0x03D4
mov al, 0x0D
out dx, al
mov dx, 0x03D5
mov al, 0x00
out dx, al
mov dx, 0x03D4
mov al, 0x0E
out dx, al
mov dx, 0x03D5
mov al, 0x00
out dx, al
mov dx, 0x03D4
mov al, 0x0F
out dx, al
mov dx, 0x03D5
mov al, 0x00
out dx, al
mov dx, 0x03D4
mov al, 0x10
out dx, al
mov dx, 0x03D5
mov al, 0x90
out dx, al
mov dx, 0x03D4
mov al, 0x11
out dx, al
mov dx, 0x03D5
mov al, 0x8C
out dx, al
mov dx, 0x03D4
mov al, 0x12
out dx, al
mov dx, 0x03D5
mov al, 0xAF
out dx, al
mov dx, 0x03D4
mov al, 0x13
out dx, al
mov dx, 0x03D5
mov al, 0x28
out dx, al
mov dx, 0x03D4
mov al, 0x14
out dx, al
mov dx, 0x03D5
mov al, 0x07
out dx, al
mov dx, 0x03D4
mov al, 0x15
out dx, al
mov dx, 0x03D5
mov al, 0x9C
out dx, al
mov dx, 0x03D4
mov al, 0x16
out dx, al
mov dx, 0x03D5
mov al, 0xE3
out dx, al
mov dx, 0x03D4
mov al, 0x17
out dx, al
mov dx, 0x03D5
mov al, 0xE3
out dx, al
;mode control
mov dx, 0x03da
in al, dx
mov al, 0x10
mov dx, 0x03c0
out dx, al
mov al, 0x20
out dx, al
mov dx, 0x03C6
mov al, 0xFF
out dx, al
;enable display
mov dx, 0x03da
in al, dx
mov al, 0x20
mov dx, 0x03c0
out dx, al
mov ax, 0xB800
mov es, ax
mov di, 0x0000
mov al, 0x41
mov ah, 0x07
mov [es:di], ax
_loop:
jmp _loop
hlt
times (4194304 - ($-$$) - 16) db 0x00
_main:
jmp _jmpTo
_end:
times (4194304 - ($-$$)) db 0x00
mov [es:di], alis storing toB000:0000, linear addressB0000. With the same ES segment,mov byte [es: 8000], 'A'will store toB8000. Or you could use ES=B800and use offsets starting from 0 for the start of video RAM, so e.g. you couldxor di,diormov byte [es: 0], 'A'. Use a debugger attached to QEMU to check memory contents.hltinside your infinite loop will make QEMU waste less CPU time when it reaches that, only waking up for interrupts.