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 byte = self.parse_byte()?;
let mnemonic = match byte { let mnemonic = match byte {
0xAA => RepeatableStringOperation::STOSB(Mnemonic::STOSB),
0xAB => RepeatableStringOperation::STOSW(Mnemonic::STOSW),
0xA4 => RepeatableStringOperation::MOVSB(Mnemonic::MOVSB), 0xA4 => RepeatableStringOperation::MOVSB(Mnemonic::MOVSB),
0xA5 => RepeatableStringOperation::MOVSW(Mnemonic::MOVSW), 0xA5 => RepeatableStringOperation::MOVSW(Mnemonic::MOVSW),
0xA6 => RepeatableStringOperation::CMPSB(Mnemonic::CMPSB), 0xA6 => RepeatableStringOperation::CMPSB(Mnemonic::CMPSB),

View File

@@ -53,6 +53,8 @@ pub enum RepeatableStringOperation {
SCASW(Mnemonic), SCASW(Mnemonic),
MOVSB(Mnemonic), MOVSB(Mnemonic),
MOVSW(Mnemonic), MOVSW(Mnemonic),
STOSB(Mnemonic),
STOSW(Mnemonic),
} }
impl RepeatableStringOperation { impl RepeatableStringOperation {
@@ -64,13 +66,24 @@ impl RepeatableStringOperation {
RepeatableStringOperation::SCASW(mnemonic) => mnemonic, RepeatableStringOperation::SCASW(mnemonic) => mnemonic,
RepeatableStringOperation::MOVSB(mnemonic) => mnemonic, RepeatableStringOperation::MOVSB(mnemonic) => mnemonic,
RepeatableStringOperation::MOVSW(mnemonic) => mnemonic, RepeatableStringOperation::MOVSW(mnemonic) => mnemonic,
RepeatableStringOperation::STOSB(mnemonic) => mnemonic,
RepeatableStringOperation::STOSW(mnemonic) => mnemonic,
} }
} }
} }
impl fmt::Display for RepeatableStringOperation { impl fmt::Display for RepeatableStringOperation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 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, rep_op: RepeatableStringOperation,
z: bool, z: bool,
) -> Result<(), InterpreterError> { ) -> Result<(), InterpreterError> {
while self.regs.cx.read() != 0 { loop {
self.string_ops(rep_op.clone().get())?; if self.regs.cx.read() == 0 {
break;
if self.flags.zf == z {
return Ok(());
} }
self.string_ops(rep_op.clone().get())?;
self.regs.cx.write(self.regs.cx.read() - 1); 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(()) Ok(())
} }
/// Execute string operations. /// Execute string operations.
pub fn string_ops(&mut self, mnemonic: Mnemonic) -> Result<(), InterpreterError> { 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 { match mnemonic {
Mnemonic::CMPSB => self.cmp( Mnemonic::CMPSB => {
ModRmTarget::Register(crate::register::Register::AL), self.cmp(
ArithmeticOperand::Immediate(ImmediateOperand::Byte(self.read_esdi()? as Byte)), 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), adjust_sidi(self, 1);
ArithmeticOperand::Immediate(self.read_esdi()?.into()), Ok(())
), }
Mnemonic::SCASB => self.cmp( Mnemonic::CMPSW => {
ModRmTarget::Memory(self.regs.si.into()), self.cmp(
ArithmeticOperand::Immediate(ImmediateOperand::Byte(self.read_esdi()? as Byte)), ModRmTarget::Register(crate::register::Register::AL),
), ArithmeticOperand::Immediate(self.read_esdi()?.into()),
Mnemonic::SCASW => self.cmp( )?;
ModRmTarget::Memory(self.regs.si.into()), adjust_sidi(self, 2);
ArithmeticOperand::Immediate(ImmediateOperand::Byte(self.read_esdi()? as Byte)), 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 => { Mnemonic::MOVSB => {
let addr = let addr =
self.mem_addr(self.regs.di.into(), &crate::register::SegmentRegister::ES); self.mem_addr(self.regs.di.into(), &crate::register::SegmentRegister::ES);
let val = self.read(self.regs.si.into())?; let val = self.read(self.regs.si.into())?;
self.memory self.memory
.write_raw(addr, ImmediateOperand::Byte(val as u8))?; .write_raw(addr, ImmediateOperand::Byte(val as u8))?;
adjust_sidi(self, 1);
if self.flags.df {
self.regs.si -= 1;
self.regs.di -= 1;
} else {
self.regs.si += 1;
self.regs.di += 1;
}
Ok(()) Ok(())
} }
@@ -525,14 +565,33 @@ impl Computer {
self.mem_addr(self.regs.di.into(), &crate::register::SegmentRegister::ES); self.mem_addr(self.regs.di.into(), &crate::register::SegmentRegister::ES);
let val = self.read(self.regs.si.into())?; let val = self.read(self.regs.si.into())?;
self.memory.write_raw(addr, val.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 { if self.flags.df {
self.regs.si -= 2;
self.regs.di -= 2; self.regs.di -= 2;
} else { } else {
self.regs.si += 2;
self.regs.di += 2; self.regs.di += 2;
} };
Ok(()) Ok(())
} }

View File

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