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