Added Junk value, for which all operations are
defined to produce junk. Any comparison involving junk triggers the i status register. Any conditional jump triggered when the i register is true, triggers a python level exception.
This commit is contained in:
parent
6d7de5ae75
commit
8b146efe68
41
Emulator.py
41
Emulator.py
|
@ -1,24 +1,33 @@
|
|||
|
||||
import re
|
||||
|
||||
import Junk
|
||||
from opcodes import OPCODES
|
||||
|
||||
REGISTERS=["%rax", "%rbx", "%rcx", "%rdx", "%rsp", "%rbp", "%rsi", "%rdi",
|
||||
"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"]
|
||||
JUNK_VALUE = Junk.Junk()
|
||||
|
||||
class CodeParseException (BaseException):
|
||||
|
||||
def __init__ (self, line_nr, string):
|
||||
self.line_nr = line_nr
|
||||
self.string = string
|
||||
|
||||
class Emulator:
|
||||
|
||||
def __init__ (self, source_text, max_stack_size=1000):
|
||||
self.source = source_text
|
||||
self.registers = {}
|
||||
for reg_name in REGISTERS:
|
||||
self.registers[reg_name] = "Junk"
|
||||
self.registers[reg_name] = JUNK_VALUE
|
||||
self.stack = {}
|
||||
for i in range(max_stack_size):
|
||||
self.stack[i] = 0
|
||||
self.stack[i] = JUNK_VALUE
|
||||
self.code = []
|
||||
self.labels = {}
|
||||
self.changes = {}
|
||||
self.status = {}
|
||||
self.status = {'i':True}
|
||||
self.last_sp = 0
|
||||
self.max_stack_size = 0
|
||||
index = 0
|
||||
|
@ -48,14 +57,18 @@ class Emulator:
|
|||
elif val_text[0] == "%":
|
||||
return self.registers[val_text]
|
||||
else:
|
||||
raise "NOT A VALUE! UGHGUIHGUE!"
|
||||
raise ValueError('{} is not an usable value name'.format(val_text))
|
||||
|
||||
def compareVal (self, valT1, valT2):
|
||||
val1 = self.getVal(valT2)
|
||||
val2 = self.getVal(valT1)
|
||||
if isinstance(val1,Junk.Junk) or isinstance(val2,Junk.Junk):
|
||||
self.status["i"] = (True,)
|
||||
return
|
||||
self.status["g"] = val1>val2
|
||||
self.status["l"] = val1<val2
|
||||
self.status["e"] = val1==val2
|
||||
self.status["i"] = False
|
||||
|
||||
def changedRegisters (self, *args):
|
||||
for reg, val in args:
|
||||
|
@ -63,7 +76,7 @@ class Emulator:
|
|||
|
||||
def processSourceLine(self, line_text, index):
|
||||
tokens = re.findall(r'[^\s,]+', line_text)
|
||||
if len(tokens) <= 0:
|
||||
if len(tokens) <= 0 or tokens[0][0] == '#':
|
||||
return index
|
||||
if tokens[0][-1] == ':':
|
||||
self.labels[tokens[0][:-1]] = index
|
||||
|
@ -96,6 +109,21 @@ class Emulator:
|
|||
self.registers['%rsp'] += 1
|
||||
return temp
|
||||
|
||||
def jump (self, label, cond_op="or", **conditions):
|
||||
if len(conditions)>0 and self.status["i"]:
|
||||
raise Junk.JunkComparisonException(*self.status['i'])
|
||||
and_, or_ = True, False
|
||||
for cnd_name, cnd_val in conditions.iteritems():
|
||||
if self.status[cnd_name] == cnd_val:
|
||||
or_ = True
|
||||
else:
|
||||
and_ = False
|
||||
if or_ if cond_op=="or" else and_:
|
||||
self.registers['%rip'] = self.labels[label]
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def iterate (self):
|
||||
old_rip = self.registers['%rip']
|
||||
self.last_sp = self.registers['%rsp']
|
||||
|
@ -123,3 +151,6 @@ class Emulator:
|
|||
raise StopIteration()
|
||||
else:
|
||||
return output
|
||||
|
||||
def getUsedRegisters (self):
|
||||
return [reg_name for reg_name, reg_val in self.registers.iteritems() if reg_val!=JUNK_VALUE]
|
||||
|
|
27
Junk.py
Normal file
27
Junk.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
|
||||
class JunkComparisonException (BaseException):
|
||||
|
||||
pass
|
||||
|
||||
class Junk:
|
||||
|
||||
def __init__ (self):
|
||||
pass
|
||||
|
||||
def __str__ (self):
|
||||
return "[Junk]"
|
||||
|
||||
def __repr__ (self):
|
||||
return "[Junk]"
|
||||
|
||||
def __add__ (self, other):
|
||||
return self
|
||||
|
||||
def __radd__ (self, other):
|
||||
return self
|
||||
|
||||
def __sub__ (self, other):
|
||||
return self
|
||||
|
||||
def __rsub__ (self, other):
|
||||
return self
|
|
@ -2,8 +2,9 @@
|
|||
import sys
|
||||
import getopt
|
||||
|
||||
from Emulator import Emulator
|
||||
from Emulator import Emulator, CodeParseException
|
||||
from TikzPainter import TikzPainter
|
||||
from Junk import Junk, JunkComparisonException
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
||||
|
|
18
opcodes.py
18
opcodes.py
|
@ -45,33 +45,27 @@ def comp(emu, val1, val2):
|
|||
|
||||
@add_opcode("jg")
|
||||
def jg(emu, label):
|
||||
if emu.status["g"]:
|
||||
emu.registers['%rip'] = emu.labels[label]
|
||||
emu.jump(label, g=True)
|
||||
|
||||
@add_opcode("jl")
|
||||
def jl(emu, label):
|
||||
if emu.status["l"]:
|
||||
emu.registers['%rip'] = emu.labels[label]
|
||||
emu.jump(label, l=True)
|
||||
|
||||
@add_opcode("je")
|
||||
def je(emu, label):
|
||||
if emu.status["e"]:
|
||||
emu.registers['%rip'] = emu.labels[label]
|
||||
emu.jump(label, e=True)
|
||||
|
||||
@add_opcode("jge")
|
||||
def jge(emu, label):
|
||||
if emu.status["g"] or emu.status["e"]:
|
||||
emu.registers['%rip'] = emu.labels[label]
|
||||
emu.jump(label, "or", g=True, e=True)
|
||||
|
||||
@add_opcode("jle")
|
||||
def jle(emu, label):
|
||||
if emu.status["l"] or emu.status["e"]:
|
||||
emu.registers['%rip'] = emu.labels[label]
|
||||
emu.jump(label, "or", l=True, e=True)
|
||||
|
||||
@add_opcode("jne")
|
||||
def jne(emu, label):
|
||||
if not emu.status["e"]:
|
||||
emu.registers['%rip'] = emu.labels[label]
|
||||
emu.jump(label, e=False)
|
||||
|
||||
# Unconditional Jumping
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import os, sys, inspect
|
||||
import traceback
|
||||
sys.path.insert(1, os.path.join(sys.path[0], '..'))
|
||||
|
||||
import infernal
|
||||
|
||||
################################################################################
|
||||
|
@ -9,16 +11,6 @@ tests = []
|
|||
def add_test(name, result, register, code):
|
||||
tests.append((name, result, register, code))
|
||||
|
||||
def execute_test (register, code):
|
||||
emu = infernal.Emulator(code)
|
||||
emu.setStack("junk...", "calling eip")
|
||||
emu.setRegs( rip = 0, rbp = 'old bp')
|
||||
|
||||
for line_nr in emu:
|
||||
pass
|
||||
|
||||
return emu.getVal(register)
|
||||
|
||||
def printf (str, *args):
|
||||
print(str.format(*args))
|
||||
|
||||
|
@ -29,15 +21,32 @@ def execute_tests():
|
|||
error_tests = 0
|
||||
for name, result, register, code in tests:
|
||||
total_tests += 1
|
||||
line_nr = None
|
||||
try:
|
||||
output = execute_test(register, code)
|
||||
emu = infernal.Emulator(code)
|
||||
emu.setStack("junk...", "calling eip")
|
||||
emu.setRegs( rip = 0, rbp = 'old bp')
|
||||
except infernal.CodeParseException as e:
|
||||
error_tests += 1
|
||||
printf("Encountered error when parsing {}, at line {}: {}",
|
||||
name, e.line_nr, e.str)
|
||||
try:
|
||||
for line_nr in emu:
|
||||
pass
|
||||
if isinstance(result, BaseException):
|
||||
printf("Error should have happened in {}, but did not", name)
|
||||
failed_tests += 1
|
||||
output = emu.getVal(register)
|
||||
if output != result:
|
||||
failed_tests += 1
|
||||
printf("Failed in {}. {} was {}, should be {}",
|
||||
name, register, result, output)
|
||||
except BaseException as e:
|
||||
if not isinstance(e, result):
|
||||
error_tests += 1
|
||||
printf("Encountered error in {}: {}",name,e)
|
||||
printf("Encountered error in {}, at operation {}: {}",
|
||||
name, emu.getVal('%rip'), e)
|
||||
traceback.print_exc()
|
||||
printf("Tests done! {}/{}.",
|
||||
total_tests - failed_tests - error_tests, total_tests)
|
||||
printf("{} failed, and {} encountered a python error",
|
||||
|
@ -60,6 +69,56 @@ movq $20, %rax
|
|||
addq %rax, %rsi
|
||||
""")
|
||||
|
||||
################################################################################
|
||||
|
||||
add_test("invalid comparison 1", infernal.JunkComparisonException, "None", """
|
||||
start: movq $100, %rsp # Set stack pointer to a random position.
|
||||
popq %rsi # Move a Junk value into %rsi
|
||||
cmpq $10, %rsi # Do a Junk comparison, which triggers the `i` comp
|
||||
# virtual register.
|
||||
jg start # Attempt to do a jump to the start, if (Junk-10)>0,
|
||||
# which makes no sense, and thus throws an error.
|
||||
""")
|
||||
|
||||
add_test("invalid addition 1", infernal.JunkComparisonException, "None", """
|
||||
start: movq $100, %rsp # Set stack pointer to a random position.
|
||||
popq %rsi # Move a Junk value into %rsi
|
||||
addq %rsi, %rsp # Adds Junk to 101, which produces Junk.
|
||||
cmpq $10, %rsp # Do a Junk comparison, which triggers the `i` comp
|
||||
# virtual register.
|
||||
jg start # Attempt to do a jump to the start, if (Junk-10)>0,
|
||||
# which makes no sense, and thus throws an error.
|
||||
""")
|
||||
|
||||
add_test("invalid addition 2", infernal.JunkComparisonException, "None", """
|
||||
start: movq $100, %rsp # Set stack pointer to a random position.
|
||||
popq %rsi # Move a Junk value into %rsi
|
||||
addq %rsp, %rsi # Adds 101 to Junk, which produces Junk.
|
||||
cmpq $10, %rsi # Do a Junk comparison, which triggers the `i` comp
|
||||
# virtual register.
|
||||
jg start # Attempt to do a jump to the start, if (Junk-10)>0,
|
||||
# which makes no sense, and thus throws an error.
|
||||
""")
|
||||
|
||||
add_test("invalid subtraction 1", infernal.JunkComparisonException, "None", """
|
||||
start: movq $100, %rsp # Set stack pointer to a random position.
|
||||
popq %rsi # Move a Junk value into %rsi
|
||||
subq %rsi, %rsp # Adds Junk to 101, which produces Junk.
|
||||
cmpq $10, %rsp # Do a Junk comparison, which triggers the `i` comp
|
||||
# virtual register.
|
||||
jg start # Attempt to do a jump to the start, if (Junk-10)>0,
|
||||
# which makes no sense, and thus throws an error.
|
||||
""")
|
||||
|
||||
add_test("invalid subtraction 2", infernal.JunkComparisonException, "None", """
|
||||
start: movq $100, %rsp # Set stack pointer to a random position.
|
||||
popq %rsi # Move a Junk value into %rsi
|
||||
subq %rsp, %rsi # Adds 101 to Junk, which produces Junk.
|
||||
cmpq $10, %rsi # Do a Junk comparison, which triggers the `i` comp
|
||||
# virtual register.
|
||||
jg start # Attempt to do a jump to the start, if (Junk-10)>0,
|
||||
# which makes no sense, and thus throws an error.
|
||||
""")
|
||||
|
||||
################################################################################
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user