libmwemu 0.24.3

x86 32/64bits and system internals emulator, for securely emulating malware and other stuff.
Documentation
use iced_x86::{Code, Instruction, Mnemonic};

use super::Emu;

impl Emu {
    pub(crate) fn handle_x86_rep_pre_execution(
        &mut self,
        instruction: Instruction,
        size: usize,
    ) -> bool {
        let is_ret = matches!(instruction.code(), Code::Retnw | Code::Retnd | Code::Retnq);
        let has_rep_prefix = instruction.has_rep_prefix()
            || instruction.has_repe_prefix()
            || instruction.has_repne_prefix();

        if is_ret || !has_rep_prefix {
            return false;
        }

        if self.rep.is_none() {
            self.rep = Some(0);
        }

        if self.regs().rcx == 0 {
            self.rep = None;
            if self.cfg.is_x64() {
                self.regs_mut().rip += size as u64;
            } else {
                let new_eip = self.regs().get_eip() + size as u64;
                self.regs_mut().set_eip(new_eip);
            }
            return true;
        }

        false
    }

    pub(crate) fn update_x86_rep_state_after_execution(&mut self, instruction: Instruction) {
        let Some(rep_count) = self.rep else {
            return;
        };

        if self.cfg.verbose >= 3 {
            log::trace!("    rcx: {}", self.regs().rcx);
        }

        if self.regs().rcx > 0 {
            self.regs_mut().rcx -= 1;
            if self.regs().rcx == 0 {
                self.rep = None;
            } else {
                self.rep = Some(rep_count + 1);
            }
        }

        let is_string_movement = matches!(
            instruction.mnemonic(),
            Mnemonic::Movsb
                | Mnemonic::Movsw
                | Mnemonic::Movsd
                | Mnemonic::Movsq
                | Mnemonic::Stosb
                | Mnemonic::Stosw
                | Mnemonic::Stosd
                | Mnemonic::Stosq
                | Mnemonic::Lodsb
                | Mnemonic::Lodsw
                | Mnemonic::Lodsd
                | Mnemonic::Lodsq
        );
        let is_string_comparison = matches!(
            instruction.mnemonic(),
            Mnemonic::Cmpsb
                | Mnemonic::Cmpsw
                | Mnemonic::Cmpsd
                | Mnemonic::Cmpsq
                | Mnemonic::Scasb
                | Mnemonic::Scasw
                | Mnemonic::Scasd
                | Mnemonic::Scasq
        );

        if is_string_movement {
            return;
        }

        if is_string_comparison {
            if instruction.has_repe_prefix() && !self.flags().f_zf {
                self.rep = None;
            }
            if instruction.has_repne_prefix() && self.flags().f_zf {
                self.rep = None;
            }
            return;
        }

        self.rep = None;
    }
}