Skip to content

Instantly share code, notes, and snippets.

@desaster
Last active July 5, 2023 14:42
Show Gist options
  • Save desaster/18a335e6251456ed92423e07c9c8adab to your computer and use it in GitHub Desktop.
Save desaster/18a335e6251456ed92423e07c9c8adab to your computer and use it in GitHub Desktop.
simple 8088 assembly program for creating binary files from keyboard input
;
; 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