use of suite.assembler.Amd64.Operand in project suite by stupidsing.
the class Amd64Assemble method assembleShift.
private InsnCode assembleShift(Instruction instruction, int b, int num) {
if (isRm.test(instruction.op0)) {
Operand shift = instruction.op1;
boolean isShiftImm;
OpImm shiftImm;
int b1;
if (shift instanceof OpImm) {
shiftImm = (OpImm) shift;
isShiftImm = 1 <= shiftImm.imm;
b1 = b + (isShiftImm ? 0 : 16);
} else if (shift.size == 1 && shift instanceof OpReg && ((OpReg) shift).reg == 1) {
// CL
shiftImm = null;
isShiftImm = false;
b1 = b + 16 + 2;
} else
return invalid;
InsnCode insnCode = assembleByteFlag(instruction.op0, b1, num);
if (shiftImm != null && !isShiftImm) {
insnCode.immSize = 1;
insnCode.imm = shiftImm.imm;
}
return insnCode;
} else
return invalid;
}
use of suite.assembler.Amd64.Operand in project suite by stupidsing.
the class Amd64Assemble method assembleInOut.
private InsnCode assembleInOut(Operand port, Operand acc, int b) {
if (isAcc.test(acc)) {
OpImm portImm;
if (port instanceof OpImm)
portImm = (OpImm) port;
else if (// DX
port.size == 2 && port instanceof OpReg && ((OpReg) port).reg == 2)
portImm = null;
else
return invalid;
InsnCode insnCode = new InsnCode(acc.size, bs(b + (acc.size == 1 ? 0 : 1) + (portImm != null ? 0 : 8)));
if (portImm != null) {
insnCode.immSize = 1;
insnCode.imm = portImm.imm;
}
return insnCode;
} else
return invalid;
}
use of suite.assembler.Amd64.Operand in project suite by stupidsing.
the class Amd64Dump method dump.
private String dump(Operand op0) {
int pointerSize = 4;
OpReg[] regs;
String name;
if (pointerSize == 4)
regs = amd64.reg32;
else if (pointerSize == 8)
regs = amd64.reg64;
else
return Fail.t();
if (op0 instanceof OpImm) {
OpImm opImm = (OpImm) op0;
return dump(opImm.imm, opImm.size);
} else if (op0 instanceof OpMem) {
OpMem opMem = (OpMem) op0;
int baseReg = opMem.baseReg;
int indexReg = opMem.indexReg;
String s = //
"" + //
(0 <= baseReg ? " + " + dump(regs[baseReg]) : "") + //
(0 <= indexReg ? " + " + dump(regs[indexReg]) + " * " + (1 << opMem.scale) : "") + (0 < opMem.dispSize ? dumpDisp(opMem.disp, pointerSize) : "");
return "[" + s.substring(3) + "]";
} else if ((name = (amd64.registerByName.inverse().get(op0).name)) != null)
return name;
else
return op0.toString();
}
use of suite.assembler.Amd64.Operand in project suite by stupidsing.
the class Amd64Interpret method interpret.
public int interpret(List<Instruction> instructions, Bytes code, Bytes input) {
mem.position(positionCode0);
mem.put(code.bs);
eip = positionCode0;
regs[esp] = baseStackx - 16;
IntIntMap labels = new IntIntMap();
for (int i = 0; i < instructions.size(); i++) {
int i_ = i;
Instruction instruction = instructions.get(i_);
if (instruction.insn == Insn.LABEL)
labels.update((int) ((OpImm) instruction.op0).imm, i0 -> i_ + 1);
}
while (true) {
Instruction instruction = instructions.get(eip++);
if (Boolean.FALSE)
LogUtil.info(state(instruction));
try {
Operand op0 = instruction.op0;
Operand op1 = instruction.op1;
int source0, source1;
IntSink assign;
if (op0 instanceof OpImm) {
source0 = (int) ((OpImm) op0).imm;
assign = null;
} else if (op0 instanceof OpMem) {
int index = index(address((OpMem) op0));
source0 = mem.getInt(index);
assign = i -> mem.putInt(index, i);
} else if (op0 instanceof OpReg) {
int reg = ((OpReg) op0).reg;
source0 = regs[reg];
assign = i -> {
regs[reg] = i;
};
} else {
source0 = 0;
assign = null;
}
if (op1 instanceof OpImm)
source1 = (int) ((OpImm) op1).imm;
else if (op1 instanceof OpMem)
source1 = mem.getInt(index(address((OpMem) op1)));
else if (op1 instanceof OpReg)
source1 = regs[((OpReg) op1).reg];
else
source1 = 0;
switch(instruction.insn) {
case ADD:
assign.sink(source0 + source1);
break;
case CALL:
push(eip);
eip = labels.get(source0);
break;
case CMP:
c = Integer.compare(source0, source1);
break;
case DEC:
assign.sink(source0 - 1);
break;
case INC:
assign.sink(source0 + 1);
break;
case INT:
if (source0 == -128)
if (regs[eax] == 1)
return regs[ebx];
else if (regs[eax] == 3) {
int length = min(regs[edx], input.size());
int di = index(regs[ecx]);
for (int i = 0; i < length; i++) mem.put(di++, input.get(i));
input = input.range(length);
regs[eax] = length;
} else if (regs[eax] == 4) {
int length = regs[edx];
int si = index(regs[ecx]);
byte[] bs = new byte[length];
for (int i = 0; i < length; i++) bs[i] = mem.get(si++);
output.sink(Bytes.of(bs));
} else
Fail.t();
else
Fail.t();
break;
case JE:
if (c == 0)
eip = labels.get(source0);
break;
case JMP:
eip = labels.get(source0);
break;
case JG:
if (0 < c)
eip = labels.get(source0);
break;
case JGE:
if (0 <= c)
eip = labels.get(source0);
break;
case JL:
if (c < 0)
eip = labels.get(source0);
break;
case JLE:
if (c <= 0)
eip = labels.get(source0);
break;
case JNE:
if (c != 0)
eip = labels.get(source0);
break;
case LABEL:
break;
case LEA:
assign.sink(address((OpMem) op1));
break;
case MOV:
assign.sink(source1);
break;
case POP:
assign.sink(pop());
break;
case PUSH:
push(source0);
break;
case RET:
eip = pop();
break;
case SUB:
assign.sink(source0 - source1);
break;
case XOR:
assign.sink(source0 ^ source1);
break;
default:
Fail.t();
}
} catch (Exception ex) {
LogUtil.info(state(instruction));
throw ex;
}
}
}
use of suite.assembler.Amd64.Operand in project suite by stupidsing.
the class Amd64Assemble method modrm.
private Modrm modrm(Operand operand, int num) {
int mod, rm, s, i, b, dispSize;
long disp;
if (operand instanceof OpReg) {
// EAX
OpReg op = (OpReg) operand;
mod = 3;
rm = op.reg;
s = i = b = -1;
dispSize = 0;
disp = 0;
} else if (operand instanceof OpMem) {
OpMem op = (OpMem) operand;
int baseReg = op.baseReg;
int indexReg;
int ds0 = op.dispSize;
if ((op.indexReg & 7) != 4)
indexReg = op.indexReg;
else
indexReg = Fail.t("bad operand");
if (baseReg < 0 && indexReg < 0) {
// [0x1234]
mod = 0;
rm = 5;
s = i = b = -1;
dispSize = 4;
} else if (0 <= baseReg && indexReg < 0)
if ((baseReg & 7) != 4) {
// [EAX], [EAX + 0x1234]
int ds1 = (baseReg & 7) == 5 && ds0 == 0 ? 1 : ds0;
mod = dispMod(ds1);
rm = baseReg;
s = i = b = -1;
dispSize = ds1;
} else {
// [ESP + 0], [ESP + 0x1234]
int ds1 = baseReg == 4 && ds0 == 0 ? 1 : ds0;
mod = dispMod(ds1);
rm = 4;
s = 0;
i = 4;
b = baseReg & 7;
dispSize = ds1;
}
else if (baseReg < 0 && 0 <= indexReg) {
// [4 * EBX + 0x1234]
mod = 0;
rm = 4;
s = scale(op);
i = indexReg;
b = 5;
dispSize = 4;
} else if (0 <= baseReg && 0 <= indexReg)
if ((baseReg & 7) != 5) {
// [4 * EBX + EAX + 0x1234]
mod = dispMod(ds0);
rm = 4;
s = scale(op);
i = indexReg;
b = baseReg;
dispSize = ds0;
} else
throw new RuntimeException("bad operand");
else
throw new RuntimeException("bad operand");
disp = op.disp;
} else
throw new RuntimeException("bad operand");
Modrm modrm = new Modrm();
modrm.size = operand.size;
modrm.mod = mod;
modrm.num = num;
modrm.rm = rm;
modrm.s = s;
modrm.i = i;
modrm.b = b;
modrm.dispSize = dispSize;
modrm.disp = disp;
return modrm;
}
Aggregations