3ByteBadVM/ass.sh

93 lines
3.1 KiB
Bash
Executable File

#!/bin/sh
# ass.sh: a bad assembler for my VM instruction set
#
# WARNING: this assembler is ASS! That is why I named it that (in addition to
# being short for 'ass'embler). This was purely a quick hack so that I could
# get working on writing my imaginary VM code ASAP. I would be embarassed if I
# had any shame left.
#
# Assumes GNU sed, will need to be modified if using BSD sed
die() {
printf "$1\n"
exit $2
}
# bad_assemble: "assembles" the temporary source file provided by $1 (converts
# instructions to opcodes, pretty simple)
# Forgive me for how this function is implemented...
bad_assemble() {
sed -i '/^[[:blank:]]*#/d;s/#.*//' "$1" # remove comments starting with '#'
sed -i 's/0X//gi' "$1" # remove hex prefix '0x'
sed -i 's/HALT[[:blank:]]*/00 00 00/gi' "$1"
sed -i 's/PUSH[[:blank:]]/01/gi' "$1"
sed -i 's/POP[[:blank:]]/02/gi' "$1"
sed -i 's/PUSHI[[:blank:]]/03/gi' "$1"
sed -i 's/LDLR[[:blank:]]/04/gi' "$1"
sed -i 's/STLR[[:blank:]]/05/gi' "$1"
sed -i 's/SETI[[:blank:]]/06/gi' "$1"
sed -i 's/DUP[[:blank:]]*/07 00 00/gi' "$1"
sed -i 's/ADD[[:blank:]]*/08 00 00/gi' "$1"
sed -i 's/SUB[[:blank:]]*/09 00 00/gi' "$1"
sed -i 's/XOR[[:blank:]]*/0a 00 00/gi' "$1"
sed -i 's/CALL[[:blank:]]/0b/gi' "$1"
sed -i 's/RET[[:blank:]]*/0c 00 00/gi' "$1"
sed -i 's/JMP[[:blank:]]/0d/gi' "$1"
sed -i 's/BEQ[[:blank:]]/0e/gi' "$1"
sed -i 's/BNQ[[:blank:]]/0f/gi' "$1"
sed -i 's/EMC[[:blank:]]/10/gi' "$1"
sed -i 's/NOP[[:blank:]]*/ff 00 00/gi' "$1"
sed -i 's/H//gi' "$1" # remove hex suffix 'h' after only hex digits remain
sed -i 's/ //g' "$1"
#sed -i 's/\n//g' "$1"
}
# link_asm_zp: "links" assembled code to zero page file by simply concatenating
# them, with the total result stored in $1. $1 is the temporary assembled file,
# and $2 is the zero page hexdump file
link_asm_zp() {
cat "$2" "$1" > "$1"-new # cat to temporary file
mv "$1"-new "$1"
rm -f "$1"-new
}
# write_binary: takes path to an "assembled" file in $1 (contains hex), writes
# it to a binary file, path provided by $2
write_binary() {
sed -i 's/ //g' "$1"
tr -d '\n' < "$1" > "$1"mod; mv "$1"mod "$1" # in-place remove newlines
xxd -p -r "$1" > "$2" # writes raw binary
}
usage_msg="Usage: $(basename $0) [vm-source-code] [optional-zero-page-hexdump]"
[ "$#" -ne 1 ] && [ "$#" -ne 2 ] && die "$usage_msg" 69
vm_src="$1"
zp_file="$2"
! [ -f "$vm_src" ] && die "[ERROR]: file $vm_src does not exist" 65
if [ "$#" = 2 ]; then
! [ -f "$zp_file" ] && die "[ERROR]: file $zp_file does not exist" 65
fi
vm_out=$(printf "$vm_src" | sed 's/.asm$/.bin/') # in file.asm, out file.bin
temp_src="${vm_src}-TEMP$(date --iso-8601=ns)" # create temporary file
cp -v "$vm_src" "$temp_src" # copy to temp file
bad_assemble "$temp_src"
if [ "$zp_file" != "" ]; then
link_asm_zp "$temp_src" "$zp_file"
write_binary "$temp_src" "$vm_out"
else
write_binary "$temp_src" "$vm_out"
fi
rm -vf $temp_src # clean up
echo "Assembling $vm_src done. Results in $vm_out"