diff options
-rw-r--r-- | builtin_clear.asm | 11 | ||||
-rw-r--r-- | builtin_echo.asm | 29 | ||||
-rw-r--r-- | builtin_exit.asm | 7 | ||||
-rw-r--r-- | builtin_free.asm | 35 | ||||
-rw-r--r-- | builtin_vga_demo.asm | 123 | ||||
-rw-r--r-- | builtin_video_mode.asm | 98 | ||||
-rw-r--r-- | builtins.asm | 16 |
7 files changed, 302 insertions, 17 deletions
diff --git a/builtin_clear.asm b/builtin_clear.asm new file mode 100644 index 0000000..cac6216 --- /dev/null +++ b/builtin_clear.asm @@ -0,0 +1,11 @@ +%ifndef _BUILTIN_CLEAR_ASM +%define _BUILTIN_CLEAR_ASM + +builtin_clear: + call cls ; clear console + push 0000h ; home position 0x0 + call setcursor ; home cursor on console + add sp, 2 ; cleanup stack + ret + +%endif diff --git a/builtin_echo.asm b/builtin_echo.asm index 1b4af89..9cc1e9c 100644 --- a/builtin_echo.asm +++ b/builtin_echo.asm @@ -5,16 +5,25 @@ builtin_echo: push bp mov bp, sp - mov bx, word [bp + 4] - add bx, 2 - push word [bx] - push .msg_fmt - call printf - add sp, 2 * 2 + mov cx, word [bp + 4] ; argc + mov bx, word [bp + 6] ; argv - mov sp, bp - pop bp - ret - .msg_fmt db '%s\n', 0 + cmp cx, 0 ; if no arguments, return + jbe .return + + .output: ; print argv + push word [bx] + push .msg_fmt + call printf + add sp, 2 * 2 + add bx, 2 + dec cx + jne .output + + .return: + mov sp, bp + pop bp + ret + .msg_fmt db '%s ', 0 %endif diff --git a/builtin_exit.asm b/builtin_exit.asm index 74594e1..08b0e38 100644 --- a/builtin_exit.asm +++ b/builtin_exit.asm @@ -2,16 +2,13 @@ %define _BUILTIN_EXIT_ASM builtin_exit: - push bp - mov bp, sp - push .msg_fmt call printf add sp, 2 * 1 - add sp, 2 ; cleanup previous call address + mov [terminal_exit], byte 1 - jmp terminal + ret .msg_fmt db 'exiting...\n', 0 %endif diff --git a/builtin_free.asm b/builtin_free.asm new file mode 100644 index 0000000..96e3c86 --- /dev/null +++ b/builtin_free.asm @@ -0,0 +1,35 @@ +%ifndef _BUILTIN_FREE_ASM +%define _BUILTIN_FREE_ASM + +builtin_free: + push bp + mov bp, sp + + mov cx, word [bp + 4] ; argc + mov bx, word [bp + 6] ; argv + + ;cmp cx, 0 ; if no arguments, return + ;jbe .return + + mov ah, 88h ; get extended memory size + int 15h + mov dx, ax + + int 12h ; get conventional memory size + ; but it's pretty much bogus + + push dx + push ax + push .msg_fmt + call printf + add sp, 2 * 2 + add bx, 2 + + .return: + mov sp, bp + pop bp + ret + .msg_fmt db 'Conventional memory: %dK\n' + db 'Extended memory: %dK', 0 + +%endif diff --git a/builtin_vga_demo.asm b/builtin_vga_demo.asm new file mode 100644 index 0000000..54d4a4f --- /dev/null +++ b/builtin_vga_demo.asm @@ -0,0 +1,123 @@ +%ifndef _VGA_DEMO_ASM +%define _VGA_DEMO_ASM + +VGA_SCREEN_WIDTH equ 320 +VGA_SCREEN_HEIGHT equ 200 +VGA_COLORS equ 0x100 + +vga_plot: + %define .x [bp + 4] + %define .y [bp + 6] + %define .color [bp + 8] + push bp + mov bp, sp + pusha + push es + push ds + ;push ax + ;push cx + ;push dx + ;push di +; + xor ax, ax + xor cx, cx + xor dx, dx + xor di, di + + mov ax, 0A000h + mov es, ax ; Store VGA memory segment in ES + mov ds, ax + + mov ax, word VGA_SCREEN_WIDTH + mov cx, word .y + mul cx + add ax, word .x + mov di, ax + + mov ax, word .color + mov [es:di], ax + + .return: + ;pop di + ;pop dx + ;pop cx + ;pop ax + pop ds + pop es + popa + mov sp, bp + pop bp + ret + + + +builtin_vga_demo: + push bp + mov bp, sp + sub sp, 2 + + ; + ; no arguments for this program + ; + + .main: + mov ah, 0fh ; get current video mode + int 10h + mov [bp - 2], al ; save current video mode + + mov ah, 00h + mov al, 13h ; set 256 color VGA mode + int 10h + + mov di, 0ffh + .loop: + mov si, .data_smiley ; address of smiley face array + mov cx, 10 ; number of array elements + .do_plot: + mov ax, [si] ; Load coordinates + add si, 2 ; Next set + + movzx dx, al ; Store y + movzx bx, ah ; Store x + + push di ; color + push dx ; y + push bx ; x + call vga_plot ; write pixel + add sp, 2 * 3 + + and di, 0ffh ; DI overflows into infinity so + ; use its low byte instead of resetting to zero + dec di ; Next color + dec cx ; Next loop + jne .do_plot + + xor ax, ax + call kbd_read_async ; ZF=1 if no key is pressed + je .loop + + .return: + mov ah, 00h ; Set video mode + mov al, [bp - 2] ; Restore video mode + int 10h + + add sp, 2 + mov sp, bp + pop bp + ret + + .data_smiley: + ; plots a smiley face using coordinates + ; row col + db 01h,01h ; left eye + db 01h,05h ; right eye + db 04h,03h ; nose + db 06h,00h ; left uptick mouth + db 06h,06h ; mouth + db 07h,01h ; mouth + db 07h,02h ; mouth + db 07h,03h ; mouth + db 07h,04h ; mouth + db 07h,05h ; right uptick mouth + +%endif diff --git a/builtin_video_mode.asm b/builtin_video_mode.asm new file mode 100644 index 0000000..571899e --- /dev/null +++ b/builtin_video_mode.asm @@ -0,0 +1,98 @@ +%ifndef _BUILTIN_VIDEO_MODE_ASM +%define _BUILTIN_VIDEO_MODE_ASM + +builtin_video_mode: + push bp + mov bp, sp + + mov cx, [bp + 4] ; Load argc + mov bx, [bp + 6] ; Load argv + + cmp cx, 1 ; Not enough args? + jl .no_args ; ... die + jmp .main + + .no_args: + push .error_arg + call printf + add sp, 2 * 1 + jmp .return + + ; main program + + .main: + mov bx, [bx] ; Load first element in argv array + mov si, bx ; First element is source index + + push bx ; Get length of element + call strlen + add sp, 2 + mov cx, ax ; Store length + mov bx, 0 + + + mov ax, 0 + mov dx, 0 + .chars: + lodsb ; Load character from ES:SI + cmp ax, '9' ; If value is greater than '9' it's likely hex, so + ; adjust AX to compensate + jg .ishex + + sub ax, '0' ; Otherwise, the value is base-10 + jmp .nosub + + .tolower: + sub ax, 20h + .ishex: + cmp ax, 'a' + jge .tolower ; If we recieved a lowercase letter, convert it + ; to uppercase, then continue + + cmp ax, 'F' ; Is this a valid hexadecimal value? (0 ~ F) + jg .invalid_input + + sub ax, 'A' ; Convert character to BCD + add ax, 10 + + .nosub: + shl dx, 4 ; Shift current BCD value 4-bits left + or dx, ax ; Tack on the latest value + dec cx ; Decrement counter + jne .chars ; continue until no characters remain + + + cmp dx, 13h ; Is the final value a valid video mode? + jg .invalid_mode + + + mov al, dl ; BIOS video services only operate on a byte value + ; ... oh well. + + mov ah, 00h + int 10h ; Set video mode + + .return: + mov sp, bp + pop bp + ret + + .invalid_input: + push ax + push .error_hex + call printf + add sp, 2 * 2 + jmp .return + + .invalid_mode: + push dx + push .error_mode + call printf + add sp, 2 * 2 + jmp .return + + .error_arg: db 'error: no graphics mode requested. (0..13)\n', 0 + .error_hex: db 'error: "%c" is an invalid hexadecimal value (0..F)\n', 0 + .error_mode: db 'error: %2x is an invalid video mode (0..13)\n', 0 + +%endif diff --git a/builtins.asm b/builtins.asm index 268e4b2..d09282c 100644 --- a/builtins.asm +++ b/builtins.asm @@ -1,19 +1,31 @@ %ifndef _BUILTINS_ASM %define _BUILTINS_ASM -%include "builtin_reboot.asm" -%include "builtin_exit.asm" +%include "builtin_clear.asm" %include "builtin_echo.asm" +%include "builtin_exit.asm" +%include "builtin_free.asm" +%include "builtin_reboot.asm" +%include "builtin_vga_demo.asm" +%include "builtin_video_mode.asm" t_builtins_fn: + dw builtin_clear dw builtin_echo dw builtin_exit + dw builtin_free dw builtin_reboot + dw builtin_vga_demo + dw builtin_video_mode dw 0 t_builtins_str: + .clear: db 'clear', 0 .echo: db 'echo', 0 .exit: db 'exit', 0 + .free: db 'free', 0 .reboot: db 'reboot', 0 + .vga_demo: db 'vga_demo', 0 + .video_mode: db 'video_mode', 0 dw 0 %endif |