OSDev.org https://forum.osdev.org/ |
|
x86 QEMU BIOS COM Interrupt supported? https://forum.osdev.org/viewtopic.php?f=1&t=57200 |
Page 1 of 1 |
Author: | jemo07 [ Tue Apr 02, 2024 5:28 pm ] | |||
Post subject: | x86 QEMU BIOS COM Interrupt supported? | |||
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. Attachment: Code: 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 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,
|
Author: | Octocontrabass [ Tue Apr 02, 2024 6:41 pm ] |
Post subject: | Re: x86 QEMU BIOS COM Interrupt supported? |
jemo07 wrote: Code: mov al, 0x03 ; Baud rate divisor for 9600 baud No, that's 110 baud. If you want 9600 baud, set AL to 0xE3. jemo07 wrote: Code: mov al, [bx] ; Fetch the byte from that address mov [bx], al ; Store the byte at that address call far [bx] ; Call the subroutine at that address You never set DS, so you have no idea what addresses these instructions are actually using. jemo07 wrote: Code: mov dx, 0x3f8 ; COM1 base address in al, dx ; Read line status register That's not the line status register, that's the data register. jemo07 wrote: Code: mov ah, al ; Move byte to AH for sending That's not what you need to put in AH before calling INT 0x14. What are you using as your reference for BIOS calls? |
Author: | jemo07 [ Wed Apr 03, 2024 6:04 am ] |
Post subject: | Re: x86 QEMU BIOS COM Interrupt supported? |
Thank you that was most helpful, I had missed some of the suggestions you made... however, I'm thinking that before I get to the fetch/store/jump functions, I need to ensure that my serial communications is correct. For this, I have overly simplified this to see if I can catch some of my errors. Currently, when I assemble the code, I get a "00" for every entry when running qemu with -serial: stdio or with -serial tcp::9600,server,nowait connected through tera term, telnet. Any key sent now produces a "30" hex or "0" in ascii. I have created two files: boot.fasm: Code: ; boot.fasm use16 org 0x7C00 start: cli ; Disable interrupts mov ax, 0x07C0 ; Set up the stack mov ss, ax mov sp, 0x1000 sti ; Enable interrupts call init_uart ; Initialize UART for serial communication ; Set video mode to 80x25 text mode mov ah, 0x00 mov al, 0x03 int 0x10 ; Main loop to echo characters main_loop: call read_byte_from_com1 ; Read a byte from COM1 call print_char ; Print the received character jmp main_loop ; Repeat indefinitely ; Include the serial communication routines include 'com.fasm' ; Print a character to the screen print_char: mov ah, 0x0E ; BIOS teletype output mov bh, 0x00 ; Page number mov bl, 0x07 ; Attribute (light grey on black) int 0x10 ; Call BIOS ret times 510-($-$$) db 0 ; Pad the bootloader to 510 bytes dw 0xAA55 ; Boot signature And com.fasm: Code: ; com.fasm
use16 PORT equ 0x3F8 ; COM1 Base Port ; Initialize UART for serial communication init_uart: pusha ; Save all general-purpose registers ; Disable all UART interrupts mov dx, PORT + 1 ; Interrupt Enable Register mov al, 0x00 ; Disable all interrupts out dx, al ; Set baud rate to 9600 mov dx, PORT + 3 ; Line Control Register mov al, 0x80 ; Enable DLAB (Divisor Latch Access Bit) out dx, al mov ax, 0x000C ; Divisor for 9600 baud rate (12) mov dx, PORT ; Divisor latch low byte out dx, al mov dx, PORT + 1 ; Divisor latch high byte mov al, ah out dx, al ; Set line control register: 8 bits, no parity, 1 stop bit mov dx, PORT + 3 mov al, 0x03 ; 8 bits, no parity, one stop bit out dx, al ; Enable FIFO, clear them, with 1-byte threshold (optional, for simplicity) ;mov dx, PORT + 2 ;mov al, 0x01 ; Enable FIFO & set 1-byte threshold ;out dx, al popa ; Restore all general-purpose registers ret ; Send a byte to COM1 send_byte_to_com1: push ax push dx mov dx, PORT + 5 ; Line Status Register wait_for_transmit_empty: in al, dx test al, 0x20 ; Wait for the transmitter to be empty jz wait_for_transmit_empty pop dx mov dx, PORT pop ax out dx, al ret ; Read a byte from COM1 read_byte_from_com1: push ax push dx mov dx, PORT + 5 ; Line Status Register wait_for_data_ready: in al, dx test al, 0x01 ; Check if data is available jz wait_for_data_ready mov dx, PORT in al, dx pop dx pop ax ret |
Author: | jemo07 [ Wed Apr 03, 2024 11:31 am ] |
Post subject: | Re: x86 QEMU BIOS COM Interrupt supported? |
here is the problem, kept saving AX on the read_byte_from_com1... that left AL untouched Was pointed out on the FASM forum... ! Here is the corrected code: Code: ; Read a byte from COM1
read_byte_from_com1: ; push ax push dx mov dx, PORT + 5 ; Line Status Register wait_for_data_ready: in al, dx test al, 0x01 ; Check if data is available jz wait_for_data_ready mov dx, PORT in al, dx ; Read the byte ; pop ax pop dx ret |
Page 1 of 1 | All times are UTC - 6 hours |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |