differentiate numerical imm and label imm,
implement assembler, add binary file outputs to gitignore, add development container for assembler
This commit is contained in:
parent
216d118967
commit
5d8ea74edc
6
.devcontainer/Dockerfile
Normal file
6
.devcontainer/Dockerfile
Normal file
@ -0,0 +1,6 @@
|
||||
FROM python:slim
|
||||
WORKDIR /
|
||||
RUN apt-get -y update; apt-get -y upgrade
|
||||
RUN apt-get -y install git binutils
|
||||
COPY requirements.txt .
|
||||
RUN pip install -r requirements.txt
|
30
.devcontainer/devcontainer.json
Normal file
30
.devcontainer/devcontainer.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "cse141L development container",
|
||||
"build": {
|
||||
"dockerfile": "Dockerfile",
|
||||
},
|
||||
"settings": {
|
||||
"terminal.integrated.shell.linux": "/bin/bash",
|
||||
"python.pythonPath": "/usr/local/bin/python",
|
||||
"python.linting.enabled": true,
|
||||
"python.linting.pylintEnabled": true,
|
||||
"python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
|
||||
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
|
||||
"python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
|
||||
"python.linting.banditPath": "/usr/local/py-utils/bin/bandit",
|
||||
"python.linting.flake8Path": "/usr/local/py-utils/bin/flake8",
|
||||
"python.linting.mypyPath": "/usr/local/py-utils/bin/mypy",
|
||||
"python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle",
|
||||
"python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle",
|
||||
"python.linting.pylintPath": "/usr/local/bin/pylint",
|
||||
"python.testing.pytestPath": "/usr/local/py-utils/bin/pytest",
|
||||
"editor.tabSize": 4,
|
||||
"editor.insertSpaces": false
|
||||
},
|
||||
"extensions": [
|
||||
"mhutchie.git-graph",
|
||||
"ms-python.python",
|
||||
"waderyan.gitblame"
|
||||
],
|
||||
"postCreateCommand": ""
|
||||
}
|
1
.devcontainer/requirements.txt
Normal file
1
.devcontainer/requirements.txt
Normal file
@ -0,0 +1 @@
|
||||
tqdm
|
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
**/*.bin
|
138
assembler.py
Normal file
138
assembler.py
Normal file
@ -0,0 +1,138 @@
|
||||
from re import M
|
||||
import sys
|
||||
from tqdm import tqdm
|
||||
|
||||
reg_map = {
|
||||
'r0': 0,
|
||||
'r1': 1,
|
||||
'r2': 2,
|
||||
'r3': 3,
|
||||
'r4': 4,
|
||||
'r5': 5,
|
||||
'r6': 6,
|
||||
'r7': 7,
|
||||
'r8': 8,
|
||||
'r9': 9,
|
||||
'r10': 10,
|
||||
'r11': 11,
|
||||
'r12': 12,
|
||||
'r13': 13,
|
||||
'r14': 14,
|
||||
'r15': 15
|
||||
}
|
||||
|
||||
op_type = {
|
||||
'LDI': 'I',
|
||||
'PUT': 'A',
|
||||
'GET': 'A',
|
||||
'LDW': 'S',
|
||||
'STW': 'S',
|
||||
'NXT': 'S',
|
||||
'CLB': 'G',
|
||||
'ADD': 'A',
|
||||
'SUB': 'A',
|
||||
'ORR': 'A',
|
||||
'AND': 'A',
|
||||
'LSH': 'T',
|
||||
'PTY': 'G',
|
||||
'CHK': 'A',
|
||||
'XOR': 'A',
|
||||
'JNZ': 'G',
|
||||
'JEZ': 'G',
|
||||
'JMP': 'G',
|
||||
'JAL': 'G'
|
||||
}
|
||||
|
||||
op_codes = {
|
||||
'LDI': 0b1_0000_0000,
|
||||
'PUT': 0b0_0000_0000,
|
||||
'GET': 0b0_0001_0000,
|
||||
'LDW': 0b0_0010_0000,
|
||||
'STW': 0b0_0010_1000,
|
||||
'NXT': 0b0_0011_0000,
|
||||
'CLB': 0b0_0011_1000,
|
||||
'ADD': 0b0_0100_0000,
|
||||
'SUB': 0b0_0101_0000,
|
||||
'ORR': 0b0_0110_0000,
|
||||
'AND': 0b0_0111_0000,
|
||||
'LSH': 0b0_1000_0000,
|
||||
'PTY': 0b0_1000_1000,
|
||||
'CHK': 0b0_1001_0000,
|
||||
'XOR': 0b0_1010_0000,
|
||||
'JNZ': 0b0_1110_0000,
|
||||
'JEZ': 0b0_1110_1000,
|
||||
'JMP': 0b0_1111_0000,
|
||||
'JAL': 0b0_1111_1000
|
||||
}
|
||||
|
||||
def get_reg(type, opcode):
|
||||
if type == 'S':
|
||||
return reg_map[opcode] - 8
|
||||
elif type == 'G':
|
||||
return reg_map[opcode]
|
||||
elif type == 'A':
|
||||
return reg_map[opcode]
|
||||
else:
|
||||
print('invalid opcode detected: ' + opcode)
|
||||
exit(1)
|
||||
|
||||
def get_immediate(operand, labels):
|
||||
if operand.startswith("#b"):
|
||||
operand = operand.strip("#b")
|
||||
return int(operand, 2)
|
||||
elif operand.startswith("#x"):
|
||||
operand = operand.strip("#x")
|
||||
return int(operand, 16)
|
||||
elif operand.startswith("#d"):
|
||||
operand = operand.strip("#d")
|
||||
return int(operand, 10)
|
||||
elif operand in labels:
|
||||
return labels[operand]
|
||||
else:
|
||||
print('invalid immediate detected: ' + operand)
|
||||
exit(1)
|
||||
|
||||
output = sys.argv[1]
|
||||
targets = sys.argv[2:]
|
||||
print('detected targets: ' + str(targets))
|
||||
for file in targets:
|
||||
print('assembing: ' + file)
|
||||
no_comments = []
|
||||
instructions = []
|
||||
labels = {}
|
||||
index = 0
|
||||
raw_lines = []
|
||||
instructions = []
|
||||
f = open(file, 'r')
|
||||
for line in f:
|
||||
raw_lines.append(line)
|
||||
for line in tqdm(raw_lines, desc='Preprocessing', unit=' lines'):
|
||||
line = line.split('//')[0] # remove comments
|
||||
if line != '':
|
||||
line = line.replace('\t', '') # remove leading tabs
|
||||
line = line.replace('\n', '') # remove trailing newline
|
||||
if ': ' in line:
|
||||
labels[line.split(': ')[0]] = index # ': ' must be used to end a label
|
||||
no_comments.append(line.split(': ')[1])
|
||||
else:
|
||||
no_comments.append(line)
|
||||
index += 1
|
||||
index = 0
|
||||
for line in tqdm(no_comments, desc='Operand', unit=' operands'):
|
||||
line = line.split(' ')
|
||||
opcode = line[0]
|
||||
operand = line[1]
|
||||
if op_type[opcode] == "I" or op_type[opcode] == "T":
|
||||
operand = get_immediate(operand, labels)
|
||||
else:
|
||||
operand = get_reg(op_type[opcode], operand)
|
||||
instructions.append((opcode, operand))
|
||||
#print(str(index+1) + " " + str(opcode) + " " + str(operand))
|
||||
index += 1
|
||||
out = open(output, "wb")
|
||||
for inst in tqdm(instructions, desc='Assembly', unit=' instructions'):
|
||||
opcode = op_codes[inst[0]]
|
||||
operand = inst[1]
|
||||
#print(str(opcode) + " " + str(operand))
|
||||
#print(str(opcode | operand))
|
||||
out.write((opcode| operand).to_bytes(length=2, byteorder='big'))
|
14
program1.asm
14
program1.asm
@ -28,34 +28,34 @@ preamble_loop: LDI #d32 // get space character decimal 32
|
||||
XOR r7 // bitwise XOR the current state with plaintext space to generate ciphertext
|
||||
CLB r0 // clear the leading bit of the ciphertext as in requirements
|
||||
STW r12 // store ciphertext to write pointer
|
||||
LDI #lfsr_routine // load address for the lfsr_routine label
|
||||
LDI lfsr_routine // load address for the lfsr_routine label
|
||||
JAL r0 // jump to the lfsr_routine label
|
||||
NXT r12 // increment write pointer
|
||||
NXT r9 // decrement number of remaining ciphertext characters
|
||||
LDI #main_loop // load the address of label main_loop
|
||||
LDI main_loop // load the address of label main_loop
|
||||
NXT r8 // decrement preamble counter
|
||||
JEZ r0 // exit preamble loop if the preamble counter has just reached 0
|
||||
LDI #preamble_loop // load the address of label preamble_loop
|
||||
LDI preamble_loop // load the address of label preamble_loop
|
||||
JMP r0 // jump to preamble_loop if there are more space characters to encode
|
||||
main_loop: LDW r11 // load the next plaintext byte
|
||||
XOR r7 // bitwise XOR the current state with plaintext space to generate ciphertext
|
||||
CLB r0 // clear the leading bit of the ciphertext as in requirements
|
||||
STW r12 // store ciphertext to write pointer
|
||||
LDI #lfsr_routine // load address for the lfsr_routine label
|
||||
LDI lfsr_routine // load address for the lfsr_routine label
|
||||
JAL r0 // jump to the lfsr_routine label
|
||||
NXT r11 // increment read pointer
|
||||
NXT r12 // increment write pointer
|
||||
LDI #done // load address of label done
|
||||
LDI done // load address of label done
|
||||
NXT r9 // decrement number of remaining ciphertext chars
|
||||
JEZ r0 // jump to end of program if all ciphertext chars have been processed
|
||||
LDI #main_loop // load address of main_loop
|
||||
LDI main_loop // load address of main_loop
|
||||
JMP r0 // jump to main_loop if there is still space for message characters
|
||||
lfsr_routine: GET r7 // get previous state
|
||||
AND r6 // and state with taps to get feedback pattern
|
||||
PTY r0 // get feedback parity bit
|
||||
PUT r1 // store feedback bit to r1 temporarily
|
||||
GET r7 // get previous state again
|
||||
LSH #1 // left shift previous state by 1
|
||||
LSH #d1 // left shift previous state by 1
|
||||
ORR r1 // or with parity bit to get next state
|
||||
PUT r7 // put next state to r7
|
||||
GET r14 // load link register
|
||||
|
25
program2.asm
25
program2.asm
@ -10,7 +10,7 @@
|
||||
// r12 is the write pointer
|
||||
init: LDI #d10
|
||||
PUT r10 // set the tap counter to 10, which will choose tap pattern 9 to start after subtracting by 1
|
||||
tap_lut: LDI #tap_init
|
||||
tap_lut: LDI tap_init
|
||||
JMP r0 // goto tap_init, skipping the LUT
|
||||
LDI #x60 // load tap pattern 1
|
||||
JMP r5 // jump back to tap loop
|
||||
@ -38,11 +38,12 @@ tap_init: LDI #d64
|
||||
PUT r8 // load 10 into preamble counter
|
||||
LDI #d64
|
||||
PUT r9 // load 64 (total encryption length) to r9
|
||||
LDI done
|
||||
NXT r10 // decrement tap selection by 1, starts at 9 for the first iteration
|
||||
JEZ #done // if no more taps left that didn't work, raise the done flag
|
||||
LDI #tap_init
|
||||
JEZ r0 // if no more taps left that didn't work, raise the done flag
|
||||
LDI tap_init
|
||||
PUT r5 // put the tap_loop address in r5
|
||||
LDI #tap_lut
|
||||
LDI tap_lut
|
||||
ADD r10
|
||||
ADD r10 // add 2*tap select to tap_lut location, results in location of selected tap pattern
|
||||
JMP r0 // jump to LUT, which loads the tap pattern into r0
|
||||
@ -56,13 +57,13 @@ tap_init: LDI #d64
|
||||
NXT r11 // increment read pointer
|
||||
NXT r12 // increment write pointer
|
||||
NXT r9 // decrement total encryption chars remaining
|
||||
tap_loop: LDI #lfsr_routine
|
||||
tap_loop: LDI lfsr_routine
|
||||
JAL r0 // jump to lfsr routine which calculates next state in r7
|
||||
LDI #d32 // load space char expected plaintext
|
||||
XOR r7
|
||||
CLB r0 // clear leading bit in the expected ciphertext
|
||||
PUT r1 // store expected cipher text in r1
|
||||
LDI #tap_init
|
||||
LDI tap_init
|
||||
PUT r2 // load the outer loop top into r2
|
||||
LDW r11 // load actual ciphertext
|
||||
SUB r1 // subtract actual from expected, result of 0 means matching
|
||||
@ -72,30 +73,30 @@ tap_init: LDI #d64
|
||||
NXT r11 // increment read pointer
|
||||
NXT r12 // increment write pointer
|
||||
NXT r9 // decrement total encryption chars remaining
|
||||
LDI #main_loop // load main_loop location into r0
|
||||
LDI main_loop // load main_loop location into r0
|
||||
NXT r8 // decrement preamble counter
|
||||
JEZ r0 // if r8 (preamble counter) is zero, then all preamble have matched and current tap pattern is correct, jump to main loop
|
||||
LDI #tap_loop
|
||||
LDI tap_loop
|
||||
JMP r0 // jump to tap_loop if characters matched but preamble is not over
|
||||
main_loop: LDW r11 // load the next ciphertext byte
|
||||
XOR r7 // bitwise XOR the current state with ciphertext space to generate plaintext
|
||||
CLB r0 // clear the leading bit of the plaintext as in requirements
|
||||
STW r12 // store plaintext to write pointer
|
||||
LDI #lfsr_routine // load address for the lfsr_routine label
|
||||
LDI lfsr_routine // load address for the lfsr_routine label
|
||||
JAL r0 // jump to the lfsr_routine label
|
||||
NXT r11 // increment read pointer
|
||||
NXT r12 // increment write pointer
|
||||
LDI #done // load address of label done
|
||||
LDI done // load address of label done
|
||||
NXT r9 // decrement number of remaining plaintext chars
|
||||
JEZ r0 // jump to end of program if all plaintext chars have been processed
|
||||
LDI #main_loop // load address of main_loop
|
||||
LDI main_loop // load address of main_loop
|
||||
JMP r0 // jump to main_loop if there is still space for message characters
|
||||
lfsr_routine: GET r7 // get previous state
|
||||
AND r6 // and state with taps to get feedback pattern
|
||||
PTY r0 // get feedback parity bit
|
||||
PUT r1 // store feedback bit to r1 temporarily
|
||||
GET r7 // get previous state again
|
||||
LSH #1 // left shift previous state by 1
|
||||
LSH #d1 // left shift previous state by 1
|
||||
ORR r1 // or with parity bit to get next state
|
||||
PUT r7 // put next state to r7
|
||||
GET r14 // load link register
|
||||
|
29
program3.asm
29
program3.asm
@ -10,7 +10,7 @@
|
||||
// r12 is the write pointer
|
||||
init: LDI #d10
|
||||
PUT r10 // set the tap counter to 10, which will choose tap pattern 9 to start after subtracting by 1
|
||||
tap_lut: LDI #tap_init
|
||||
tap_lut: LDI tap_init
|
||||
JMP r0 // goto tap_init, skipping the LUT
|
||||
LDI #x60 // load tap pattern 1
|
||||
JMP r5 // jump back to tap loop
|
||||
@ -38,11 +38,12 @@ tap_init: LDI #d64
|
||||
PUT r8 // load 10 into preamble counter
|
||||
LDI #d64
|
||||
PUT r9 // load 64 (total encryption length) to r9
|
||||
LDI done
|
||||
NXT r10 // decrement tap selection by 1, starts at 9 for the first iteration
|
||||
JEZ #done // if no more taps left that didn't work, raise the done flag
|
||||
LDI #tap_init
|
||||
JEZ r0 // if no more taps left that didn't work, raise the done flag
|
||||
LDI tap_init
|
||||
PUT r5 // put the tap_loop address in r5
|
||||
LDI #tap_lut
|
||||
LDI tap_lut
|
||||
ADD r10
|
||||
ADD r10 // add 2*tap select to tap_lut location, results in location of selected tap pattern
|
||||
JMP r0 // jump to LUT, which loads the tap pattern into r0
|
||||
@ -56,13 +57,13 @@ tap_init: LDI #d64
|
||||
NXT r11 // increment read pointer
|
||||
NXT r12 // increment write pointer
|
||||
NXT r9 // decrement total encryption chars remaining
|
||||
tap_loop: LDI #lfsr_routine
|
||||
tap_loop: LDI lfsr_routine
|
||||
JAL r0 // jump to lfsr routine which calculates next state in r7
|
||||
LDI #d32 // load space char expected plaintext
|
||||
XOR r7
|
||||
CLB r0 // clear leading bit in the expected ciphertext
|
||||
PUT r1 // store expected cipher text in r1
|
||||
LDI #tap_init
|
||||
LDI tap_init
|
||||
PUT r2 // load the outer loop top into r2
|
||||
LDW r11 // load actual ciphertext
|
||||
SUB r1 // subtract actual from expected, result of 0 means matching
|
||||
@ -72,38 +73,38 @@ tap_init: LDI #d64
|
||||
NXT r11 // increment read pointer
|
||||
NXT r12 // increment write pointer
|
||||
NXT r9 // decrement total encryption chars remaining
|
||||
LDI #main_loop // load main_loop location into r0
|
||||
LDI main_loop // load main_loop location into r0
|
||||
NXT r8 // decrement preamble counter
|
||||
JEZ r0 // if r8 (preamble counter) is zero, then all preamble have matched and current tap pattern is correct, jump to main loop
|
||||
LDI #tap_loop
|
||||
LDI tap_loop
|
||||
JMP r0 // jump to tap_loop if characters matched but preamble is not over
|
||||
main_loop: LDI #correct
|
||||
main_loop: LDI correct
|
||||
PUT r1 // put correct handle address in r1
|
||||
LDW r11 // load the next ciphertext byte
|
||||
CHK r0 // check ciphertext for error
|
||||
JEZ r1 // if no error, jump to correct, otherwise continue to error handling
|
||||
error: LDI #x80 // load error flag character into r0
|
||||
STW r12 // store error flag to write pointer
|
||||
LDI #common
|
||||
LDI common
|
||||
JMP r0 // jump out of error handling, to common operations after writing
|
||||
correct: XOR r7 // bitwise XOR the current state with ciphertext space to generate plaintext
|
||||
CLB r0 // clear the leading bit of the plaintext as in requirements
|
||||
STW r12 // store plaintext to write pointer
|
||||
common: LDI #lfsr_routine // load address for the lfsr_routine label
|
||||
common: LDI lfsr_routine // load address for the lfsr_routine label
|
||||
JAL r0 // jump to the lfsr_routine label
|
||||
NXT r11 // increment read pointer
|
||||
NXT r12 // increment write pointer
|
||||
LDI #done // load address of label done
|
||||
LDI done // load address of label done
|
||||
NXT r9 // decrement number of remaining plaintext chars
|
||||
JEZ r0 // jump to end of program if all plaintext chars have been processed
|
||||
LDI #main_loop // load address of main_loop
|
||||
LDI main_loop // load address of main_loop
|
||||
JMP r0 // jump to main_loop if there is still space for message characters
|
||||
lfsr_routine: GET r7 // get previous state
|
||||
AND r6 // and state with taps to get feedback pattern
|
||||
PTY r0 // get feedback parity bit
|
||||
PUT r1 // store feedback bit to r1 temporarily
|
||||
GET r7 // get previous state again
|
||||
LSH #1 // left shift previous state by 1
|
||||
LSH #d1 // left shift previous state by 1
|
||||
ORR r1 // or with parity bit to get next state
|
||||
PUT r7 // put next state to r7
|
||||
GET r14 // load link register
|
||||
|
Reference in New Issue
Block a user