コード例 #1
0
        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);
            }
        }