commit 488b58b2d6be64403c14f7e9a9df66c900a37269 Author: maelstrom Date: Wed Jul 24 18:41:52 2024 +0300 Starting point copied from guess-os diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/input_util.asm b/input_util.asm new file mode 100644 index 0000000..03c0b6c --- /dev/null +++ b/input_util.asm @@ -0,0 +1,57 @@ +read_line: + pusha + + mov bx, read_buffer + .loop: + mov ah, 0x00 + int 0x16 ; Read char + + cmp al, 0x0D ; Is enter? + jne .enter_end + jmp .end + .enter_end: + + cmp al, 0x08 ; Is backspace? + jne .backspace_end + ; Don't do anything if we're at col == 0 + cmp bx, read_buffer + jle .backspace_end + + sub bx, 1 + mov ah, 0x0 + mov [bx], ah + + ; Erase the character on screen + mov ah, 0x0e + mov al, 0x08 ; Back one + int 0x10 + mov al, 0x20 ; Erase it + int 0x10 + mov al, 0x08 ; Back one more + int 0x10 + + jmp .loop + .backspace_end + + ; Don't add any characters if over the limit + cmp bx, read_buffer + 20 + jge .loop + + ; Add char to bx and incr + mov [bx], al + add bx, 1 + + ; Display the character + mov ah, 0x0e + int 0x10 + + jmp .loop + .end: + + mov al, 0x0 + mov [bx], al ; Null terminater + + popa + ret + +read_buffer: resb 20 diff --git a/main.asm b/main.asm new file mode 100644 index 0000000..6ccdf92 --- /dev/null +++ b/main.asm @@ -0,0 +1,33 @@ +[org 0x7c00] + +main: + ; Video mode + mov ax, 0x13 + int 0x10 + + call mouse_initialize + call mouse_enable + +lp: + cli + mov bx, [mouseX] + call print_hex + mov bx, [mouseY] + sti + + jmp lp + +jmp $ ; Halt + +; Make sure includes are done last, otherwise the first include will become main +%include "print_util.asm" +;%include "input_util.asm" +;%include "num_util.asm" +%include "mouse_util.asm" + +; Make sure data is *inside* the boot sector, or it will not be copied to the right place +; in memory. + + +times 510-($-$$) db 0 +dw 0xaa55 diff --git a/main.bin b/main.bin new file mode 100644 index 0000000..41d3388 Binary files /dev/null and b/main.bin differ diff --git a/mouse_util.asm b/mouse_util.asm new file mode 100644 index 0000000..2b1b0bd --- /dev/null +++ b/mouse_util.asm @@ -0,0 +1,163 @@ +; Adapted from https://stackoverflow.com/a/54367182 + +HW_EQUIP_PS2 equ 4 ; PS2 mouse installed? +MOUSE_PKT_BYTES equ 3 ; Number of bytes in mouse packet +MOUSE_RESOLUTION equ 3 ; Mouse resolution 8 counts/mm + +VIDEO_MODE equ 0x13 + +; Function: mouse_initialize +; Initialize the mouse if present +; +; Inputs: None +; Returns: CF = 1 if error, CF=0 success +; Clobbers: AX + +mouse_initialize: + push es + push bx + + int 0x11 ; Get equipment list + test ax, HW_EQUIP_PS2 ; Is a PS2 mouse installed? + jz .no_mouse ; if not print error and end + + mov ax, 0xC205 ; Initialize mouse + mov bh, MOUSE_PKT_BYTES ; 3 byte packets + int 0x15 ; Call BIOS to initialize + jc .no_mouse ; If not successful assume no mouse + + mov ax, 0xC203 ; Set resolution + mov bh, MOUSE_RESOLUTION ; 8 counts / mm + int 0x15 ; Call BIOS to set resolution + jc .no_mouse ; If not successful assume no mouse + + push cs + pop es ; ES = segment where code and mouse handler reside + + mov bx, mouse_callback_dummy + mov ax, 0xC207 ; Install a default null handler (ES:BX) + int 0x15 ; Call BIOS to set callback + jc .no_mouse ; If not successful assume no mouse + + clc ; CF=0 is success + jmp .finished +.no_mouse: + stc ; CF=1 is error +.finished: + pop bx + pop es + ret + +; Function: mouse_enable +; Enable the mouse +; +; Inputs: None +; Returns: None +; Clobbers: AX + +mouse_enable: + push es + push bx + + call mouse_disable ; Disable mouse before enabling + + push cs + pop es + mov bx, mouse_callback + mov ax, 0xC207 ; Set mouse callback function (ES:BX) + int 0x15 ; Call BIOS to set callback + + mov ax, 0xC200 ; Enable/Disable mouse + mov bh, 1 ; BH = Enable = 1 + int 0x15 ; Call BIOS to disable mouse + + pop bx + pop es + ret + +; Function: mouse_disable +; Disable the mouse +; +; Inputs: None +; Returns: None +; Clobbers: AX + +mouse_disable: + push es + push bx + + mov ax, 0xC200 ; Enable/Disable mouse + xor bx, bx ; BH = Disable = 0 + int 0x15 ; Call BIOS to disable mouse + + mov es, bx + mov ax, 0xC207 ; Clear callback function (ES:BX=0:0) + int 0x15 ; Call BIOS to set callback + + pop bx + pop es + ret + +; Function: mouse_callback (FAR) +; called by the interrupt handler to process a mouse data packet +; All registers that are modified must be saved and restored +; Since we are polling manually this handler does nothing +; +; Inputs: SP+4 = Unused (0) +; SP+6 = MovementY +; SP+8 = MovementX +; SP+10 = Mouse Status +; +; Returns: None +; Clobbers: None + +ARG_OFFSETS equ 6 ; Offset of args from BP + +mouse_callback: + push bp ; Function prologue + mov bp, sp + push ds ; Save registers we modify + push ax + push bx + push cx + push dx + + push cs + pop ds ; DS = CS, CS = where our variables are stored + + mov al,[bp+ARG_OFFSETS+6] + mov bl, al ; BX = copy of status byte + mov cl, 3 ; Shift signY (bit 5) left 3 bits + shl al, cl ; CF = signY + ; Sign bit of AL = SignX + sbb dh, dh ; CH = SignY value set in all bits + cbw ; AH = SignX value set in all bits + mov dl, [bp+ARG_OFFSETS+2] ; CX = movementY + mov al, [bp+ARG_OFFSETS+4] ; AX = movementX + + ; new mouse X_coord = X_Coord + movementX + ; new mouse Y_coord = Y_Coord + (-movementY) + neg dx + mov cx, [mouseY] + add dx, cx ; DX = new mouse Y_coord + mov cx, [mouseX] + add ax, cx ; AX = new mouse X_coord + + ; Status + mov [curStatus], bl ; Update the current status with the new bits + mov [mouseX], ax ; Update current virtual mouseX coord + mov [mouseY], dx ; Update current virtual mouseY coord + + pop dx ; Restore all modified registers + pop cx + pop bx + pop ax + pop ds + pop bp ; Function epilogue + +mouse_callback_dummy: + retf ; This routine was reached via FAR CALL. Need a FAR RET + +mouseX: dw 0 ; Current mouse X coordinate +mouseY: dw 0 ; Current mouse Y coordinate +curStatus: db 0 ; Current mouse status diff --git a/num_util.asm b/num_util.asm new file mode 100644 index 0000000..2c8c7d3 --- /dev/null +++ b/num_util.asm @@ -0,0 +1,43 @@ +; Loops over every character. +; Multiplies current by 10 +; Adds [bx] - 0x30 +; add bx, 1 +parse_int: + pusha + + ; Contains the actual result + mov ax, 0 + + .loop: + mov cl, [bx] + + cmp cl, 0x0 ; End on null + je .end + + ; If the character is invalid, stop here. + cmp cl, 0x30 + jl .end + cmp cl, 0x39 + jg .end + + ; Multiply by 10 + mov cx, 10 ; NOT 0x10 + mul cx + ; Note: Has to be cx and not cl, otherwise it will be limited to 8-bits only + + mov cl, [bx] + sub cl, 0x30 + mov ch, 0x0 + add ax, cx ; Use 16-bit addition + + add bx, 1 ; Next char + + jmp .loop + .end: + + mov [result], ax + + popa + ret + +result: dw 0 \ No newline at end of file diff --git a/print_util.asm b/print_util.asm new file mode 100644 index 0000000..5ca91f8 --- /dev/null +++ b/print_util.asm @@ -0,0 +1,121 @@ +print: + pusha + + .loop: + mov al, [bx] + cmp al, 0 + je .end ; go to end if char == 0 + + mov ah, 0x0e + int 0x10 + + add bx, 1 + jmp .loop ; loop + .end: + + popa + ret + + +print_nl: + pusha + + mov ax, 0x0e0a + int 0x10 + mov ax, 0x0e0d + int 0x10 + + popa + ret + +println: + pusha + + call print + + mov ax, 0x0e0a + int 0x10 + mov ax, 0x0e0d + int 0x10 + + popa + ret + +print_hex_digit: + pusha + + mov al, bl + mov bl, 0x0F + and al, bl ; Get rid of all but the last nibble + + ; If the value is >= 0xA, then we need to add to the alphabetical block of the ascii table + cmp al, 0x0A + jl .skip_alpha ; If the number is not at least 0xA, then skip this step + add al, 0x07 ; 'A' == 0x41, '0' == 0x30, 0x41 - 0x30 == 0x11 + ; Ignore ^^^^^^^ THIS ^^^^^^ actually. + ; It works and i've not got a clue why. Oh well. Such is life. + + .skip_alpha: + add al, 0x30 ; Add ASCII '0' + + mov ah, 0x0e + int 0x10 + + popa + ret + +print_hex: + pusha + + mov ax, bx + + shr bx, 12 + call print_hex_digit + + mov bx, ax + shr bx, 8 + call print_hex_digit + + mov bx, ax + shr bx, 4 + call print_hex_digit + + mov bx, ax + call print_hex_digit + + popa + ret + +print_bin: + pusha + + mov cx, 0 + .loop: + cmp cx, 16 + je .end + + test bx, 0x8000 + jnz .one + push bx + mov bl, 0x02 + mov ah, 0x0e + mov al, 0x30 + int 0x10 + pop bx + jmp .continue + .one: + push bx + mov bl, 0x03 + mov ah, 0x0e + mov al, 0x31 + int 0x10 + pop bx + .continue: + + shl bx, 1 + add cx, 1 + jmp .loop + .end: + + popa + ret \ No newline at end of file diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..3a62e0b --- /dev/null +++ b/run.sh @@ -0,0 +1,2 @@ +nasm -f bin main.asm -o main.bin +qemu-system-x86_64 main.bin \ No newline at end of file