x86 QEMU BIOS COM Interrupt supported?
Posted: Tue Apr 02, 2024 5:28 pm
Hi all, I hopping someone can help me out. I have created what I thought would be a trivial test for a fun bare metal implementation, but I seem to have hit a limit wall, which I can't seem to figure out if it's a qemu limitation or my own
Inspiration came from https://pages.cs.wisc.edu/~bolo/shipyard/3ins4th.html and the goal was to use this to created some hand crafted machine code and execute in bare metal for low level benchmarking. Things like latency for different calls, register access times, memory pipeline performance ect...
Ok, I have this simple code, it's just a bios that does the following, initiates UART on com1, it listens on com1, and do some storing and fetching of bytes. I have been looking at the code for some time now, and the send of the data through qemu seems to fail. I don't have HW to test this on to connect a real serial on it, here is my original code in FASAM. The other two files, are iteration of me testing different areas of the code to see if this was an issue with my com1 setup.
when I was trying to setup the code to simply revert back what I was sending, I could not get it to properly print on the VGA screen what was been sent via the serial console, I have run the code with QEMU -serial stdio and without, but it seems that either way, I can type a character, hit return, CR will trigger, but the value is not correctly printed or submitted.
Start here, this was the original code I started with, the two others it's just me testing things see if I would find something broken.
Thank you all,
Inspiration came from https://pages.cs.wisc.edu/~bolo/shipyard/3ins4th.html and the goal was to use this to created some hand crafted machine code and execute in bare metal for low level benchmarking. Things like latency for different calls, register access times, memory pipeline performance ect...
Ok, I have this simple code, it's just a bios that does the following, initiates UART on com1, it listens on com1, and do some storing and fetching of bytes. I have been looking at the code for some time now, and the send of the data through qemu seems to fail. I don't have HW to test this on to connect a real serial on it, here is my original code in FASAM. The other two files, are iteration of me testing different areas of the code to see if this was an issue with my com1 setup.
when I was trying to setup the code to simply revert back what I was sending, I could not get it to properly print on the VGA screen what was been sent via the serial console, I have run the code with QEMU -serial stdio and without, but it seems that either way, I can type a character, hit return, CR will trigger, but the value is not correctly printed or submitted.
Code: Select all
org 0x7c00 ; BIOS load address
start:
; Initialize the processor (not explicitly done in the code, usually BIOS job)
; Initialize the serial port
mov ah, 0x00 ; Set COM port initialization function
mov al, 0x03 ; Baud rate divisor for 9600 baud
mov dx, 0 ; COM1 port number (0 for COM1)
int 0x14 ; Call BIOS COM interrupt
; Clear the screen
mov ax, 0x0003 ; Set video mode to 80x25 text mode
int 0x10
main_loop:
call read_byte ; Read a byte from the serial port
cmp al, 0x01 ; Check if byte = 01 [fetch]
je fetch_byte
cmp al, 0x02 ; Check if byte = 02 [store]
je store_byte
cmp al, 0x03 ; Check if byte = 03 [call]
je call_subroutine
jmp main_loop ; Loop back if none of the above
fetch_byte:
call read_address ; Get address from the serial port
mov al, [bx] ; Fetch the byte from that address
call send_byte ; Send the byte to the serial port
jmp main_loop
store_byte:
call read_address ; Get address from the serial port
call read_byte ; Get a byte from the serial port
mov [bx], al ; Store the byte at that address
jmp main_loop
call_subroutine:
call read_address ; Get address from the serial port
call far [bx] ; Call the subroutine at that address
jmp main_loop ; Return to the main loop after subroutine
read_address: ; Function to read an address from the serial port
call read_byte ; Read low byte
mov bl, al
call read_byte ; Read high byte
mov bh, al
ret
read_byte: ; Function to read a byte from the serial port
mov dx, 0x3f8 ; COM1 base address
wait_for_data:
in al, dx ; Read line status register
test al, 1 ; Test if data available (bit 0)
jz wait_for_data ; If not, loop until data is available
mov dx, 0x3f8 ; Reset dx to point to the data register
in al, dx ; Read received byte from data register
ret
send_byte: ; Function to send a byte to the serial port
push ax ; Save AX register
mov ah, al ; Move byte to AH for sending
mov dx, 0 ; COM1 port number (0 for COM1)
int 0x14 ; Call BIOS COM interrupt
pop ax ; Restore AX register
ret
; The print_byte and nibble_to_ascii functions are not necessary for the goals
; and have been removed to simplify the code.
times 510-($-$$) db 0 ; Pad remaining bytes with zeros
dw 0xaa55 ; Boot signature
Thank you all,