ft(interpreter): impl stosb/stosw
This commit is contained in:
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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(
|
||||
Mnemonic::CMPSB => {
|
||||
self.cmp(
|
||||
ModRmTarget::Register(crate::register::Register::AL),
|
||||
ArithmeticOperand::Immediate(ImmediateOperand::Byte(self.read_esdi()? as Byte)),
|
||||
),
|
||||
Mnemonic::CMPSW => self.cmp(
|
||||
)?;
|
||||
adjust_sidi(self, 1);
|
||||
Ok(())
|
||||
}
|
||||
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()),
|
||||
)?;
|
||||
adjust_sidi(self, 2);
|
||||
Ok(())
|
||||
}
|
||||
Mnemonic::SCASB => {
|
||||
self.cmp(
|
||||
ModRmTarget::Register(crate::register::Register::AL),
|
||||
ArithmeticOperand::Immediate(ImmediateOperand::Byte(self.read_esdi()? as Byte)),
|
||||
),
|
||||
Mnemonic::SCASW => self.cmp(
|
||||
ModRmTarget::Memory(self.regs.si.into()),
|
||||
)?;
|
||||
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(())
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user