[0.2.1580] - Added basic "include" functionality to the assembler
This commit is contained in:
parent
085bdbc75c
commit
713711d247
11 changed files with 403 additions and 328 deletions
2
build.nr
2
build.nr
|
|
@ -1 +1 @@
|
|||
1579
|
||||
1581
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
118
extra/dss/bios/drivers.dss
Normal 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
51
extra/dss/bios/entry.dss
Normal 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
102
extra/dss/bios/utils.dss
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -14,6 +14,100 @@ namespace dragon
|
|||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,22 @@ namespace dragon
|
|||
}
|
||||
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
|
||||
{
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue