diff --git a/build.nr b/build.nr index 4f66854..6ad20cc 100644 --- a/build.nr +++ b/build.nr @@ -1 +1 @@ -1579 +1581 diff --git a/create_win_release.sh b/create_win_release.sh index 291b80c..df3d63b 100644 --- a/create_win_release.sh +++ b/create_win_release.sh @@ -7,7 +7,7 @@ rm -r ./win-release cd bin printf "${green}Compiling vBIOS...\n${clear}" -./dasm dss/bios/bios.dss -o dragon/bios.bin --save-disassembly disassembly/bios.dds --verbose +./dasm dss/bios/entry.dss -o dragon/bios.bin --save-disassembly disassembly/bios.dds --verbose printf "\n${green}Creating Virtual Disk...\n${clear}" rm dragon/disk1.dr @@ -46,7 +46,7 @@ rm ./bin/disassembly/test2.dds mkdir ./win-release/dss mkdir ./win-release/dss/bios -cp ./bin/dss/bios/bios.dss ./win-release/dss/bios +cp ./bin/dss/bios/* ./win-release/dss/bios cp ./bin/dss/mbr.dss ./win-release/dss cp ./bin/dss/test1.dss ./win-release/dss cp ./bin/dss/test2.dss ./win-release/dss diff --git a/extra/dss/bios/bios.dss b/extra/dss/bios/bios.dss deleted file mode 100644 index 059263c..0000000 --- a/extra/dss/bios/bios.dss +++ /dev/null @@ -1,312 +0,0 @@ -## ============================= 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 - and FL, 0b1111111111111110 ## Disable interrupts - mov FL, ACC - push 0 - call $_load_mbr_data_block - or FL, 0b0000000000000001 ## Enable interrupts - mov FL, ACC - ## ---- - - 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 - 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 - mov R3, 0 ## Used as boolean, 0 = positive, 1 = negative - jle $_print_integer_not_negative, 0 - mov R3, 1 - jeq $_print_integer_overflow_case, 0x8000 - neg ACC - jmp $_print_integer_loop -_print_integer_overflow_case: ## Hardcoded for -32768 (0x8000) - push 56 - push 54 - push 55 - push 50 - push 51 - mov R1, 5 - jmp $_print_integer_loop_end -_print_integer_not_negative: - 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: - mov ACC, R3 - jne $_print_integer_no_sign, 1 - push 45 ## '-' ASCII is 45 - inc R1 -_print_integer_no_sign: - 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_no_sign, 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 diff --git a/extra/dss/bios/drivers.dss b/extra/dss/bios/drivers.dss new file mode 100644 index 0000000..1df8fef --- /dev/null +++ b/extra/dss/bios/drivers.dss @@ -0,0 +1,118 @@ +@guard _DRIVERS_DSS_ + +## ============================= 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 + 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 +## ================================================================================== diff --git a/extra/dss/bios/entry.dss b/extra/dss/bios/entry.dss new file mode 100644 index 0000000..7d4b69b --- /dev/null +++ b/extra/dss/bios/entry.dss @@ -0,0 +1,51 @@ +.load 0x0000 ## BIOS is mapped to address 0x0000 in memory + +@include + +## ============================= 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 + and FL, 0b1111111111111110 ## Disable interrupts + mov FL, ACC + push 0 + call $_load_mbr_data_block + or FL, 0b0000000000000001 ## Enable interrupts + mov FL, ACC + ## ---- + + jmp MemoryAddresses.MBR ## Jump to start of MBR in memory + hlt ## Just in case somehow execution reaches this point +## ======================================================================== + +@include +@include + +.fixed 4096, 0x00 ## BIOS Needs to be 4096 Bytes exactly diff --git a/extra/dss/bios/utils.dss b/extra/dss/bios/utils.dss new file mode 100644 index 0000000..8205ae0 --- /dev/null +++ b/extra/dss/bios/utils.dss @@ -0,0 +1,102 @@ +@guard _UTILS_DSS_ + +@include + +_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 + mov R3, 0 ## Used as boolean, 0 = positive, 1 = negative + jle $_print_integer_not_negative, 0 + mov R3, 1 + jeq $_print_integer_overflow_case, 0x8000 + neg ACC + jmp $_print_integer_loop +_print_integer_overflow_case: ## Hardcoded for -32768 (0x8000) + push 56 + push 54 + push 55 + push 50 + push 51 + mov R1, 5 + jmp $_print_integer_loop_end +_print_integer_not_negative: + 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: + mov ACC, R3 + jne $_print_integer_no_sign, 1 + push 45 ## '-' ASCII is 45 + inc R1 +_print_integer_no_sign: + 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_no_sign, 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 diff --git a/extra/dss/newTest.dss b/extra/dss/newTest.dss index d854d9c..cd39984 100644 --- a/extra/dss/newTest.dss +++ b/extra/dss/newTest.dss @@ -10,7 +10,7 @@ $string "Hello World!!" .code - mov R1, 0x7FF0 ## Zero the counter + mov R1, 0 ## Zero the counter infinite_loop: inc R1 ## Increment the counter div R1, 10 ## Divide the counter by 10 diff --git a/extra/scripts/bios_flash b/extra/scripts/bios_flash index 7f5af9d..e673e16 100644 --- a/extra/scripts/bios_flash +++ b/extra/scripts/bios_flash @@ -5,6 +5,6 @@ clear='\033[0m' printf "${green}Reloading BIOS...\n${clear}" cd .. -cp ../extra/dss/bios/bios.dss ./dss/bios/bios.dss -./dasm dss/bios/bios.dss -o dragon/bios.bin --save-disassembly disassembly/bios.dds --verbose +cp ../extra/dss/bios/* ./dss/bios/ +./dasm dss/bios/entry.dss -o dragon/bios.bin --save-disassembly disassembly/bios.dds --verbose cp dragon/bios.bin ../extra/dragon/bios.bin diff --git a/src/assembler/Assembler.cpp b/src/assembler/Assembler.cpp index 2ce2570..ec228a4 100644 --- a/src/assembler/Assembler.cpp +++ b/src/assembler/Assembler.cpp @@ -14,6 +14,100 @@ namespace dragon { namespace code { + std::vector IncludePreprocessor::loadEntryFile(const ostd::String& filePath) + { + m_guards.clear(); + m_lines.clear(); + m_directory = ""; + m_lines = __load_file(filePath); + if (m_lines.size() == 0) return { }; //TODO: Error + if (filePath.contains("/")) + m_directory = filePath.new_substr(0, filePath.lastIndexOf("/") + 1); + if (!__can_file_be_included(m_lines)) + return { }; //TODO: Error + if (!__include_loop()) return { }; //TODO: Error + std::vector newLines; + for (auto& line : m_lines) + { + line.trim(); + if (line != "") + newLines.push_back(line); + } + m_lines.clear(); + m_lines = newLines; + return m_lines; + } + + bool IncludePreprocessor::__can_file_be_included(std::vector& lines) + { + ostd::String guard_name = ""; + for (auto& line : lines) + { + ostd::String lineEdit = line.new_trim(); + if (lineEdit.new_toLower().startsWith("@guard ")) + { + guard_name = lineEdit.new_substr(7).trim(); + line = ""; + break; + } + } + if (guard_name == "") return true; + for (auto& guard : m_guards) + { + if (guard == guard_name) + return false; + } + m_guards.push_back(guard_name); + return true; + } + + bool IncludePreprocessor::__include_loop(void) + { + std::vector lines = m_lines; + bool included = false; + do + { + included = false; + uint32_t i = 0; + for ( ; i < lines.size(); i++) + { + ostd::String line = lines[i]; + line.trim(); + if (line.new_toLower().startsWith("@include") && line.len() > 8) + { + line.substr(8).trim(); + if (!line.startsWith("<") || !line.endsWith(">")) + return false; + line.substr(1, line.len() - 1).trim(); + auto file_lines = __load_file(m_directory + line); + if (file_lines.size() == 0) + return false; + lines.erase(lines.begin() + i); + if (__can_file_be_included(file_lines)) + { + lines.insert(lines.begin() + i, file_lines.begin(), file_lines.end()); + included = true; + } + break; + } + } + } while(included); + m_lines = lines; + return true; + } + + std::vector IncludePreprocessor::__load_file(const ostd::String& filePath) + { + ostd::TextFileBuffer file(filePath); + if (!file.exists()) + return { }; //TODO: Error + ostd::String source = file.rawContent(); + return ostd::String(source.replaceAll("\t", " ")).tokenize("\n").getRawData(); + } + + + + int32_t Assembler::Application::loadArguments(int argc, char** argv) { if (argc < 2) @@ -101,8 +195,9 @@ namespace dragon m_loadAddress = 0x0000; m_currentDataAddr = 0x0000; m_dataSize = 0x0000; - ostd::TextFileBuffer file(fileName); - loadSource(file.rawContent()); + m_lines = IncludePreprocessor::loadEntryFile(fileName); + if (m_lines.size() == 0) + return { }; //TODO: Error removeComments(); replaceGroupDefines(); replaceDefines(); @@ -125,12 +220,6 @@ namespace dragon return m_code; } - void Assembler::loadSource(ostd::String source) - { - m_rawSource = source; - m_lines = ostd::String(source.replaceAll("\t", " ")).tokenize("\n").getRawData(); - } - ostd::ByteStream Assembler::assembleToFile(ostd::String sourceFileName, ostd::String binaryFileName) { assembleFromFile(sourceFileName); diff --git a/src/assembler/Assembler.hpp b/src/assembler/Assembler.hpp index b2c53ef..d9ac44a 100644 --- a/src/assembler/Assembler.hpp +++ b/src/assembler/Assembler.hpp @@ -12,6 +12,22 @@ namespace dragon } namespace code { + class IncludePreprocessor + { + public: + static std::vector loadEntryFile(const ostd::String& filePath); + + private: + static bool __can_file_be_included(std::vector& lines); + static bool __include_loop(void); + static std::vector __load_file(const ostd::String& filePath); + + private: + inline static std::vector m_lines; + inline static std::vector m_guards; + inline static ostd::String m_directory { "" }; + }; + class Assembler { public: struct tDisassemblyLine @@ -83,7 +99,6 @@ namespace dragon public: static ostd::ByteStream assembleFromFile(ostd::String fileName); - static void loadSource(ostd::String source); static ostd::ByteStream assembleToFile(ostd::String sourceFileName, ostd::String binaryFileName); static ostd::ByteStream assembleToVirtualDisk(ostd::String fileName, hw::VirtualHardDrive& vhdd, uint32_t address); static bool saveDisassemblyToFile(ostd::String fileName); diff --git a/src/debugger/Debugger.cpp b/src/debugger/Debugger.cpp index b3be0e3..24f6e84 100644 --- a/src/debugger/Debugger.cpp +++ b/src/debugger/Debugger.cpp @@ -1416,6 +1416,7 @@ namespace dragon else if (data().command.startsWith("p ") || data().command.startsWith("print ")) { data().command.substr(data().command.indexOf(" ") + 1).trim(); + const uint8_t TYPE_STRING = 0; const uint8_t TYPE_BYTE = 1; const uint8_t TYPE_WORD = 2; const uint8_t TYPE_DWORD = 4; @@ -1429,9 +1430,12 @@ namespace dragon else if (size_str == "word") type = TYPE_WORD; else if (size_str == "dword") type = TYPE_DWORD; else if (size_str == "qword") type = TYPE_QWORD; + else if (size_str == "string") type = TYPE_STRING; } if (data().command.isNumeric()) { + if (type == TYPE_STRING) + type = TYPE_WORD; uint16_t addr = data().command.toInt(); uint16_t end_addr = addr; ostd::String tmp = ""; @@ -1474,7 +1478,6 @@ namespace dragon { ostd::String tmp = ""; tmp.add("*(").add(ostd::Utils::getHexStr(addr, true, 2)); - if (type != TYPE_BYTE) if (size > 1) tmp.add("-").add(ostd::Utils::getHexStr((uint16_t)(addr + size - 1), true, 2)); tmp.add(")"); @@ -1485,13 +1488,22 @@ namespace dragon output().pStyled(rgx); output().fg(ostd::ConsoleColors::White).p(" = "); output().fg(ostd::ConsoleColors::Gray).p("["); + if (type == TYPE_STRING) + output().fg(ostd::ConsoleColors::BrightRed).p("\""); for (uint16_t a = addr; a < addr + size; a++) { uint8_t value = DragonRuntime::memMap.read8(a); + if (type == TYPE_STRING) + { + output().fg(ostd::ConsoleColors::BrightRed).pChar((char)value); + continue; + } output().fg(ostd::ConsoleColors::BrightRed).p(ostd::Utils::getHexStr(value, true, 1)); if (a < addr + size - 1) output().p(" "); } + if (type == TYPE_STRING) + output().fg(ostd::ConsoleColors::BrightRed).p("\""); output().fg(ostd::ConsoleColors::Gray).p("]"); output().reset().nl(); }