Compare commits

..

No commits in common. "e5180294855b5e36d4dc09ef52b0a7ef3af6dfe4" and "0dfd9bdb57628746803475f57560ab3a079d8510" have entirely different histories.

5 changed files with 80 additions and 188 deletions

View File

@ -56,9 +56,6 @@ class VMAssembler:
self.functions = []
self.decrypt_ops(key)
self.parse_functions()
self.resolve_functions_offsets()
self.resolve_symbols()
self.disassembly()
main = next((x for x in self.functions if x.name == "main"), None)
if main == None:
print("Main has to be defined")
@ -88,46 +85,20 @@ class VMAssembler:
i] = self.functions[i], self.functions[0]
break
def resolve_functions_offsets(self):
# calculating functions offsets
for i in range(1, len(self.functions)):
prev_fun_tot_size = self.functions[
i - 1].size() + self.functions[i - 1].offset
i - 1].size + self.functions[i - 1].offset
cur_fun_size = self.functions[i].size
self.functions[i].set_offset(prev_fun_tot_size)
return
def resolve_symbols(self):
for f in self.functions:
for i in f.instructions:
symcall = symcall_re.match(str(i))
if symcall:
symname = symcall.group(1)
# checking if it's a jump to a label
if symname in [y.label for x in self.functions for y in x.instructions]:
fun = next(
(x for x in self.functions for y in x.instructions if symname == y.label), None)
offset = f.offset_of_label(symname) + f.offset
# function
elif symname in [x.name for x in self.functions]:
offset = next(
(x.offset for x in self.functions if x.name == symname), None)
else:
print("SYMBOL \"{}\" NOT FOUND!".format(symname))
i.args[0].set_value(offset)
def parse(self):
for f in self.functions:
for i in f.instructions:
action = getattr(self, "{}".format(i.opcode.method))
action(i)
def disassembly(self):
for f in self.functions:
print("FUNCTION {}".format(f.name))
for idx, ins in enumerate(f.instructions):
print("{}:\t{}".format(hex(f.offset_of_instruction(idx)), ins))
def imm2reg(self, instruction):
"""
Intel syntax -> REG, IMM
@ -231,11 +202,29 @@ class VMAssembler:
return
def jump(self, instruction):
imm_op_re = re.compile("^([cC][aA][lL]{2})$|(.*[iI])$")
imm_op_re = re.compile(".*[iI]$")
reg_op_re = re.compile(".*[rR]$")
symcall = symcall_re.match(str(instruction))
dst = instruction.args[0]
print(instruction)
# let's check if the jump is to a label or a function
if symcall:
# the symbal has not been resolved
if dst.name == dst.value:
# check whether it is a function
val = next(
(x.offset for x in self.functions if x.name == dst.name), None)
# check whether it is a label
if val == None:
for f in self.functions:
for i in f.instructions:
if i.label == dst.name:
val = f.offset_of_label(dst) + f.offset
if val == None:
raise AssemblerException()
# resolving the symbol
instruction.args[0].set_value(val)
# define the kind of jump: to immediate or to register
if imm_op_re.match(instruction.opcode.name):
self.immonly(instruction)
@ -274,6 +263,7 @@ class VMFunction:
def __init__(self, name, code):
self.name = name
self.size = 0
self.offset = 0
self.instructions = []
@ -293,12 +283,11 @@ class VMFunction:
i += 1
else:
raise InvalidOperation(line)
self.calc_size()
def size(self):
size = 0
def calc_size(self):
for i in self.instructions:
size += i.size
return size
self.size += i.size
def set_offset(self, offset):
self.offset = offset
@ -312,16 +301,8 @@ class VMFunction:
return offset
def offset_of_instruction(self, idx):
offset = 0
for i, ins in enumerate(self.instructions):
if i == idx:
break
offset += ins.size
return offset
def __repr__(self):
return "{}: size {}, offset {}".format(self.name, hex(self.size()), hex(self.offset))
return "{}: size {}, offset {}".format(self.name, hex(self.size), hex(self.offset))
class VMInstruction:
@ -335,7 +316,7 @@ class VMInstruction:
def __init__(self, line, label=None):
self.opcode = None
self.args = []
self.size = 0
self.size = 1
self.label = label
ins = instruction_re.match(line)
@ -345,13 +326,13 @@ class VMInstruction:
self.opcode = next((x for x in ops if x.name == opcode), None)
if self.opcode == None:
raise InvalidOperation(opcode)
self.size = ops_sizes[self.opcode.method]
args = [x for x in ins.groups()[1:] if x is not None]
print("OP: {} | ARGS: {} | SYMCALL: {}".format(self.opcode, args,symcall))
for a in args:
if immediate_re.match(a) or symcall:
# directly append the immediate
self.args.append(VMComponent(a, a))
self.size += 2
continue
elif register_re.match(a):
# create a VM component for a register
@ -359,6 +340,7 @@ class VMInstruction:
if reg == None:
raise InvalidRegister(a)
self.args.append(reg)
self.size += 1
continue
def __repr__(self):
@ -426,10 +408,8 @@ class VMComponent:
op_names = [["MOVI", "imm2reg"],
["MOVR", "reg2reg"],
["LODI", "imm2reg"],
["LODR", "reg2reg"],
["STRI", "imm2reg"],
["STRR", "reg2reg"],
["LOAD", "imm2reg"],
["STOR", "reg2imm"],
["ADDI", "imm2reg"],
["ADDR", "reg2reg"],
["SUBI", "imm2reg"],
@ -454,8 +434,7 @@ op_names = [["MOVI", "imm2reg"],
["SHRR", "reg2reg"],
["PUSH", "regonly"],
["POOP", "regonly"],
["CMPB", "byt2reg"],
["CMPW", "imm2reg"],
["CMPI", "imm2reg"],
["CMPR", "reg2reg"],
["JMPI", "jump"],
["JMPR", "jump"],
@ -467,21 +446,12 @@ op_names = [["MOVI", "imm2reg"],
["JPER", "jump"],
["JPNI", "jump"],
["JPNR", "jump"],
["CALL", "jump"],
["RETN", "single"],
["SHIT", "single"],
["NOPE", "single"],
["GRMN", "single"]]
reg_names = ["R0", "R1", "R2", "R3", "S0", "S1", "S2", "S3", "IP", "RP", "SP"]
ops_sizes = {"reg2reg": 2,
"imm2reg": 4,
"reg2imm": 4,
"byt2reg": 3,
"regonly": 3,
"immonly": 3,
"jump": 3,
"single": 1}
reg_names = ["R0", "R1", "R2", "R3", "S0", "S1", "S2", "S3", "IP", "BP", "SP"]
ops = [VMComponent(le[0], i, le[1]) for i, le in enumerate(op_names)]
regs = [VMComponent(s.casefold(), i) for i, s in enumerate(reg_names)]
instruction_re = re.compile(
@ -491,7 +461,7 @@ immediate_re = re.compile("(?:0x)?[0-9a-fA-F]+$")
alpha_re = re.compile("^[a-zA-Z]*$")
register_re = re.compile("(^[rRsS][0-4]$)|([iIrRsS][pP]$)")
label_re = re.compile("^([a-zA-Z]+)\:$")
symcall_re = re.compile("^(?:[jJ][pPmM][pPaAbBeEnN][iIrR]|(?:[cC][aA][lL]{2}))\ +([\w]*)$")
symcall_re = re.compile("^([jJ][pPmM][pPaAbBeEnN][iIrR])\ +([\w]*)$")
def main():
@ -505,7 +475,6 @@ def main():
filedata = [x.strip() for x in filedata if x.strip()]
vma = VMAssembler(sys.argv[1], filedata)
print(vma.functions)
vma.parse()
with open(sys.argv[3], 'wb') as f:

View File

@ -4,12 +4,11 @@
#include <string.h>
#include <unistd.h>
void encrypt(uint16_t *v, uint16_t *k) {
uint16_t v0 = v[0], v1 = v[1], sum = 0, i; /* set up */
//uint32_t delta = 0x9e3779b9; /* a key schedule constant */
uint16_t delta= 0x9e37;
uint16_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; /* cache key */
for (i = 0; i < 64; i++) { /* basic cycle start */
void encrypt(uint32_t *v, uint32_t *k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0, i; /* set up */
uint32_t delta = 0x9e3779b9; /* a key schedule constant */
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; /* cache key */
for (i = 0; i < 32; i++) { /* basic cycle start */
sum += delta;
v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
@ -29,7 +28,7 @@ int main(int argc, char *argv[]) {
buflen = strlen(argv[1]);
buf = (uint8_t *)malloc(buflen);
memcpy(buf, argv[1], buflen);
encrypt((uint16_t *)buf, (uint16_t *)argv[2]);
encrypt((uint32_t *)buf, (uint32_t *)argv[2]);
printf("Result:\n");
for (i = 0; i < buflen; i++) {
printf("%02x", buf[i]);

View File

@ -4,10 +4,8 @@ MEMORY LOCATIONS AND IMMEDIATES ARE 16 BITS LONG
enum OPS_STARTING_VALUES {
MOVI,
MOVR,
LODI,
LODR,
STRI,
STRR,
LOAD,
STOR,
ADDI,
ADDR,
SUBI,
@ -32,8 +30,7 @@ enum OPS_STARTING_VALUES {
SHRR,
PUSH,
POOP,
CMPB,
CMPW,
CMPI,
CMPR,
JMPI,
JMPR,
@ -45,7 +42,6 @@ enum OPS_STARTING_VALUES {
JPER,
JPNI,
JPNR,
CALL,
RETN,
SHIT,
NOPE,
@ -71,10 +67,8 @@ INSTRUCTION SIZES
*/
#define MOVI_SIZE IMM2REG
#define MOVR_SIZE REG2REG
#define LODI_SIZE IMM2REG
#define LODR_SIZE REG2REG
#define STRI_SIZE IMM2REG
#define STRR_SIZE REG2REG
#define LOAD_SIZE IMM2REG
#define STOR_SIZE REG2IMM
#define ADDI_SIZE IMM2REG
#define ADDR_SIZE REG2REG
#define SUBI_SIZE IMM2REG
@ -99,8 +93,7 @@ INSTRUCTION SIZES
#define SHRR_SIZE REG2REG
#define PUSH_SIZE REGONLY
#define POOP_SIZE REGONLY
#define CMPB_SIZE BYT2REG
#define CMPW_SIZE IMM2REG
#define CMPI_SIZE IMM2REG
#define CMPR_SIZE REG2REG
#define JMPI_SIZE IMMONLY
#define JMPR_SIZE REGONLY

123
vm/vm.cpp
View File

@ -201,58 +201,32 @@ bool VM::execMOVR(void) {
return true;
}
bool VM::execLODI(void) {
bool VM::execLOAD(void) {
/*
LODI R0, 0x1000 -> R0 = data[0x1000]
LOAD R0, 0x1000 -> R0 = data[0x1000]
*/
uint8_t dst;
uint16_t src;
dst = as.code[regs[IP] + 1];
src = *((uint16_t *)&as.code[regs[IP] + 2]);
DBG_INFO(("LODI %s, 0x%x\n", getRegName(dst), src));
DBG_INFO(("LOAD %s, 0x%x\n", getRegName(dst), src));
regs[dst] = *((uint16_t *)&as.data[src]);
return true;
}
bool VM::execLODR(void) {
bool VM::execSTOR(void) {
/*
LODR R1, R0 -> R1 = data[R0]
*/
uint16_t dst;
uint8_t src;
dst = as.code[regs[IP] + 1] >> 4;
src = as.code[regs[IP] + 1] & 0b00001111;
DBG_INFO(("LODR %s, %s\n", getRegName(dst), getRegName(src)));
regs[dst] = *((uint16_t *)&as.data[regs[src]]);
return true;
}
bool VM::execSTRI(void) {
/*
STRI 0x1000, R0 -> data[0x1000] = R0
STOR 0x1000, R0 -> data[0x1000] = R0
*/
uint16_t dst;
uint8_t src;
dst = *((uint16_t *)&as.code[regs[IP] + 1]);
src = as.code[regs[IP] + 3];
DBG_INFO(("STRI 0x%x, %s\n", dst, getRegName(src)));
DBG_INFO(("STOR 0x%x, %s\n", dst, getRegName(src)));
*((uint16_t *)&as.data[dst]) = regs[src];
return true;
}
bool VM::execSTRR(void) {
/*
STRR R1, R0 -> data[R1] = R0
*/
uint8_t dst;
uint8_t src;
dst = as.code[regs[IP] + 1] >> 4;
src = as.code[regs[IP] + 1] & 0b00001111;
DBG_INFO(("STRR %s, %s\n", getRegName(dst), getRegName(src)));
*((uint16_t *)&as.data[regs[dst]]) = regs[src];
return true;
}
bool VM::execADDI(void) {
/*
ADDI R0, 0x2 -> R0 += 2
@ -561,38 +535,16 @@ bool VM::execPOOP(void) {
memcpy(&regs[dst], &as.stack[regs[SP]], sizeof(uint16_t));
return true;
}
bool VM::execCMPB(void) {
bool VM::execCMPI(void) {
/*
CMPB R0, 0x2 -> Compare immediate with lower half (BYTE) register
*/
uint8_t reg;
uint8_t imm;
reg = as.code[regs[IP] + 1];
imm = as.code[regs[IP] + 2];
DBG_INFO(("CMPB %s, 0x%x\n", getRegName(reg), imm));
if (*((uint8_t *)&regs[reg]) == imm) {
flags.ZF = 1;
} else {
flags.ZF = 0;
}
if (*((uint8_t *)&regs[reg]) > imm) {
flags.CF = 1;
} else {
flags.CF = 0;
}
return true;
}
bool VM::execCMPW(void) {
/*
CMPW R0, 0x2 -> Compare immediate with whole (WORD) register
CMPI R0, 0x2 -> Compare immediate with register
*/
uint8_t reg;
uint16_t imm;
reg = as.code[regs[IP] + 1];
imm = *((uint16_t *)&as.code[regs[IP] + 2]);
DBG_INFO(("CMPW %s, 0x%x\n", getRegName(reg), imm));
DBG_INFO(("CMPI %s, 0x%x\n", getRegName(reg), imm));
if (regs[reg] == imm) {
flags.ZF = 1;
} else {
@ -635,6 +587,7 @@ bool VM::execJMPI(void) {
imm = *(uint16_t *)&as.code[regs[IP] + 1];
DBG_INFO(("JMPI 0x%x\n", imm));
regs[RP] = regs[IP] + 3;
regs[IP] = imm;
return true;
}
@ -646,6 +599,7 @@ bool VM::execJMPR(void) {
reg = as.code[regs[IP] + 1];
DBG_INFO(("JMPR %s = 0x%x\n", getRegName(reg), regs[reg]));
regs[RP] = regs[IP] + 2;
regs[IP] = regs[reg];
return true;
}
@ -658,6 +612,7 @@ bool VM::execJPAI(void) {
imm = *(uint16_t *)&as.code[regs[IP] + 1];
DBG_INFO(("JPAI 0x%x\n", imm));
if (flags.CF == 1) {
regs[RP] = regs[IP] + 2;
regs[IP] = imm;
return true;
}
@ -672,6 +627,7 @@ bool VM::execJPAR(void) {
reg = as.code[regs[IP] + 1];
DBG_INFO(("JPAR %s = 0x%x\n", getRegName(reg), regs[reg]));
if (flags.CF == 1) {
regs[RP] = regs[IP] + 2;
regs[IP] = reg;
return true;
}
@ -686,6 +642,7 @@ bool VM::execJPBI(void) {
imm = *(uint16_t *)&as.code[regs[IP] + 1];
DBG_INFO(("JPBI 0x%x\n", imm));
if (flags.CF == 0) {
regs[RP] = regs[IP] + 3;
regs[IP] = imm;
return true;
}
@ -700,6 +657,7 @@ bool VM::execJPBR(void) {
reg = as.code[regs[IP] + 1];
DBG_INFO(("JPBR %s = 0x%x\n", getRegName(reg), regs[reg]));
if (flags.CF == 0) {
regs[RP] = regs[IP] + 2;
regs[IP] = reg;
return true;
}
@ -714,6 +672,7 @@ bool VM::execJPEI(void) {
imm = *(uint16_t *)&as.code[regs[IP] + 1];
DBG_INFO(("JPEI 0x%x\n", imm));
if (flags.ZF == 1) {
regs[RP] = regs[IP] + 2;
regs[IP] = imm;
return true;
}
@ -728,6 +687,7 @@ bool VM::execJPER(void) {
reg = as.code[regs[IP] + 1];
DBG_INFO(("JPER %s = 0x%x\n", getRegName(reg), regs[reg]));
if (flags.ZF == 1) {
regs[RP] = regs[IP] + 2;
regs[IP] = reg;
return true;
}
@ -742,6 +702,7 @@ bool VM::execJPNI(void) {
imm = *(uint16_t *)&as.code[regs[IP] + 1];
DBG_INFO(("JPNI 0x%x\n", imm));
if (flags.ZF == 0) {
regs[RP] = regs[IP] + 2;
regs[IP] = imm;
return true;
}
@ -756,32 +717,17 @@ bool VM::execJPNR(void) {
reg = as.code[regs[IP] + 1];
DBG_INFO(("JPNR %s = 0x%x\n", getRegName(reg), regs[reg]));
if (flags.ZF == 0) {
regs[RP] = regs[IP] + 2;
regs[IP] = reg;
return true;
}
return false;
}
bool VM::execCALL(void) {
/*
CALL 0x1000 -> Jump to data[0x1000] and saves the RP onto the stack
*/
uint16_t dst;
dst = *((uint16_t *)&as.code[regs[IP] + 1]);
DBG_INFO(("CALL 0x%x\n", dst));
*((uint16_t *)&as.stack[regs[SP]]) = regs[IP] + 3;
regs[SP] += sizeof(uint16_t);
regs[IP] = dst;
return false;
}
bool VM::execRETN(void) {
/*
RETN -> IP = RP , restores saved return IP
*/
regs[SP] -= sizeof(uint16_t);
regs[RP] = *((uint16_t *)&as.stack[regs[SP]]);
DBG_INFO(("RETN 0x%x\n", regs[RP]));
regs[IP] = regs[RP];
return true;
}
bool VM::execGRMN(void) {
@ -804,18 +750,12 @@ void VM::run(void) {
} else if (opcode == OPS[MOVR]) {
execMOVR();
regs[IP] += MOVR_SIZE;
} else if (opcode == OPS[LODI]) {
execLODI();
regs[IP] += LODI_SIZE;
} else if (opcode == OPS[LODR]) {
execLODR();
regs[IP] += LODR_SIZE;
} else if (opcode == OPS[STRI]) {
execSTRI();
regs[IP] += STRI_SIZE;
} else if (opcode == OPS[STRR]) {
execSTRR();
regs[IP] += STRR_SIZE;
} else if (opcode == OPS[LOAD]) {
execLOAD();
regs[IP] += LOAD_SIZE;
} else if (opcode == OPS[STOR]) {
execSTOR();
regs[IP] += STOR_SIZE;
} else if (opcode == OPS[ADDI]) {
execADDI();
regs[IP] += ADDI_SIZE;
@ -888,12 +828,9 @@ void VM::run(void) {
} else if (opcode == OPS[POOP]) {
execPOOP();
regs[IP] += POOP_SIZE;
} else if (opcode == OPS[CMPB]) {
execCMPB();
regs[IP] += CMPB_SIZE;
} else if (opcode == OPS[CMPW]) {
execCMPW();
regs[IP] += CMPW_SIZE;
} else if (opcode == OPS[CMPI]) {
execCMPI();
regs[IP] += CMPI_SIZE;
} else if (opcode == OPS[CMPR]) {
execCMPR();
regs[IP] += CMPR_SIZE;
@ -933,8 +870,6 @@ void VM::run(void) {
if (!execJPNR()) {
regs[IP] += JPNR_SIZE;
}
} else if (opcode == OPS[CALL]) {
execCALL();
} else if (opcode == OPS[RETN]) {
execRETN();
regs[IP] = regs[RP];
@ -947,7 +882,7 @@ void VM::run(void) {
} else if (opcode == OPS[NOPE]) {
regs[IP] += NOPE_SIZE;
} else {
DBG_ERROR(("WAT: 0x%x\n", as.code[regs[IP]]));
DBG_ERROR(("WAT\n"));
finished = true;
}
}

10
vm/vm.h
View File

@ -34,10 +34,8 @@ private:
bool execMOVI(void);
bool execMOVR(void);
bool execMOVM(void);
bool execLODI(void);
bool execLODR(void);
bool execSTRI(void);
bool execSTRR(void);
bool execLOAD(void);
bool execSTOR(void);
bool execADDI(void);
bool execADDR(void);
bool execSUBI(void);
@ -62,8 +60,7 @@ private:
bool execSHRR(void);
bool execPUSH(void);
bool execPOOP(void);
bool execCMPB(void);
bool execCMPW(void);
bool execCMPI(void);
bool execCMPR(void);
bool execJMPI(void);
bool execJMPR(void);
@ -75,7 +72,6 @@ private:
bool execJPER(void);
bool execJPNI(void);
bool execJPNR(void);
bool execCALL(void);
bool execRETN(void);
bool execGRMN(void);