public Stos(StringOpSettings settings = StringOpSettings.NONE) // Set up the destination to be DI and source to be A. DI will automatically be // treat as a pointer by the base class. : base("STOS", XRegCode.DI, XRegCode.A, settings) { }
public StringOperation(string mnemonic, XRegCode destination, XRegCode source, StringOpSettings settings) { Settings = settings; // Determine capacity as well as an informal mnemonic convention. I haven't seen it defined anywhere, but // in many programs such as GDB and GCC, this is used/accepted. // BYTE => append "B" // WORD => append "W" // DWORD => append "D" // QWORD => append "Q" // E.g, // SCAS RAX, QWORD PTR [RSI] => SCASQ // CMPS BYTE PTR [RDI], BYTE PTR[RSI] => CMPSB // However in my program(as with numerous others), the operands will remain but // without BYTE PTR or equivalent. This does slightly contradict the purpose of // this convention, but I don't expect everyone using the program to know the // operands of every string operation off by heart(as each has a constant set of operands). if ((Settings | StringOpSettings.BYTEMODE) == Settings) { Capacity = RegisterCapacity.BYTE; mnemonic += 'B'; } else if ((ControlUnit.RexByte | REX.W) == ControlUnit.RexByte) { Capacity = RegisterCapacity.QWORD; mnemonic += 'Q'; } else if (ControlUnit.LPrefixBuffer.Contains(PrefixByte.SIZEOVR)) { Capacity = RegisterCapacity.WORD; mnemonic += 'W'; } else { Capacity = RegisterCapacity.DWORD; mnemonic += 'D'; } Mnemonic = mnemonic; // Determine and store the pointer size(There will always be at least one). E.g [RSI] or [ESI]. PtrSize = ControlUnit.LPrefixBuffer.Contains(PrefixByte.ADDROVR) ? RegisterCapacity.DWORD : RegisterCapacity.QWORD; // Create a handle to the destination. If the destination is DI, treat it as a pointer, as DI is always a pointer in a // string operation. destination == XRegCode.DI will also be checked later to mimic the same behaviour. Destination = new ControlUnit.RegisterHandle(destination, RegisterTable.GP, (destination == XRegCode.DI) ? PtrSize : Capacity); // Same as the above Source = new ControlUnit.RegisterHandle(source, RegisterTable.GP, (source == XRegCode.SI) ? PtrSize : Capacity); // Convert the two operands into pointers. These will only be used if their XRegCode is SI or DI, but stored regardless. // Saving these to a variable means that the registers themselves do not have to be operated on until the execution of // the opcode has finished. DestPtr = BitConverter.ToUInt64(Bitwise.ZeroExtend(Destination.FetchOnce(), 8), 0); SrcPtr = BitConverter.ToUInt64(Bitwise.ZeroExtend(Source.FetchOnce(), 8), 0); // Fetch and store the value operand. This will only be ever used if one operand is the A register. This is because // the value of the register is only needed to form the pointers above if the register is SI/DI. There can only // be one operand that is the A register, therefore only the value of that operand needs to be stored. If there // is no A register, SI will be stored in ValueOperand. ValueOperand = (Destination.Code == XRegCode.A) ? Destination.FetchAs(Capacity) : Source.FetchAs(Capacity); OnInitialise(); }
public Cmps(StringOpSettings settings = StringOpSettings.NONE) : base("CMPS", XRegCode.DI, XRegCode.SI, settings | StringOpSettings.COMPARE) { }
public Lods(StringOpSettings settings = StringOpSettings.NONE) : base("LODS", XRegCode.A, XRegCode.SI, settings) { }
public Scas(StringOpSettings settings = StringOpSettings.NONE) : base("SCAS", XRegCode.DI, XRegCode.A, settings | StringOpSettings.COMPARE) { }
public Movs(StringOpSettings settings = StringOpSettings.NONE) : base("MOVS", XRegCode.DI, XRegCode.SI, settings) { }