예제 #1
0
        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);
        }
예제 #2
0
 void TakeRegister(x86Register reg)
 {
     usedRegs[(int)reg] = true;
     if ((int)reg > MaxUsedRegister)
     {
         MaxUsedRegister = (int)reg;
     }
 }
예제 #3
0
        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());
        }
예제 #4
0
        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();
        }
예제 #5
0
 public x86RegisterOperand(x86Register reg)
 {
     Register = reg;
 }
예제 #6
0
 private void TakeRegister(x86Register reg)
 {
     usedRegs[(int)reg] = true;
     if ((int)reg > MaxUsedRegister)
         MaxUsedRegister = (int)reg;
 }
예제 #7
0
 private void ReleaseRegister(x86Register reg)
 {
     usedRegs[(int)reg] = false;
 }
예제 #8
0
		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);
			}
		}
예제 #9
0
        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);
        }
예제 #10
0
		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() + "]";
			}
		}
예제 #11
0
		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!");
			}
		}
예제 #12
0
        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);
            }
        }
예제 #13
0
 void SetRegister(Expression exp, x86Register reg)
 {
     exp.Annotations[REG] = reg;
     regs[(int)reg]       = true;
 }
예제 #14
0
 public x86Instruction[] GetInstructions(out x86Register reg)
 {
     reg = this.reg;
     return(insts.ToArray());
 }
예제 #15
0
		public void WriteRegister(byte o, x86Register r)
		{
			WriteModRM(x86AddressingMode.Register, o, (byte)r);
		}
예제 #16
0
        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();
        }
예제 #17
0
 public x86RegisterOperand(x86Register reg)
 {
     Register = reg;
 }
예제 #18
0
		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 + "]";
		}
예제 #19
0
 void ReleaseRegister(x86Register reg)
 {
     usedRegs[(int)reg] = false;
 }
예제 #20
0
        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;
        }
예제 #21
0
        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;
        }
예제 #22
0
		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);
			}
		}