diff --git a/stage1_hex_compiler.s b/stage1_hex_compiler.s new file mode 100644 index 0000000..a9c6c1b --- /dev/null +++ b/stage1_hex_compiler.s @@ -0,0 +1,238 @@ +BITS 16 + ;; Steps for building + ;; nasm -o stage1_hex_compiler stage1_hex_compiler + ;; + ;; Steps for testing + ;; qemu -fda stage0 + ;; manually toggle in program hex + ;; or + ;; qemu -fda stage1_loader -fdb output + ;; then change floppy0 to the compiled version of this file +start: + mov sp, 256 ; Allocate 256B for stack + mov ax, 7e00h ; Which is much more than we need + mov ss, ax ; And stopping before this code + + ;; Prompt user to press any key after loading desire source into A: + mov ax, MSG0 + call print_string + + ;; Wait until the user presses a key + call read_key + + ;; Inform the user that we are starting to read + mov ax, MSG1 + call print_string + + ;; Read A: into memory + call read_floppy + + ;; Inform the user that we completed reading A: and are starting to compile + mov ax, MSG2 + call print_string + + ;; Actually compile + call compile + + ;; Inform that user that we completed Compiling and are starting to write to B: + mov ax, MSG3 + call print_string + + ;; Start writing memory into B: + call write_floppy2 + + ;; Inform the user that we completed writing to B: + mov ax, MSG4 + call print_string + jmp start + +;; Our glourious strings +MSG0 db 'Load source into A: and hit any key',10,13,0 +MSG1 db 'Starting to read A:',10,13,0 +MSG2 db 'Read Complete, Starting to compile',10,13, 0 +MSG3 db 'Compile Complete, Starting to write B:',10,13,0 +MSG4 db 'Write Complete',10,13, 0 + +;; Deal with the problem of printing the above strings +print_string: + pusha + mov bx, ax +.L0: + mov al, [cs:bx] + cmp al, 0 + je .L99 + call print_char + add bx, 1 + jmp .L0 +.L99: + popa + ret + +print_char: + pusha + ; Routine: output char in al to screen + mov ah, 0Eh ; int 10h 'print char' function + int 10h ; print it + popa + ret + +read_floppy: + pusha +.L0: + ;; Read bytes from floppy + push 02000h ; Use The read space + pop es ; ES is needed to be set for bios call + mov al, 128 ; Read 2^15 Bytes from diskette + mov ah, 02h ; Read Sectors to Memory + mov ch, 0 ; Cylinder Number + mov cl, 1 ; Starting sector number + mov dh, 0 ; Drive head number + mov dl, 00h ; Drive number [first floppy] + mov bx, 0h ; Starting address + int 13h ; Make the function call + + jc .L0 + popa + ret + +read_key: + pusha + ;; Routine: read a char into al + mov ah, 00h + int 16h + popa + ret + +write_floppy2: + pusha +.L0: + ;; Write bytes onto floppy2 + push 03000h ; Use the write space + pop es ; ES is needed to be set for bios all + mov al, 128 ; Write 2^15 Bytes to diskette + mov ah, 03h ; Write Sectors from Memory + mov ch, 0 ; Cylinder Number + mov cl, 1 ; Starting sector number + mov dh, 0 ; Drive head number + mov dl, 01h ; Drive number [second floppy] + mov bx, 0h ; Starting address + int 13h ; Make the function call + + jc .L0 + popa + ret + +compile: + pusha + ;; Initialize our pointers + mov ax, 0 + mov [Read_Pointer], ax + mov [Write_Pointer], ax + + ;; Initialize variables + mov di, 1 ; Our toggle + mov si, 0 ; Our holder + +.L0: + call read_char ; Read a byte + cmp al, 0 ; Check for NULL + je .L99 ; Be done at NULL + call hex ; Otherwise try to convert hex + cmp al, 0 ; Check if it is hex + jl .L0 ; Don't use nonhex chars + cmp di, 0 ; Check if toggled + je .L1 + + ;; Process first byte of pair + mov si, 0Fh ; Mask out top + and si, ax ; Store first nibble + mov di, 0 ; Flip the toggle + jmp .L0 + +.L1: + shl si, 4 ; shift our first nibble + and ax, 0Fh ; Mask out top + add ax, si ; Combine nibbles + mov di, 1 ; Flip the toggle + call write_char ; Write our byte out + jmp .L0 +.L99: + popa + ret + +Read_Pointer dw 0 +read_char: + push bx + push es + push 02000h + pop es + mov bx, [cs:Read_Pointer] + mov al, [es:bx] + add bx, 1 + mov [cs:Read_Pointer], bx + pop es + pop bx + ret + +Write_Pointer dw 0 +write_char: + pusha + push 03000h + pop es + mov bx, [cs:Write_Pointer] + mov [es:bx], al + add bx, 1 + mov [cs:Write_Pointer], bx + popa + ret + + +hex: + ; deal with line comments starting with # + cmp al, 35 + je ascii_comment + ; deal with line comments starting with ; + cmp al, 59 + je ascii_comment + ; deal all ascii less than 0 + cmp al, 48 + jl ascii_other + ; deal with 0-9 + cmp al, 58 + jl ascii_num + ; deal with all ascii less than A + cmp al, 65 + jl ascii_other + ; deal with A-F + cmp al, 71 + jl ascii_high + ; deal with all ascii less than a + cmp al, 97 + jl ascii_other + ; deal with a-f + cmp al, 103 + jl ascii_low + ; The rest that remains needs to be ignored + jmp ascii_other + +ascii_num: + sub al, 48 + ret +ascii_low: + sub al, 87 + ret +ascii_high: + sub al, 55 + ret +ascii_other: + mov al, -1 + ret +ascii_comment: + call read_char ; Read until end of Line + cmp al, 13 ; Carriage return counts + je ascii_other + cmp al, 10 ; So does line feed + je ascii_other + cmp al, 0 ; Nulls are probably a safe stopping point too + je ascii_other + jmp ascii_comment ; Otherwise keep dropping input