예제 #1
0
		public Encoding Encode(AddressSize defaultAddressSize, byte modReg, DisplacementSize displacementSize)
		{
			if ((defaultAddressSize == AddressSize._16 && AddressSize == AddressSize._64)
				|| (defaultAddressSize == AddressSize._64 && AddressSize == AddressSize._16))
				throw new ArgumentException(nameof(defaultAddressSize));

			if (modReg >= 8) throw new ArgumentException(nameof(modReg));
			if (!IsEncodableWithDisplacementSize(displacementSize))
				throw new ArgumentException(nameof(displacementSize));

			var encoding = new Encoding()
			{
				Segment = RequiresSegmentOverride ? Segment : (SegmentRegister?)null,
				AddressSizeOverride = AddressSize != defaultAddressSize,
				BaseRegExtension = BaseAsGprCode >= GprCode.R8,
				IndexRegExtension = IndexAsGprCode >= GprCode.R8,
				Displacement = displacement
			};

			if (AddressSize == AddressSize._16) throw new NotImplementedException();

			byte mod;
			switch (displacementSize)
			{
				case DisplacementSize._0: mod = 0; break;
				case DisplacementSize._8: mod = 1; break;
				default: mod = 2; break;
			}

			var @base = Base;
			bool needsSib = false;
			if (AddressSize == AddressSize._64)
			{
				// Same as 32-bit except that [disp32] encodes [rip + disp32]
				if ([email protected]) needsSib = true;
				if (@base == AddressBaseRegister.Rip) @base = null;
			}

			if (@base == AddressBaseRegister.SP || (mod == 0 && @base == AddressBaseRegister.BP))
				needsSib = true;

			if (needsSib)
			{
				if (@base == AddressBaseRegister.BP) throw new NotImplementedException();

				encoding.ModRM = ModRMEnum.FromComponents(mod, modReg, 0) | ModRM.RM_Sib;
				encoding.Sib = SibEnum.FromComponents(
					ss: (byte)((int)(flags & Flags.Scale_Mask) >> (int)Flags.Scale_Shift),
					index: (IndexAsGprCode ?? GprCode.SP).GetLow3Bits(),
					@base: (BaseAsGprCode ?? GprCode.BP).GetLow3Bits());
			}
			else
			{
				encoding.ModRM = ModRMEnum.FromComponents(mod, modReg, (byte)((byte)@base.Value & 0x7));
			}

			return encoding;
		}
예제 #2
0
		public bool IsEncodableWithDisplacementSize(DisplacementSize size)
		{
			return size >= MinimumDisplacementSize
				&& (size == DisplacementSize._16) == (AddressSize == AddressSize._16);
		}