private void EmitModRM(byte subOpcode, ref AddrMode addrMode) { byte modRM = (byte)((subOpcode & 0x07) << 3); if (addrMode.BaseReg > Register.None) { Debug.Assert(addrMode.BaseReg >= Register.RegDirect); Register reg = (Register)(addrMode.BaseReg - Register.RegDirect); Builder.EmitByte((byte)(0xC0 | modRM | ((int)reg & 0x07))); } else { byte lowOrderBitsOfBaseReg = (byte)((int)addrMode.BaseReg & 0x07); modRM |= lowOrderBitsOfBaseReg; int offsetSize = 0; if (addrMode.Offset == 0 && (lowOrderBitsOfBaseReg != (byte)Register.EBP)) { offsetSize = 0; } else if (InSignedByteRange(addrMode.Offset)) { offsetSize = 1; modRM |= 0x40; } else { offsetSize = 4; modRM |= 0x80; } bool emitSibByte = false; Register sibByteBaseRegister = addrMode.BaseReg; if (addrMode.BaseReg == Register.None) { emitSibByte = (addrMode.IndexReg != Register.NoIndex); modRM &= 0x38; // set Mod bits to 00 and clear out base reg offsetSize = 4; // this forces 32-bit displacement if (emitSibByte) { // EBP in SIB byte means no base // ModRM base register forced to ESP in SIB code below sibByteBaseRegister = Register.EBP; } else { // EBP in ModRM means no base modRM |= (byte)(Register.EBP); } } else if (lowOrderBitsOfBaseReg == (byte)Register.ESP || addrMode.IndexReg.HasValue) { emitSibByte = true; } if (!emitSibByte) { Builder.EmitByte(modRM); } else { modRM = (byte)((modRM & 0xF8) | (int)Register.ESP); Builder.EmitByte(modRM); int indexRegAsInt = (int)(addrMode.IndexReg.HasValue ? addrMode.IndexReg.Value : Register.ESP); Builder.EmitByte((byte)((addrMode.Scale << 6) + ((indexRegAsInt & 0x07) << 3) + ((int)sibByteBaseRegister & 0x07))); } EmitImmediate(addrMode.Offset, offsetSize); } }