namespace X86Disassembler.X86.Handlers.String;
/// 
/// Handler for string instructions (MOVS, STOS, LODS, SCAS)
/// 
public class StringInstructionHandler : InstructionHandler
{
    /// 
    /// Initializes a new instance of the StringInstructionHandler class
    /// 
    /// The buffer containing the code to decode
    /// The instruction decoder that owns this handler
    /// The length of the buffer
    public StringInstructionHandler(byte[] codeBuffer, InstructionDecoder decoder, int length) 
        : base(codeBuffer, decoder, length)
    {
    }
    
    /// 
    /// Checks if this handler can handle the given opcode
    /// 
    /// The opcode to check
    /// True if this handler can handle the opcode
    public override bool CanHandle(byte opcode)
    {
        // Check if the opcode is a string instruction
        return opcode == 0xA4 || opcode == 0xA5 || // MOVS
               opcode == 0xAA || opcode == 0xAB || // STOS
               opcode == 0xAC || opcode == 0xAD || // LODS
               opcode == 0xAE || opcode == 0xAF;   // SCAS
    }
    
    /// 
    /// Decodes a string instruction
    /// 
    /// The opcode to decode
    /// The instruction to populate
    /// True if the instruction was successfully decoded
    public override bool Decode(byte opcode, Instruction instruction)
    {
        // Set the mnemonic
        instruction.Mnemonic = OpcodeMap.GetMnemonic(opcode);
        
        // Set the operands based on the string operation
        switch (opcode)
        {
            case 0xA4: // MOVSB
                instruction.Operands = "byte ptr [edi], byte ptr [esi]";
                break;
            case 0xA5: // MOVSD
                instruction.Operands = "dword ptr [edi], dword ptr [esi]";
                break;
            case 0xAA: // STOSB
                instruction.Operands = "byte ptr [edi], al";
                break;
            case 0xAB: // STOSD
                instruction.Operands = "dword ptr [edi], eax";
                break;
            case 0xAC: // LODSB
                instruction.Operands = "al, byte ptr [esi]";
                break;
            case 0xAD: // LODSD
                instruction.Operands = "eax, dword ptr [esi]";
                break;
            case 0xAE: // SCASB
                instruction.Operands = "al, byte ptr [edi]";
                break;
            case 0xAF: // SCASD
                instruction.Operands = "eax, dword ptr [edi]";
                break;
            default:
                instruction.Operands = "??";
                break;
        }
        
        return true;
    }
}