public x86Visitor(Expression exp, Func <x86Register, x86Instruction[]> args) { insts = new List <x86Instruction>(); this.args = args ?? (_ => new x86Instruction[] { new x86Instruction() { OpCode = x86OpCode.POP, Operands = new Ix86Operand[] { new x86RegisterOperand() { Register = _ } } } }); regs = new bool[8]; regs[(int)x86Register.EBP] = true; //CRITICAL registers! regs[(int)x86Register.ESP] = true; exp.VisitPostOrder(this); reg = GetRegister(exp); }
void TakeRegister(x86Register reg) { usedRegs[(int)reg] = true; if ((int)reg > MaxUsedRegister) { MaxUsedRegister = (int)reg; } }
public static byte[] AssembleCode(x86CodeGen codeGen, x86Register reg) { var stream = new MemoryStream(); using (var writer = new BinaryWriter(stream)) { /* * mov eax, esp * push ebx * push edi * push esi * sub eax, esp * cmp eax, 24 ; determine the bitness of platform * je n * mov eax, [esp + 4] ; 32 bits => argument in stack * push eax * jmp z * n: push ecx ; 64 bits => argument in register * z: XXX * pop esi * pop edi * pop ebx * pop ret * */ writer.Write(new byte[] { 0x89, 0xe0 }); writer.Write(new byte[] { 0x53 }); writer.Write(new byte[] { 0x57 }); writer.Write(new byte[] { 0x56 }); writer.Write(new byte[] { 0x29, 0xe0 }); writer.Write(new byte[] { 0x83, 0xf8, 0x18 }); writer.Write(new byte[] { 0x74, 0x07 }); writer.Write(new byte[] { 0x8b, 0x44, 0x24, 0x10 }); writer.Write(new byte[] { 0x50 }); writer.Write(new byte[] { 0xeb, 0x01 }); writer.Write(new byte[] { 0x51 }); foreach (x86Instruction i in codeGen.Instructions) { writer.Write(i.Assemble()); } if (reg != x86Register.EAX) { writer.Write(x86Instruction.Create(x86OpCode.MOV, new x86RegisterOperand(x86Register.EAX), new x86RegisterOperand(reg)).Assemble()); } writer.Write(new byte[] { 0x5e }); writer.Write(new byte[] { 0x5f }); writer.Write(new byte[] { 0x5b }); writer.Write(new byte[] { 0xc3 }); } return(stream.ToArray()); }
public static byte[] AssembleCode(x86CodeGen codeGen, x86Register reg) { var stream = new MemoryStream(); using (var writer = new BinaryWriter(stream)) { /* * mov eax, esp * push ebx * push edi * push esi * sub eax, esp * cmp eax, 24 ; determine the bitness of platform * je n * mov eax, [esp + 4] ; 32 bits => argument in stack * push eax * jmp z * n: push ecx ; 64 bits => argument in register * z: XXX * pop esi * pop edi * pop ebx * pop ret * */ writer.Write(new byte[] { 0x89, 0xe0 }); writer.Write(new byte[] { 0x53 }); writer.Write(new byte[] { 0x57 }); writer.Write(new byte[] { 0x56 }); writer.Write(new byte[] { 0x29, 0xe0 }); writer.Write(new byte[] { 0x83, 0xf8, 0x18 }); writer.Write(new byte[] { 0x74, 0x07 }); writer.Write(new byte[] { 0x8b, 0x44, 0x24, 0x10 }); writer.Write(new byte[] { 0x50 }); writer.Write(new byte[] { 0xeb, 0x01 }); writer.Write(new byte[] { 0x51 }); foreach (x86Instruction i in codeGen.Instructions) writer.Write(i.Assemble()); if (reg != x86Register.EAX) writer.Write(x86Instruction.Create(x86OpCode.MOV, new x86RegisterOperand(x86Register.EAX), new x86RegisterOperand(reg)).Assemble()); writer.Write(new byte[] { 0x5e }); writer.Write(new byte[] { 0x5f }); writer.Write(new byte[] { 0x5b }); writer.Write(new byte[] { 0xc3 }); } return stream.ToArray(); }
public x86RegisterOperand(x86Register reg) { Register = reg; }
private void TakeRegister(x86Register reg) { usedRegs[(int)reg] = true; if ((int)reg > MaxUsedRegister) MaxUsedRegister = (int)reg; }
private void ReleaseRegister(x86Register reg) { usedRegs[(int)reg] = false; }
public void WriteMemIndex(byte r, x86Register baseReg, int displacement, x86Register indexReg, x86IndexShift iShift) { byte shift = (byte)iShift; switch (shift) { case 0: case 1: case 2: case 3: break; default: throw new Exception("Invalid shift!"); } if (baseReg == x86Register.None) { WriteAddressByte(0, r, 4); WriteAddressByte(shift, (byte)indexReg, 5); WriteImm32((uint)displacement); } else if (displacement == 0 && baseReg != x86Register.EBP) { WriteAddressByte(0, r, 4); WriteAddressByte(shift, (byte)indexReg, (byte)baseReg); } else if (InSByteRange(displacement)) { WriteAddressByte(1, r, 4); WriteAddressByte(shift, (byte)indexReg, (byte)baseReg); WriteImm8((byte)displacement); } else { WriteAddressByte(2, r, 4); WriteAddressByte(shift, (byte)indexReg, (byte)baseReg); WriteImm32((uint)displacement); } }
x86Register Normalize(x86Instruction instr) { if (instr.Operands.Length == 2 && instr.Operands[0] is x86ImmediateOperand && instr.Operands[1] is x86ImmediateOperand) { /* * op imm1, imm2 * ==> * mov reg, imm1 * op reg, imm2 */ x86Register reg = GetFreeRegister(); instrs.Add(x86Instruction.Create(x86OpCode.MOV, new x86RegisterOperand(reg), instr.Operands[0])); instr.Operands[0] = new x86RegisterOperand(reg); instrs.Add(instr); return(reg); } if (instr.Operands.Length == 1 && instr.Operands[0] is x86ImmediateOperand) { /* * op imm * ==> * mov reg, imm * op reg */ x86Register reg = GetFreeRegister(); instrs.Add(x86Instruction.Create(x86OpCode.MOV, new x86RegisterOperand(reg), instr.Operands[0])); instr.Operands[0] = new x86RegisterOperand(reg); instrs.Add(instr); return(reg); } if (instr.OpCode == x86OpCode.SUB && instr.Operands[0] is x86ImmediateOperand && instr.Operands[1] is x86RegisterOperand) { /* * sub imm, reg * ==> * neg reg * add reg, imm */ x86Register reg = ((x86RegisterOperand)instr.Operands[1]).Register; instrs.Add(x86Instruction.Create(x86OpCode.NEG, new x86RegisterOperand(reg))); instr.OpCode = x86OpCode.ADD; instr.Operands[1] = instr.Operands[0]; instr.Operands[0] = new x86RegisterOperand(reg); instrs.Add(instr); return(reg); } if (instr.Operands.Length == 2 && instr.Operands[0] is x86ImmediateOperand && instr.Operands[1] is x86RegisterOperand) { /* * op imm, reg * ==> * op reg, imm */ x86Register reg = ((x86RegisterOperand)instr.Operands[1]).Register; instr.Operands[1] = instr.Operands[0]; instr.Operands[0] = new x86RegisterOperand(reg); instrs.Add(instr); return(reg); } Debug.Assert(instr.Operands.Length > 0); Debug.Assert(instr.Operands[0] is x86RegisterOperand); if (instr.Operands.Length == 2 && instr.Operands[1] is x86RegisterOperand) { ReleaseRegister(((x86RegisterOperand)instr.Operands[1]).Register); } instrs.Add(instr); return(((x86RegisterOperand)instr.Operands[0]).Register); }
public static string NameMembase(x86Register reg, int displacement) { int sVal = (int)displacement; if (displacement == 0) { return "[" + reg.ToString() + "]"; } else if (x86Stream.InSByteRange(sVal)) { return "[" + reg.ToString() + " " + (sVal < 0 ? "-" : "+") + " " + (sVal < 0 ? -sVal : sVal).ToString() + "]"; } else { return "[" + reg.ToString() + " " + (sVal < 0 ? "-" : "+") + " " + (sVal < 0 ? -sVal : sVal).ToString() + "]"; } }
public static string NameRegister(x86Register reg, byte size) { if (reg == x86Register.None) { throw new Exception("This should never happen!"); } switch (size) { case 1: switch(reg) { case x86Register.EAX: return "AL"; case x86Register.EBP: return "CH"; case x86Register.EBX: return "BL"; case x86Register.ECX: return "CL"; case x86Register.EDI: return "BH"; case x86Register.EDX: return "DL"; case x86Register.ESI: return "DH"; case x86Register.ESP: return "AH"; default: throw new Exception("Unknown register!"); } case 2: switch(reg) { case x86Register.EAX: return "AX"; case x86Register.EBP: return "BP"; case x86Register.EBX: return "BX"; case x86Register.ECX: return "CX"; case x86Register.EDI: return "DI"; case x86Register.EDX: return "DX"; case x86Register.ESI: return "SI"; case x86Register.ESP: return "SP"; default: throw new Exception("Unknown register!"); } case 4: return reg.ToString(); default: throw new Exception("Unknown size!"); } }
public override void VisitPostOrder(Expression exp) { x86Register reg = GetFreeRegister(exp); if (exp is ConstantExpression) { insts.Add(new x86Instruction() { OpCode = x86OpCode.MOV, Operands = new Ix86Operand[] { new x86RegisterOperand() { Register = reg }, new x86ImmediateOperand() { Immediate = (exp as ConstantExpression).Value } } }); SetRegister(exp, reg); } else if (exp is VariableExpression) { insts.AddRange(args(reg)); SetRegister(exp, reg); } else if (exp is AddExpression) { AddExpression _exp = exp as AddExpression; insts.Add(new x86Instruction() { OpCode = x86OpCode.ADD, Operands = new Ix86Operand[] { new x86RegisterOperand() { Register = GetRegister(_exp.OperandA) }, new x86RegisterOperand() { Register = GetRegister(_exp.OperandB) } } }); SetRegister(exp, GetRegister(_exp.OperandA)); ReleaseRegister(_exp.OperandB); } else if (exp is SubExpression) { SubExpression _exp = exp as SubExpression; insts.Add(new x86Instruction() { OpCode = x86OpCode.SUB, Operands = new Ix86Operand[] { new x86RegisterOperand() { Register = GetRegister(_exp.OperandA) }, new x86RegisterOperand() { Register = GetRegister(_exp.OperandB) } } }); SetRegister(exp, GetRegister(_exp.OperandA)); ReleaseRegister(_exp.OperandB); } else if (exp is MulExpression) { throw new NotSupportedException(); } else if (exp is DivExpression) { throw new NotSupportedException(); } else if (exp is NegExpression) { NegExpression _exp = exp as NegExpression; insts.Add(new x86Instruction() { OpCode = x86OpCode.NEG, Operands = new Ix86Operand[] { new x86RegisterOperand() { Register = GetRegister(_exp.Value) } } }); SetRegister(exp, GetRegister(_exp.Value)); } else if (exp is InvExpression) { InvExpression _exp = exp as InvExpression; insts.Add(new x86Instruction() { OpCode = x86OpCode.NOT, Operands = new Ix86Operand[] { new x86RegisterOperand() { Register = GetRegister(_exp.Value) } } }); SetRegister(exp, GetRegister(_exp.Value)); } else if (exp is XorExpression) { XorExpression _exp = exp as XorExpression; insts.Add(new x86Instruction() { OpCode = x86OpCode.XOR, Operands = new Ix86Operand[] { new x86RegisterOperand() { Register = GetRegister(_exp.OperandA) }, new x86RegisterOperand() { Register = GetRegister(_exp.OperandB) } } }); SetRegister(exp, GetRegister(_exp.OperandA)); ReleaseRegister(_exp.OperandB); } }
void SetRegister(Expression exp, x86Register reg) { exp.Annotations[REG] = reg; regs[(int)reg] = true; }
public x86Instruction[] GetInstructions(out x86Register reg) { reg = this.reg; return(insts.ToArray()); }
public void WriteRegister(byte o, x86Register r) { WriteModRM(x86AddressingMode.Register, o, (byte)r); }
Ix86Operand Emit(Expression exp, Func <Variable, x86Register, IEnumerable <x86Instruction> > loadArg) { if (exp is BinOpExpression) { var binOp = (BinOpExpression)exp; x86Register reg; switch (binOp.Operation) { case BinOps.Add: reg = Normalize(x86Instruction.Create(x86OpCode.ADD, Emit(binOp.Left, loadArg), Emit(binOp.Right, loadArg))); break; case BinOps.Sub: reg = Normalize(x86Instruction.Create(x86OpCode.SUB, Emit(binOp.Left, loadArg), Emit(binOp.Right, loadArg))); break; case BinOps.Mul: reg = Normalize(x86Instruction.Create(x86OpCode.IMUL, Emit(binOp.Left, loadArg), Emit(binOp.Right, loadArg))); break; case BinOps.Xor: reg = Normalize(x86Instruction.Create(x86OpCode.XOR, Emit(binOp.Left, loadArg), Emit(binOp.Right, loadArg))); break; default: throw new NotSupportedException(); } TakeRegister(reg); return(new x86RegisterOperand(reg)); } if (exp is UnaryOpExpression) { var unaryOp = (UnaryOpExpression)exp; x86Register reg; switch (unaryOp.Operation) { case UnaryOps.Negate: reg = Normalize(x86Instruction.Create(x86OpCode.NEG, Emit(unaryOp.Value, loadArg))); break; case UnaryOps.Not: reg = Normalize(x86Instruction.Create(x86OpCode.NOT, Emit(unaryOp.Value, loadArg))); break; default: throw new NotSupportedException(); } TakeRegister(reg); return(new x86RegisterOperand(reg)); } if (exp is LiteralExpression) { return(new x86ImmediateOperand((int)((LiteralExpression)exp).Value)); } if (exp is VariableExpression) { x86Register reg = GetFreeRegister(); TakeRegister(reg); instrs.AddRange(loadArg(((VariableExpression)exp).Variable, reg)); return(new x86RegisterOperand(reg)); } throw new NotSupportedException(); }
public x86RegisterOperand(x86Register reg) { Register = reg; }
public static string NameMemIndex(x86Assembler a, x86Register baseRegister, int displacement, x86Register indexRegister, x86IndexShift shift, x86Segment segment) { string ret = ""; bool form2 = baseRegister == x86Register.None; if (form2) { ret += NameSegment(segment) + ":0x" + displacement.ToString("X").PadLeft(8, '0'); } ret += "[" + NameRegister(indexRegister, 4); switch (shift) { case x86IndexShift.Mul1: break; case x86IndexShift.Mul2: ret += " * 2"; break; case x86IndexShift.Mul4: ret += " * 4"; break; case x86IndexShift.Mul8: ret += " * 8"; break; default: throw new Exception("Invalid index shift!"); } if (baseRegister != x86Register.None) { ret += " + " + NameRegister(baseRegister, 4); } if (displacement != 0 && !form2) { ret += " " + (displacement < 0 ? "-" : "+") + " " + (displacement < 0 ? -displacement : displacement).ToString(); } return ret + "]"; }
void ReleaseRegister(x86Register reg) { usedRegs[(int)reg] = false; }
internal void DecodeRegisterPair(x86Instruction instruction, byte registerToken, out x86Register register1, out x86Register register2) { byte registerToken1 = (byte)(registerToken >> 4 << 4); // high bits. byte registerToken2 = (byte)(registerToken - registerToken1); // lower bits. while (registerToken1 >= 0x40) registerToken1 -= 0x40; registerToken1 /= 8; if (registerToken2 > 0x7) { registerToken2 -= 8; registerToken1++; } switch (instruction.OpCode.OperandType) { case x86OperandType.Multiple16Register: // add bit16 mask registerToken1 |= (byte)x86Register.Bit16Mask; registerToken2 |= (byte)x86Register.Bit16Mask; break; case x86OperandType.Multiple32Or8Register: // Not sure if right or not byte mask1; byte mask2; GetDoubleRegisterMask(registerToken, out mask1, out mask2); registerToken1 |= mask1; registerToken2 |= mask2; break; case x86OperandType.Multiple32Register: // do nothing, normal registers are used. break; } // notice inverted registers. register2 = (x86Register)registerToken1; register1 = (x86Register)registerToken2; }
private void DecodeRegisterPair(x86Instruction instruction, byte registerToken, out x86Register register1, out x86Register register2) { byte registerToken1 = (byte)(registerToken >> 4 << 4); // high bits. byte registerToken2 = (byte)(registerToken - registerToken1); // lower bits. while (registerToken1 >= 0x40) { registerToken1 -= 0x40; } registerToken1 /= 8; if (registerToken2 > 0x7) { registerToken2 -= 8; registerToken1++; } switch (instruction.OpCode.OperandType) { case x86OperandType.Multiple16Register: // add bit16 mask registerToken1 |= (byte)x86Register.Bit16Mask; registerToken2 |= (byte)x86Register.Bit16Mask; break; case x86OperandType.Multiple32Or8Register: // Not sure if right or not byte mask1; byte mask2; GetRegisterMask(registerToken, out mask1, out mask2); registerToken1 |= mask1; registerToken2 |= mask2; break; case x86OperandType.Multiple32Register: // do nothing, normal registers are used. break; } // notice inverted registers. register2 = (x86Register)registerToken1; register1 = (x86Register)registerToken2; }
public void WriteMembase(byte r, x86Register baseReg, int displacement) { if (baseReg == x86Register.ESP) { if (displacement == 0) { WriteAddressByte(0, r, (byte)x86Register.ESP); WriteAddressByte(0, (byte)x86Register.ESP, (byte)x86Register.ESP); } else if (InSByteRange(displacement)) { WriteAddressByte(1, r, (byte)x86Register.ESP); WriteAddressByte(0, (byte)x86Register.ESP, (byte)x86Register.ESP); WriteImm8((byte)displacement); } else { WriteAddressByte(2, r, (byte)x86Register.ESP); WriteAddressByte(0, (byte)x86Register.ESP, (byte)x86Register.ESP); WriteImm32((uint)displacement); } } else if (displacement == 0 && baseReg != x86Register.EBP) { WriteAddressByte(0, r, (byte)baseReg); } else if (InSByteRange(displacement)) { WriteAddressByte(1, r, (byte)baseReg); WriteImm8((byte)displacement); } else { WriteAddressByte(2, r, (byte)baseReg); WriteImm32((uint)displacement); } }