ft(interpreter): impl stosb/stosw

This commit is contained in:
2025-07-24 11:43:08 +09:00
parent b3a24ade00
commit 4cc97cffbf
4 changed files with 110 additions and 36 deletions

View File

@@ -252,6 +252,8 @@ impl Disassembler {
);
let byte = self.parse_byte()?;
let mnemonic = match byte {
0xAA => RepeatableStringOperation::STOSB(Mnemonic::STOSB),
0xAB => RepeatableStringOperation::STOSW(Mnemonic::STOSW),
0xA4 => RepeatableStringOperation::MOVSB(Mnemonic::MOVSB),
0xA5 => RepeatableStringOperation::MOVSW(Mnemonic::MOVSW),
0xA6 => RepeatableStringOperation::CMPSB(Mnemonic::CMPSB),

View File

@@ -53,6 +53,8 @@ pub enum RepeatableStringOperation {
SCASW(Mnemonic),
MOVSB(Mnemonic),
MOVSW(Mnemonic),
STOSB(Mnemonic),
STOSW(Mnemonic),
}
impl RepeatableStringOperation {
@@ -64,13 +66,24 @@ impl RepeatableStringOperation {
RepeatableStringOperation::SCASW(mnemonic) => mnemonic,
RepeatableStringOperation::MOVSB(mnemonic) => mnemonic,
RepeatableStringOperation::MOVSW(mnemonic) => mnemonic,
RepeatableStringOperation::STOSB(mnemonic) => mnemonic,
RepeatableStringOperation::STOSW(mnemonic) => mnemonic,
}
}
}
impl fmt::Display for RepeatableStringOperation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "self.0")
match self {
RepeatableStringOperation::CMPSB(mnemonic) => write!(f, "{}", mnemonic),
RepeatableStringOperation::CMPSW(mnemonic) => write!(f, "{}", mnemonic),
RepeatableStringOperation::SCASB(mnemonic) => write!(f, "{}", mnemonic),
RepeatableStringOperation::SCASW(mnemonic) => write!(f, "{}", mnemonic),
RepeatableStringOperation::MOVSB(mnemonic) => write!(f, "{}", mnemonic),
RepeatableStringOperation::MOVSW(mnemonic) => write!(f, "{}", mnemonic),
RepeatableStringOperation::STOSB(mnemonic) => write!(f, "{}", mnemonic),
RepeatableStringOperation::STOSW(mnemonic) => write!(f, "{}", mnemonic),
}
}
}

View File

@@ -471,52 +471,92 @@ impl Computer {
rep_op: RepeatableStringOperation,
z: bool,
) -> Result<(), InterpreterError> {
while self.regs.cx.read() != 0 {
self.string_ops(rep_op.clone().get())?;
if self.flags.zf == z {
return Ok(());
loop {
if self.regs.cx.read() == 0 {
break;
}
self.string_ops(rep_op.clone().get())?;
self.regs.cx.write(self.regs.cx.read() - 1);
self.regs.di -= 1;
// REPZ stop if zf == 0
// REPNZ stop if zf == 1
match rep_op {
RepeatableStringOperation::CMPSB(_)
| RepeatableStringOperation::CMPSW(_)
| RepeatableStringOperation::SCASB(_)
| RepeatableStringOperation::SCASW(_) => {
if self.flags.zf != z {
break;
}
}
_ => {}
}
}
Ok(())
}
/// Execute string operations.
pub fn string_ops(&mut self, mnemonic: Mnemonic) -> Result<(), InterpreterError> {
fn adjust_sidi(computer: &mut Computer, val: Word) {
if computer.flags.df {
computer.regs.si -= val;
computer.regs.di -= val;
} else {
computer.regs.si += val;
computer.regs.di += val;
}
}
// TODO: can i write this more compact?
match mnemonic {
Mnemonic::CMPSB => self.cmp(
ModRmTarget::Register(crate::register::Register::AL),
ArithmeticOperand::Immediate(ImmediateOperand::Byte(self.read_esdi()? as Byte)),
),
Mnemonic::CMPSW => self.cmp(
ModRmTarget::Register(crate::register::Register::AL),
ArithmeticOperand::Immediate(self.read_esdi()?.into()),
),
Mnemonic::SCASB => self.cmp(
ModRmTarget::Memory(self.regs.si.into()),
ArithmeticOperand::Immediate(ImmediateOperand::Byte(self.read_esdi()? as Byte)),
),
Mnemonic::SCASW => self.cmp(
ModRmTarget::Memory(self.regs.si.into()),
ArithmeticOperand::Immediate(ImmediateOperand::Byte(self.read_esdi()? as Byte)),
),
Mnemonic::CMPSB => {
self.cmp(
ModRmTarget::Register(crate::register::Register::AL),
ArithmeticOperand::Immediate(ImmediateOperand::Byte(self.read_esdi()? as Byte)),
)?;
adjust_sidi(self, 1);
Ok(())
}
Mnemonic::CMPSW => {
self.cmp(
ModRmTarget::Register(crate::register::Register::AL),
ArithmeticOperand::Immediate(self.read_esdi()?.into()),
)?;
adjust_sidi(self, 2);
Ok(())
}
Mnemonic::SCASB => {
self.cmp(
ModRmTarget::Register(crate::register::Register::AL),
ArithmeticOperand::Immediate(ImmediateOperand::Byte(self.read_esdi()? as Byte)),
)?;
if self.flags.df {
self.regs.di -= 1;
} else {
self.regs.di += 1;
}
Ok(())
}
Mnemonic::SCASW => {
self.cmp(
ModRmTarget::Register(crate::register::Register::AX),
ArithmeticOperand::Immediate(ImmediateOperand::Byte(self.read_esdi()? as Byte)),
)?;
if self.flags.df {
self.regs.di -= 2;
} else {
self.regs.di += 2;
}
Ok(())
}
Mnemonic::MOVSB => {
let addr =
self.mem_addr(self.regs.di.into(), &crate::register::SegmentRegister::ES);
let val = self.read(self.regs.si.into())?;
self.memory
.write_raw(addr, ImmediateOperand::Byte(val as u8))?;
if self.flags.df {
self.regs.si -= 1;
self.regs.di -= 1;
} else {
self.regs.si += 1;
self.regs.di += 1;
}
adjust_sidi(self, 1);
Ok(())
}
@@ -525,14 +565,33 @@ impl Computer {
self.mem_addr(self.regs.di.into(), &crate::register::SegmentRegister::ES);
let val = self.read(self.regs.si.into())?;
self.memory.write_raw(addr, val.into())?;
adjust_sidi(self, 2);
Ok(())
}
Mnemonic::STOSB => {
let addr =
self.mem_addr(self.regs.di.into(), &crate::register::SegmentRegister::ES);
let val = self.regs.ax.lower;
self.memory.write_raw(addr, val.into())?;
if self.flags.df {
self.regs.di -= 1;
} else {
self.regs.di += 1;
};
Ok(())
}
Mnemonic::STOSW => {
let addr =
self.mem_addr(self.regs.di.into(), &crate::register::SegmentRegister::ES);
let val = self.regs.ax.read();
self.memory.write_raw(addr, val.into())?;
if self.flags.df {
self.regs.si -= 2;
self.regs.di -= 2;
} else {
self.regs.si += 2;
self.regs.di += 2;
}
};
Ok(())
}

View File

@@ -643,8 +643,6 @@ impl Interpreter {
/*
* String Byte Operations
*/
Mnemonic::STOSB => todo!(),
Mnemonic::STOSW => todo!(),
Mnemonic::LODSB => todo!(),
Mnemonic::LODSW => todo!(),
@@ -654,6 +652,8 @@ impl Interpreter {
Mnemonic::CMPSW => self.computer.string_ops(current_instruction.mnemonic)?,
Mnemonic::MOVSB => self.computer.string_ops(current_instruction.mnemonic)?,
Mnemonic::MOVSW => self.computer.string_ops(current_instruction.mnemonic)?,
Mnemonic::STOSB => self.computer.string_ops(current_instruction.mnemonic)?,
Mnemonic::STOSW => self.computer.string_ops(current_instruction.mnemonic)?,
/*
* RET