diff --git a/2020/gctf/sprint/README.md b/2020/gctf/sprint/README.md index a6290ca..69984c8 100644 --- a/2020/gctf/sprint/README.md +++ b/2020/gctf/sprint/README.md @@ -276,7 +276,7 @@ Now we write a python script to parse each of the types of instructions we've seen above, and translate them to human-readable form. We can also check if some of the assumptions we've made hold and print an error message if they don't. The code below is -abbreviated, you can find the full code [here](#). +abbreviated, you can find the full code [here](disassemble.py). #!/usr/bin/env python3 diff --git a/2020/gctf/sprint/disassemble.py b/2020/gctf/sprint/disassemble.py new file mode 100755 index 0000000..9ecf36b --- /dev/null +++ b/2020/gctf/sprint/disassemble.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python3 + +import fileinput +import re + +literalMove = re.compile(r"^%1\$(\d*)s%3\$hn%1\$(\d*)s%1\$(\d*)s%(\d*)\$hn$") +regMove = re.compile(r"^%1\$(\d*)s%3\$hn%1\$(\d*)s%1\$\*(\d*)\$s%(\d*)\$hn$") +regAdd = re.compile(r"^%1\$(\d*)s%3\$hn%1\$(\d*)s%1\$\*(\d*)\$s%1\$\*(\d*)\$s%(\d*)\$hn$") +regLiteralAdd = re.compile(r"^%1\$(\d*)s%3\$hn%1\$(\d*)s%1\$\*(\d*)\$s%1\$(\d*)s%(\d*)\$hn$") +literalRegAdd = re.compile(r"^%1\$(\d*)s%3\$hn%1\$(\d*)s%1\$(\d*)s%1\$\*(\d*)\$s%(\d*)\$hn$") +jump = re.compile(r"^%1\$(\d*)s%3\$hn$") +condJump = re.compile(r"^%(\d*)\$c%1\$(\d*)s%2\$c%4\$s%1\$(\d*)s%3\$hn$") + +# The address of the instruction being read +addr = 0 + + +def showRegisterDest(regRef): + if regRef == 6: + regStr = "(%r1)" + elif regRef >= 7 and regRef <= 23 and regRef % 2 == 1: + regStr = "%r{}".format(regRef // 2 - 2) + else: + print("bad destination: {}".format(regRef)) + exit() + return regStr + + +def showRegisterSource(regRef): + if regRef == 5: + regStr = "(%r1)" + elif regRef >= 6 and regRef <= 22 and regRef % 2 == 0: + regStr = "%r{}".format(regRef // 2 - 2) + else: + print("bad source") + exit() + return regStr + + +for line in fileinput.input(): + oldAddr = addr + addr += len(line) + m = literalMove.match(line) + if m: + nextAddr = int(m.group(1)) + filler = int(m.group(2)) + literal = int(m.group(3)) + regRef = int(m.group(4)) + + if addr != nextAddr: + print("address is not the next instruction") + exit() + if nextAddr + filler != 0x10000: + print("first two numbers do not add to 0x10000") + exit() + + dest = showRegisterDest(regRef) + print("{:04x}: mov 0x{:x}, {}".format(oldAddr, literal, dest)) + continue + + m = regMove.match(line) + if m: + nextAddr = int(m.group(1)) + filler = int(m.group(2)) + sourceRef = int(m.group(3)) + destRef = int(m.group(4)) + + if addr != nextAddr: + print("address is not the next instruction") + exit() + if nextAddr + filler != 0x10000: + print("first two numbers do not add to 0x10000") + exit() + + source = showRegisterSource(sourceRef) + dest = showRegisterDest(destRef) + print("{:04x}: mov {}, {}".format(oldAddr, source, dest)) + continue + + m = regAdd.match(line) + if m: + nextAddr = int(m.group(1)) + filler = int(m.group(2)) + source1Ref = int(m.group(3)) + source2Ref = int(m.group(4)) + destRef = int(m.group(5)) + + if addr != nextAddr: + print("address is not the next instruction") + exit() + if nextAddr + filler != 0x10000: + print("first two numbers do not add to 0x10000") + exit() + + source1 = showRegisterSource(source1Ref) + source2 = showRegisterSource(source2Ref) + dest = showRegisterDest(destRef) + print("{:04x}: add {}, {}, {}".format(oldAddr, source1, source2, dest)) + continue + + m = regLiteralAdd.match(line) + if m: + nextAddr = int(m.group(1)) + filler = int(m.group(2)) + sourceRef = int(m.group(3)) + literal = int(m.group(4)) + destRef = int(m.group(5)) + + if addr != nextAddr: + print("address is not the next instruction") + exit() + if nextAddr + filler != 0x10000: + print("first two numbers do not add to 0x10000") + exit() + + source = showRegisterSource(sourceRef) + dest = showRegisterDest(destRef) + print("{:04x}: add {}, 0x{:x}, {}".format(oldAddr, source, literal, dest)) + continue + + m = literalRegAdd.match(line) + if m: + nextAddr = int(m.group(1)) + filler = int(m.group(2)) + sourceRef = int(m.group(4)) + literal = int(m.group(3)) + destRef = int(m.group(5)) + + if addr != nextAddr: + print("address is not the next instruction") + exit() + if nextAddr + filler != 0x10000: + print("first two numbers do not add to 0x10000") + exit() + + source = showRegisterSource(sourceRef) + dest = showRegisterDest(destRef) + print("{:04x}: add {}, 0x{:x}, {}".format(oldAddr, source, literal, dest)) + continue + + m = jump.match(line) + if m: + target = int(m.group(1)) + if target == 0xfffe: + print("{:04x}: halt".format(oldAddr)) + else: + print("{:04x}: jmp {:04x}".format(oldAddr, target)) + continue + + m = condJump.match(line) + if m: + sourceRef = int(m.group(1)) + fill1 = int(m.group(2)) + fill2 = int(m.group(3)) + + source = showRegisterSource(sourceRef) + + zeroTarget = (fill1 + fill2 + 2) % 0x10000 + nonzeroTarget = (fill1 * 2 + fill2 + 3) % 0x10000 + + if zeroTarget == addr: + print("{:04x}: jnz {}, {:04x}".format(oldAddr, source, nonzeroTarget)) + elif nonzeroTarget == addr: + print("{:04x}: jz {}, {:04x}".format(oldAddr, source, zeroTarget)) + else: + print("neither jump target is the next instruction") + exit() + continue + + print(line[:-1])