protected IList<AddressIndependentThing> EncodeImmediate(RISA.Operand op) { var immop = op as ImmediateOperand; var addrop = op as AddressOperand; if (immop != null) { byte[] bytes = null; switch (op.Size) { case OperandSize.Byte: bytes = new byte[1] { (byte)immop.Value }; break; case OperandSize.Word: bytes = BitConverter.GetBytes((short)immop.Value); break; case OperandSize.DWord: bytes = BitConverter.GetBytes((int)immop.Value); break; case OperandSize.QWord: bytes = BitConverter.GetBytes(immop.Value); break; } return bytes.Convert(); } else if (addrop != null) { return new List<AddressIndependentThing>() { AIF.Instance.Address(addrop.Label) }; } return null; }
private bool IsExtendedRegister(RISA.Operand op) { var rop = op as RegisterOperand; if (rop != null) { if (rop.Type.IsCombo(RISA.OperandType.ArgumentRegister)) { return rop.Index == 2 || rop.Index == 3; } // general register case? } return false; }
protected byte RegisterIndex(RISA.Operand baseOperand) { var operand = baseOperand as RegisterOperand; if (operand == null) throw new Exception("ModRM.rm not register"); if (operand.Type.IsCombo(RISA.OperandType.ReturnRegister)) return 0; // rax | xmm0 else if (operand.Type.IsCombo(RISA.OperandType.StackRegister)) return 4; else if (operand.Type.IsCombo(RISA.OperandType.ReturnRegister)) return 5; else if (operand.Type.IsCombo(RISA.OperandType.ArgumentRegister)) { switch (operand.Index) { case 0: return 1; //TODO: windows only case 1: return 2; //TODO: windows only case 2: return 0; case 3: return 1; } } else if (operand.Type.IsCombo(RISA.OperandType.GeneralRegister)) { switch (operand.Index) { case 0: return 3; case 1: return 6; case 2: return 7; default: return (byte)(operand.Index - 2); } } throw new Exception("Unexpected register"); }
private bool IsLargeOperand(RISA.Operand op) { return op.Size == OperandSize.QWord || op.Size == OperandSize.OWord; }
private void ProcessOp(ref byte modrm, ref byte sib, Operand localOperand, RISA.Operand op) { if (localOperand.Type == OperandType.Register) PutValue(ref modrm, ref sib, localOperand.EncodingPosition, RegisterIndex(op)); else if (localOperand.Type == OperandType.Memory) { var mop = op as MemoryOperand; var registerOffset = mop.Address as RegisterOperand; var offsetOffset = mop.Address as OffsetOperand; var addrOffset = mop.Address as AddressOperand; if (registerOffset != null) { PutValue(ref modrm, ref sib, EncodingPosition.Mod, 0); byte regIndex = RegisterIndex(registerOffset); switch (regIndex & 7) { case 4: //SP/R12 PutValue(ref modrm, ref sib, EncodingPosition.RM, regIndex); PutValue(ref modrm, ref sib, EncodingPosition.Index, regIndex); PutValue(ref modrm, ref sib, EncodingPosition.Base, regIndex); break; case 5: // BP/R13 throw new Exception("this is weird"); default: // check for scale, indexer, etc PutValue(ref modrm, ref sib, EncodingPosition.RM, regIndex); break; } } else if (offsetOffset != null) { byte regIndex = RegisterIndex(offsetOffset.Register); switch (regIndex & 7) { case 4: //SP/R12 PutValue(ref modrm, ref sib, EncodingPosition.RM, regIndex); PutValue(ref modrm, ref sib, EncodingPosition.Index, (byte)(regIndex & 7)); PutValue(ref modrm, ref sib, EncodingPosition.Base, regIndex); break; case 5: // BP/R13 throw new Exception("this is weird"); default: // check for scale, indexer, etc PutValue(ref modrm, ref sib, EncodingPosition.RM, regIndex); break; } if (offsetOffset.Immediate.Size == OperandSize.S8) { PutValue(ref modrm, ref sib, EncodingPosition.Mod, 1); delayAdd = EncodeImmediate(offsetOffset.Immediate); } else if (offsetOffset.Immediate.Size == OperandSize.S32) { PutValue(ref modrm, ref sib, EncodingPosition.Mod, 2); delayAdd = EncodeImmediate(offsetOffset.Immediate); } else throw new Exception("Invalid memory offset size"); } else if(addrOffset != null) { PutValue(ref modrm, ref sib, EncodingPosition.Mod, 0); PutValue(ref modrm, ref sib, EncodingPosition.RM, 5); // [disp32] maybe? delayAdd = new List<AddressIndependentThing>() { AIF.Instance.Address(addrOffset.Label, addrOffset.Size == OperandSize.QWord) }; } } }