[0.2.1580] - Added basic "include" functionality to the assembler

This commit is contained in:
OmniaX-dev 2024-01-13 00:40:47 +01:00
parent 085bdbc75c
commit 713711d247
11 changed files with 403 additions and 328 deletions

View file

@ -1 +1 @@
1579 1581

View file

@ -7,7 +7,7 @@ rm -r ./win-release
cd bin cd bin
printf "${green}Compiling vBIOS...\n${clear}" 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}" printf "\n${green}Creating Virtual Disk...\n${clear}"
rm dragon/disk1.dr rm dragon/disk1.dr
@ -46,7 +46,7 @@ rm ./bin/disassembly/test2.dds
mkdir ./win-release/dss mkdir ./win-release/dss
mkdir ./win-release/dss/bios 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/mbr.dss ./win-release/dss
cp ./bin/dss/test1.dss ./win-release/dss cp ./bin/dss/test1.dss ./win-release/dss
cp ./bin/dss/test2.dss ./win-release/dss cp ./bin/dss/test2.dss ./win-release/dss

View file

@ -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 <Status> register into ACC
jne $_load_mbr_data_block_wait_loop, 0x00 ## If <Status> 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

118
extra/dss/bios/drivers.dss Normal file
View file

@ -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
## ==================================================================================

51
extra/dss/bios/entry.dss Normal file
View file

@ -0,0 +1,51 @@
.load 0x0000 ## BIOS is mapped to address 0x0000 in memory
@include <data.dss>
## ============================= 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 <drivers.dss>
@include <utils.dss>
.fixed 4096, 0x00 ## BIOS Needs to be 4096 Bytes exactly

102
extra/dss/bios/utils.dss Normal file
View file

@ -0,0 +1,102 @@
@guard _UTILS_DSS_
@include <data.dss>
_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 <Status> register into ACC
jne $_load_mbr_data_block_wait_loop, 0x00 ## If <Status> 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

View file

@ -10,7 +10,7 @@
$string "Hello World!!" $string "Hello World!!"
.code .code
mov R1, 0x7FF0 ## Zero the counter mov R1, 0 ## Zero the counter
infinite_loop: infinite_loop:
inc R1 ## Increment the counter inc R1 ## Increment the counter
div R1, 10 ## Divide the counter by 10 div R1, 10 ## Divide the counter by 10

View file

@ -5,6 +5,6 @@ clear='\033[0m'
printf "${green}Reloading BIOS...\n${clear}" printf "${green}Reloading BIOS...\n${clear}"
cd .. cd ..
cp ../extra/dss/bios/bios.dss ./dss/bios/bios.dss cp ../extra/dss/bios/* ./dss/bios/
./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
cp dragon/bios.bin ../extra/dragon/bios.bin cp dragon/bios.bin ../extra/dragon/bios.bin

View file

@ -14,6 +14,100 @@ namespace dragon
{ {
namespace code namespace code
{ {
std::vector<ostd::String> 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<ostd::String> 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<ostd::String>& 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<ostd::String> 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<ostd::String> 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) int32_t Assembler::Application::loadArguments(int argc, char** argv)
{ {
if (argc < 2) if (argc < 2)
@ -101,8 +195,9 @@ namespace dragon
m_loadAddress = 0x0000; m_loadAddress = 0x0000;
m_currentDataAddr = 0x0000; m_currentDataAddr = 0x0000;
m_dataSize = 0x0000; m_dataSize = 0x0000;
ostd::TextFileBuffer file(fileName); m_lines = IncludePreprocessor::loadEntryFile(fileName);
loadSource(file.rawContent()); if (m_lines.size() == 0)
return { }; //TODO: Error
removeComments(); removeComments();
replaceGroupDefines(); replaceGroupDefines();
replaceDefines(); replaceDefines();
@ -125,12 +220,6 @@ namespace dragon
return m_code; 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) ostd::ByteStream Assembler::assembleToFile(ostd::String sourceFileName, ostd::String binaryFileName)
{ {
assembleFromFile(sourceFileName); assembleFromFile(sourceFileName);

View file

@ -12,6 +12,22 @@ namespace dragon
} }
namespace code namespace code
{ {
class IncludePreprocessor
{
public:
static std::vector<ostd::String> loadEntryFile(const ostd::String& filePath);
private:
static bool __can_file_be_included(std::vector<ostd::String>& lines);
static bool __include_loop(void);
static std::vector<ostd::String> __load_file(const ostd::String& filePath);
private:
inline static std::vector<ostd::String> m_lines;
inline static std::vector<ostd::String> m_guards;
inline static ostd::String m_directory { "" };
};
class Assembler class Assembler
{ {
public: struct tDisassemblyLine public: struct tDisassemblyLine
@ -83,7 +99,6 @@ namespace dragon
public: public:
static ostd::ByteStream assembleFromFile(ostd::String fileName); 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 assembleToFile(ostd::String sourceFileName, ostd::String binaryFileName);
static ostd::ByteStream assembleToVirtualDisk(ostd::String fileName, hw::VirtualHardDrive& vhdd, uint32_t address); static ostd::ByteStream assembleToVirtualDisk(ostd::String fileName, hw::VirtualHardDrive& vhdd, uint32_t address);
static bool saveDisassemblyToFile(ostd::String fileName); static bool saveDisassemblyToFile(ostd::String fileName);

View file

@ -1416,6 +1416,7 @@ namespace dragon
else if (data().command.startsWith("p ") || data().command.startsWith("print ")) else if (data().command.startsWith("p ") || data().command.startsWith("print "))
{ {
data().command.substr(data().command.indexOf(" ") + 1).trim(); data().command.substr(data().command.indexOf(" ") + 1).trim();
const uint8_t TYPE_STRING = 0;
const uint8_t TYPE_BYTE = 1; const uint8_t TYPE_BYTE = 1;
const uint8_t TYPE_WORD = 2; const uint8_t TYPE_WORD = 2;
const uint8_t TYPE_DWORD = 4; const uint8_t TYPE_DWORD = 4;
@ -1429,9 +1430,12 @@ namespace dragon
else if (size_str == "word") type = TYPE_WORD; else if (size_str == "word") type = TYPE_WORD;
else if (size_str == "dword") type = TYPE_DWORD; else if (size_str == "dword") type = TYPE_DWORD;
else if (size_str == "qword") type = TYPE_QWORD; else if (size_str == "qword") type = TYPE_QWORD;
else if (size_str == "string") type = TYPE_STRING;
} }
if (data().command.isNumeric()) if (data().command.isNumeric())
{ {
if (type == TYPE_STRING)
type = TYPE_WORD;
uint16_t addr = data().command.toInt(); uint16_t addr = data().command.toInt();
uint16_t end_addr = addr; uint16_t end_addr = addr;
ostd::String tmp = ""; ostd::String tmp = "";
@ -1474,7 +1478,6 @@ namespace dragon
{ {
ostd::String tmp = ""; ostd::String tmp = "";
tmp.add("*(").add(ostd::Utils::getHexStr(addr, true, 2)); tmp.add("*(").add(ostd::Utils::getHexStr(addr, true, 2));
if (type != TYPE_BYTE)
if (size > 1) if (size > 1)
tmp.add("-").add(ostd::Utils::getHexStr((uint16_t)(addr + size - 1), true, 2)); tmp.add("-").add(ostd::Utils::getHexStr((uint16_t)(addr + size - 1), true, 2));
tmp.add(")"); tmp.add(")");
@ -1485,13 +1488,22 @@ namespace dragon
output().pStyled(rgx); output().pStyled(rgx);
output().fg(ostd::ConsoleColors::White).p(" = "); output().fg(ostd::ConsoleColors::White).p(" = ");
output().fg(ostd::ConsoleColors::Gray).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++) for (uint16_t a = addr; a < addr + size; a++)
{ {
uint8_t value = DragonRuntime::memMap.read8(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)); output().fg(ostd::ConsoleColors::BrightRed).p(ostd::Utils::getHexStr(value, true, 1));
if (a < addr + size - 1) if (a < addr + size - 1)
output().p(" "); output().p(" ");
} }
if (type == TYPE_STRING)
output().fg(ostd::ConsoleColors::BrightRed).p("\"");
output().fg(ostd::ConsoleColors::Gray).p("]"); output().fg(ostd::ConsoleColors::Gray).p("]");
output().reset().nl(); output().reset().nl();
} }