Skip to content

Commit

Permalink
lods and stos added
Browse files Browse the repository at this point in the history
Signed-off-by: VoR0220 <catalanor0220@gmail.com>
  • Loading branch information
VoR0220 committed Oct 30, 2019
1 parent 8c7e2d0 commit d99d057
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 3 deletions.
14 changes: 13 additions & 1 deletion src/opcodes.rs
Expand Up @@ -1119,7 +1119,19 @@ lazy_static! {
.into_table(&mut ops);
//0xA7 CMPSD/CMPSW
define_opcode(0xA7).calls(cmps_native_word).with_gas(Low)
.into_table(&mut ops);
.into_table(&mut ops);
//0xAA STOS m8
define_opcode(0xAA).calls(store_string_byte).with_gas(Low)
.into_table(&mut ops);
//0xAB STOS m16/m32
define_opcode(0xAB).calls(store_string_native_word).with_gas(Low)
.into_table(&mut ops);
//0xAC LODS m8
define_opcode(0xAC).calls(load_string_byte).with_gas(Low)
.into_table(&mut ops);
//0xAD LODS m16/m32
define_opcode(0xAD).calls(load_string_native_word).with_gas(Low)
.into_table(&mut ops);
ops
};
}
Expand Down
68 changes: 68 additions & 0 deletions src/ops.rs
Expand Up @@ -1275,5 +1275,73 @@ pub fn cmpsb(vm: &mut VM, pipeline: &Pipeline, hv: &mut dyn Hypervisor) -> Resul
vm.set_reg32(Reg32::EDI, vm.reg32(Reg32::EDI).wrapping_add(d));
vm.set_reg32(Reg32::ESI, vm.reg32(Reg32::ESI).wrapping_add(d));

Ok(())
}

pub fn store_string_byte(vm: &mut VM, pipeline: &Pipeline, hv: &mut dyn Hypervisor) -> Result<(), VMError>{
vm.set_mem(vm.reg32(Reg32::EDI), vm.get_reg(Reg8::AL as u8, ValueSize::Byte))?;
let d = if vm.flags.direction{
(-1i32) as u32
}else{
1
};
vm.set_reg32(Reg32::EDI, vm.reg32(Reg32::EDI).wrapping_add(d));
Ok(())
}

pub fn load_string_byte(vm: &mut VM, pipeline: &Pipeline, hv: &mut dyn Hypervisor) -> Result<(), VMError>{
let esi_mem = vm.get_mem(vm.reg32(Reg32::ESI), ValueSize::Byte)?.u8_exact()?;
println!("load_string_byte: {}", esi_mem);
vm.set_reg(Reg8::AL as u8, SizedValue::Byte(esi_mem as u8));
let d = if vm.flags.direction{
(-1i32) as u32
}else{
1
};
vm.set_reg32(Reg32::ESI, vm.reg32(Reg32::ESI).wrapping_add(d));
Ok(())
}

pub fn store_string_native_word(vm: &mut VM, pipeline: &Pipeline, hv: &mut dyn Hypervisor) -> Result<(), VMError>{
if pipeline.size_override{
vm.set_mem(vm.reg32(Reg32::EDI), vm.get_reg(Reg16::AX as u8, ValueSize::Word))?;
let d = if vm.flags.direction{
(-2i32) as u32
}else{
2
};
vm.set_reg32(Reg32::EDI, vm.reg32(Reg32::EDI).wrapping_add(d));
} else {
vm.set_mem(vm.reg32(Reg32::EDI), vm.get_reg(Reg32::EAX as u8, ValueSize::Dword))?;
let d = if vm.flags.direction{
(-4i32) as u32
}else{
4
};
vm.set_reg32(Reg32::EDI, vm.reg32(Reg32::EDI).wrapping_add(d));
}
Ok(())
}

pub fn load_string_native_word(vm: &mut VM, pipeline: &Pipeline, hv: &mut dyn Hypervisor) -> Result<(), VMError>{
if pipeline.size_override{
let esi_mem = vm.get_mem(vm.reg32(Reg32::ESI), ValueSize::Word)?.u16_exact()?;
vm.set_reg(Reg16::AX as u8, SizedValue::Word(esi_mem));
let d = if vm.flags.direction{
(-2i32) as u32
}else{
2
};
vm.set_reg32(Reg32::ESI, vm.reg32(Reg32::ESI).wrapping_add(d));
} else {
let esi_mem = vm.get_mem(vm.reg32(Reg32::ESI), ValueSize::Dword)?.u32_exact()?;
vm.set_reg(Reg32::EAX as u8, SizedValue::Dword(esi_mem));
let d = if vm.flags.direction{
(-4i32) as u32
}else{
4
};
vm.set_reg32(Reg32::ESI, vm.reg32(Reg32::ESI).wrapping_add(d));
}
Ok(())
}
65 changes: 63 additions & 2 deletions tests/simple_tests.rs
Expand Up @@ -13,13 +13,14 @@ fn test_undefined_opcode(){
let bytes = vec![
0x90, //nop
0x90,
0xAA, //eventually this might not be an undefined opcode
0x0F,
0x0B,
0x90,
0x90
];
vm.copy_into_memory(CODE_MEM, &bytes).unwrap();
let mut hv = TestHypervisor::default();
assert_eq!(vm.execute(&mut hv).err().unwrap(), VMError::InvalidOpcode(0xAA));
assert_eq!(vm.execute(&mut hv).err().unwrap(), VMError::InvalidOpcode(0x0F));
assert_eq!(vm.error_eip, CODE_MEM + 2);
}

Expand Down Expand Up @@ -1344,4 +1345,64 @@ fn test_repe_cmpsd() {
assert_eq!(vm.reg32(Reg32::EDI), 0x80000008);
assert_eq!(vm.reg32(Reg32::ECX), 1);
assert_eq!(vm.flags, X86Flags{ adjust: true, parity: true, ..Default::default()});
}

#[test]
fn test_lodsb_stosb() {
let vm = execute_vm_with_asm("
mov esi, 0x80000000
mov edi, 0x80000004
mov byte [esi], 0x08
mov ecx, 1
rep lodsb
mov ecx, 3
rep stosb
mov ebx, dword [edi - 3]
hlt");
assert_eq!(vm.reg32(Reg32::ESI), 0x80000001);
assert_eq!(vm.reg32(Reg32::EDI), 0x80000007);
assert_eq!(vm.reg32(Reg32::ECX), 0);
assert_eq!(vm.reg32(Reg32::EAX), 0x00000008);
assert_eq!(vm.reg32(Reg32::EBX), 0x00080808);
assert_eq!(vm.flags, X86Flags{..Default::default()});
}

#[test]
fn test_lodsw_stosw() {
let vm = execute_vm_with_asm("
mov esi, 0x80000000
mov edi, 0x80000004
mov word [esi], 0x8008
mov ecx, 1
rep lodsw
mov ecx, 2
rep stosw
mov ebx, dword [edi - 4]
hlt");
assert_eq!(vm.reg32(Reg32::ESI), 0x80000002);
assert_eq!(vm.reg32(Reg32::EDI), 0x80000008);
assert_eq!(vm.reg32(Reg32::ECX), 0);
assert_eq!(vm.reg32(Reg32::EAX), 0x00008008);
assert_eq!(vm.reg32(Reg32::EBX), 0x80088008);
assert_eq!(vm.flags, X86Flags{..Default::default()});
}

#[test]
fn test_lodsd_stosd() {
let vm = execute_vm_with_asm("
mov esi, 0x80000000
mov edi, 0x80000008
mov dword [esi], 0x8080BEAD
mov ecx, 1
rep lodsd
mov ecx, 1
rep stosd
mov ebx, dword [edi - 4]
hlt");
assert_eq!(vm.reg32(Reg32::ESI), 0x80000004);
assert_eq!(vm.reg32(Reg32::EDI), 0x8000000c);
assert_eq!(vm.reg32(Reg32::ECX), 0);
assert_eq!(vm.reg32(Reg32::EAX), 0x8080bead);
assert_eq!(vm.reg32(Reg32::EBX), 0x8080bead);
assert_eq!(vm.flags, X86Flags{..Default::default()});
}

0 comments on commit d99d057

Please sign in to comment.