## ============================= Memory Mapped Devices and Registers ============================= @group MemoryAddresses MBR 0x1380 INT_VEC 0x1080 DISK_INTERFACE 0x1580 RAM 0x1740 CMOS 0x1000 VGA 0x1600 @end @group CMOS_Settings BOOT_DISK { MemoryAddresses.CMOS + 0x0010 } @end @group VGA_Registers VIDEO_MODE { MemoryAddresses.VGA + 0x0000 } SIGNAL { MemoryAddresses.VGA + 0x0003 } TEXT_SINGLE_CHAR { MemoryAddresses.VGA + 0x0004 } BUFF_START { MemoryAddresses.VGA + 0x00E0 } @end @group VGA_VideoModes TEXT_SINGLE_COLOR 0x00 @end @group Sig_VGA_Text_Single_Color CONTINUE 0x00 PRINT_CHAR 0x02 STORE_CHAR 0x03 PRINT_FLUSH_BUFF 0x04 FLUSH_BUFF 0x05 PRINT_BUFF 0x06 REFRESH_SCREEN 0xE0 CLEAR_SCREEN 0xE1 @end @define S_REG_1 0x07 @define S_REG_2 0x08 @define S_REG_3 0x09 ## =============================================================================================== .load 0x0000 ## BIOS is mapped to address 0x0000 in memory .data $_bios_name "DragonBIOS" $_bios_version_number_maj 0x00, 0x00 $_bios_version_number_min 0x00, 0x03 ## ============================= BIOS Program ============================= .code movb [VGA_Registers.VIDEO_MODE], VGA_VideoModes.TEXT_SINGLE_COLOR ## Enable Text_Single_Color graphics mode mov FL, 0b0000000000000001 ## Zero the FL Register and enable interrupts movb [{MemoryAddresses.INT_VEC + (0x20 * 3)}], 0xFF ## Setting up int 0x20 handler mov [{MemoryAddresses.INT_VEC + (0x20 * 3) + 1}], $_int_20_handler ## -- mov R10, 0x00 ## Setting up int 0x30 handler by using int 0x20 functionality mov R9, $_int_30_handler ## -Passing the handler's address mov R8, 0x30 ## -Passing the interrupt's code to setup int 0x20 ## -Calling int 0x20 with 0x00 as parameter, to set new handler up mov R10, 0x03 mov R9, $_bios_name int 0x30 mov R10, 0x01 mov R9, 32 int 0x30 mov R10, 0x04 mov R9, [$_bios_version_number_maj] int 0x30 mov R10, 0x01 mov R9, 46 int 0x30 mov R10, 0x04 mov R9, [$_bios_version_number_min] int 0x30 mov R10, 0x02 int 0x30 ## MBR Loading //TODO: Figure out why and is not working and FL, 0b1111111111111110 ## Disable interrupts push 0 call $_load_mbr_data_block or FL, 0b0000000000000001 ## Enable interrupts ## ---- //TODO: Figure out why or is not working jmp MemoryAddresses.MBR ## Jump to start of MBR in memory hlt ## Just in case somehow execution reaches this point ## ======================================================================== ## ============================= BIOS Interrupt handler ============================= _int_20_handler: mov ACC, R10 jeq $_int_20_disk_interface, 0x0010 jeq $_int_20_set_new_interrupt_handler, 0x0000 jeq $_int_20_clear_interrupt, 0x0001 jmp $_int_20_end _int_20_disk_interface: movb [{MemoryAddresses.DISK_INTERFACE + 0x1}], *R9 ## Mode inc R9 movb [{MemoryAddresses.DISK_INTERFACE + 0x2}], *R9 ## Disk inc R9 mov [{MemoryAddresses.DISK_INTERFACE + 0x3}], *R9 ## Sector inc R9 inc R9 mov [{MemoryAddresses.DISK_INTERFACE + 0x5}], *R9 ## Address inc R9 inc R9 mov [{MemoryAddresses.DISK_INTERFACE + 0x7}], *R9 ## Size inc R9 inc R9 mov [{MemoryAddresses.DISK_INTERFACE + 0x9}], *R9 ## Memory Address movb [MemoryAddresses.DISK_INTERFACE], 0x00 ## Signal set to "Start Operation" jmp $_int_20_end _int_20_set_new_interrupt_handler: push R8 ## Interrupt Code push R9 ## Handler Address push 2 call $_set_interrupt_vector_entry jmp $_int_20_end _int_20_clear_interrupt: push R9 push 0x0000 push 2 call $_set_interrupt_vector_entry _int_20_end: rti ## ================================================================================== ## ========================== BIOS Video Interrupt handler ========================= _int_30_handler: mov ACC, R10 jeq $_int_30_direct_print_char_text_single, 0x0001 jeq $_int_30_direct_new_line_text_single, 0x0002 jeq $_int_30_direct_print_string_text_single, 0x0003 jeq $_int_30_direct_print_integer_text_single, 0x0004 jeq $_int_30_store_integer_text_single, 0x0005 jeq $_int_30_store_char_text_single, 0x0006 jeq $_int_30_print_buffer_no_flush_text_single, 0x0007 jeq $_int_30_print_buffer_and_flush_text_single, 0x0008 jeq $_int_30_flush_buffer_text_single, 0x0009 jeq $_int_30_store_string_text_single, 0x000A jeq $_int_30_clear_screen, 0x00E0 jeq $_int_30_refresh_screen, 0x00E1 jmp $_int_30_end _int_30_direct_print_char_text_single: movb [VGA_Registers.TEXT_SINGLE_CHAR], R9 movb [VGA_Registers.SIGNAL], Sig_VGA_Text_Single_Color.PRINT_CHAR jmp $_int_30_end _int_30_direct_new_line_text_single: movb [VGA_Registers.TEXT_SINGLE_CHAR], 10 ## New line char code movb [VGA_Registers.SIGNAL], Sig_VGA_Text_Single_Color.STORE_CHAR jmp $_int_30_end _int_30_direct_print_string_text_single: movb R1, *R9 movb [VGA_Registers.TEXT_SINGLE_CHAR], R1 movb [VGA_Registers.SIGNAL], Sig_VGA_Text_Single_Color.PRINT_CHAR inc R9 movb ACC, *R9 jne $_int_30_direct_print_string_text_single, 0 jmp $_int_30_end _int_30_direct_print_integer_text_single: mov reg(S_REG_1), Sig_VGA_Text_Single_Color.PRINT_CHAR push R9 push 1 call $_print_integer jmp $_int_30_end _int_30_store_integer_text_single: mov reg(S_REG_1), Sig_VGA_Text_Single_Color.STORE_CHAR push R9 push 1 call $_print_integer jmp $_int_30_end _int_30_store_char_text_single: movb [VGA_Registers.TEXT_SINGLE_CHAR], R9 movb [VGA_Registers.SIGNAL], Sig_VGA_Text_Single_Color.STORE_CHAR jmp $_int_30_end _int_30_print_buffer_no_flush_text_single: movb [VGA_Registers.SIGNAL], Sig_VGA_Text_Single_Color.PRINT_BUFF _int_30_print_buffer_and_flush_text_single: movb [VGA_Registers.SIGNAL], Sig_VGA_Text_Single_Color.PRINT_FLUSH_BUFF jmp $_int_30_end _int_30_flush_buffer_text_single: movb [VGA_Registers.SIGNAL], Sig_VGA_Text_Single_Color.FLUSH_BUFF jmp $_int_30_end _int_30_store_string_text_single: movb R1, *R9 movb [VGA_Registers.TEXT_SINGLE_CHAR], R1 movb [VGA_Registers.SIGNAL], Sig_VGA_Text_Single_Color.STORE_CHAR inc R9 movb ACC, *R9 jne $_int_30_store_string_text_single, 0 debug_break jmp $_int_30_end _int_30_clear_screen: movb [VGA_Registers.SIGNAL], Sig_VGA_Text_Single_Color.CLEAR_SCREEN jmp $_int_30_end _int_30_refresh_screen: movb [VGA_Registers.SIGNAL], Sig_VGA_Text_Single_Color.REFRESH_SCREEN jmp $_int_30_end _int_30_end: rti ## ================================================================================== _load_mbr_data_block: movb [{MemoryAddresses.DISK_INTERFACE + 0x1}], 0x00 ## Mode = Read movb R1, [CMOS_Settings.BOOT_DISK] movb [{MemoryAddresses.DISK_INTERFACE + 0x2}], R1 ## Disk = Default mov [{MemoryAddresses.DISK_INTERFACE + 0x3}],0x0000 ## Sector = 0x0000 mov [{MemoryAddresses.DISK_INTERFACE + 0x5}],0x0000 ## Address = 0x0000 (Start of Disk) mov [{MemoryAddresses.DISK_INTERFACE + 0x7}], 512 ## Size = 512 (Size of MBR is 512 bytes) mov [{MemoryAddresses.DISK_INTERFACE + 0x9}], MemoryAddresses.MBR ## MemoryAddress = MBR Address in memory movb [MemoryAddresses.DISK_INTERFACE], 0x00 ## Signal = Start _load_mbr_data_block_wait_loop: mov ACC, [{MemoryAddresses.DISK_INTERFACE + 0xB}] ## Moving register into ACC jne $_load_mbr_data_block_wait_loop, 0x00 ## If register not Free, loop around and wait ret _calc_interrupt_vector_address: arg R1 mul R1, 0x03 ## Multiply the interrupt code by 3 for memory alignment mov R1, ACC add R1, MemoryAddresses.INT_VEC ## Add Interrupt Vector base address to Interrupt code mov RV, ACC ret _set_interrupt_vector_entry: arg R1 push R1 push 1 call $_calc_interrupt_vector_address mov R1, RV arg ACC jeq $_set_interrupt_vector_entry_disable, 0x0000 movb *R1, 0xFF jmp $_set_interrupt_vector_entry_end _set_interrupt_vector_entry_disable: movb *R1, 0x00 _set_interrupt_vector_entry_end: inc R1 mov *R1, ACC ret _print_integer: mov R1, 0 arg ACC jne $_print_integer_loop, 0 push 48 ## '0' ASCII is 48 inc R1 jmp $_print_integer_loop_end _print_integer_loop: jeq $_print_integer_loop_end, 0 div ACC, 10 mov R2, ACC add RV, 48 ## '0' ASCII is 48 push ACC inc R1 mov ACC, R2 jmp $_print_integer_loop _print_integer_loop_end: pop R9 dec R1 movb [VGA_Registers.TEXT_SINGLE_CHAR], R9 movb [VGA_Registers.SIGNAL], reg(S_REG_1) mov ACC, R1 jne $_print_integer_loop_end, 0 ret _strlen: arg R1 mov R2, 0 _strlen_loop: movb ACC, *R1 inc R1 jeq $_strlen_loop_end, 0 inc R2 jmp $_strlen_loop _strlen_loop_end: mov RV, R2 ret .fixed 4096, 0x00 ## BIOS Needs to be 4096 Bytes exactly