all repos — 3ByteBadVM @ 26457be29042435c16fecfca6a769791e0de512b

3ByteBadVM

ass.sh

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
#!/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/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"