Last active
July 5, 2023 14:42
-
-
Save desaster/18a335e6251456ed92423e07c9c8adab to your computer and use it in GitHub Desktop.
simple 8088 assembly program for creating binary files from keyboard input
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; | |
; Read hex values from input and write them to a file as bytes | |
; | |
; Intended to help with bootstrapping vintage computers, when the only access | |
; is via keyboard or serial console. | |
; | |
; Goal is to remain small as possible, so the program could be transferred via | |
; DEBUG.COM by hand. | |
; | |
; To compile: | |
; nasm -f bin -o wrb.com wrb.asm | |
; | |
; Usage, e.g.: | |
; | |
; WRBYTES OUTPUT.TXT | |
; = 69 6A 6B w | |
; = q | |
; DISCLAIMER! | |
; no error checking! at all! | |
; only capital letters in hex! | |
; 'q' and 'w' commands are lowercase! | |
cpu 8086 | |
org 0x100 | |
section .text | |
main: | |
call storecmdline | |
; make indexing thingie zero | |
sub si, si | |
; create file | |
mov cx, 0x0000 | |
mov dx, outfile | |
mov ah, 0x3c | |
int 0x21 | |
jc error ; if CF is set, error out | |
mov [handle], ax ; store file handle | |
call prompt | |
mainloop: | |
; read first character | |
call readone | |
; 'q' when reading the first char -> close file and quit | |
cmp bl, 'q' | |
je quit | |
; 'w' when reading the first char -> write buffer to file | |
cmp bl, 'w' | |
je writebuf | |
; wasn't 'w' or 'q', so assume it's hex and keep going | |
call hextonum | |
mov bh, bl ; store returned value in bh | |
; read second character, here we don't accept 'w' or 'q' | |
call readone | |
call hextonum | |
; now we have values in bh and bl | |
; print space after reading both characters | |
mov dl, ' ' | |
mov ah, 0x02 | |
int 0x21 | |
; shift and OR to turn the two 4-bit numbers to one 8-bit number | |
mov cl, 4 | |
rol bh, cl | |
or bl, bh | |
; store the final value in buffer | |
mov [buf + si], bl | |
inc si | |
jmp mainloop ; and loop again | |
error: | |
quit: | |
; close file | |
mov bx, [handle] | |
mov ah, 0x3e | |
int 0x21 | |
call newline | |
;mov ah, 0x4c | |
;int 0x21 | |
hextonum: | |
cmp bl, 'A' | |
jae .isletter | |
.isdigit: | |
sub bl, 48 | |
jmp .continue | |
.isletter: | |
sub bl, 55 | |
.continue: | |
ret | |
readone: | |
.loop: | |
mov ah, 0x0b ; check input | |
int 0x21 | |
cmp al, 00 ; no new character? | |
je .loop ; then keep looping | |
mov ah, 0x01 ; new character, read input | |
int 0x21 | |
mov bl, al | |
ret | |
prompt: | |
; prompt to indicate the user may enter bytes | |
mov dl, '=' | |
mov ah, 0x02 | |
int 0x21 | |
mov dl, ' ' | |
int 0x21 | |
ret | |
writebuf: | |
; write to file | |
mov dx, buf | |
mov cx, si | |
mov bx, [handle] | |
mov ah, 0x40 | |
int 0x21 | |
; reset si to zero so we start writing the buffer from start | |
sub si, si | |
; newline and default prompt, so the user knows the write is done | |
call newline | |
call prompt | |
jmp mainloop ; back to reading more bytes | |
newline: | |
mov dl, 0x0d ; \r | |
mov ah, 0x02 | |
int 0x21 | |
mov dl, 0x0a ; \n | |
int 0x21 | |
ret | |
; read cmdline from 0x81 + 1 and directly store it as the output filename | |
; no error checking or careful parsing! | |
storecmdline: | |
sub si, si | |
.loop: | |
mov bl, [0x82 + si] ; 0x81 is space, so start at 0x82 | |
cmp bl, 0x0D ; cmdline is terminated by 0x0D | |
je .done | |
mov [outfile + si], bl | |
inc si | |
jmp .loop | |
.done: | |
inc si | |
mov byte [outfile + si], 0 ; zero terminate | |
ret | |
section .data | |
;foo db 0x00 0x00 | |
;msg db 0x0d, 0x0a, 'Done!', 0x0d, 0x0a, '$' | |
;outfile db 'foo.txt', 0 | |
handle dw 0 | |
section .bss | |
buf resb 128 | |
outfile resb 16 | |
; vim: set ft=nasm: |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment