#!/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"