Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lods stos #35

Merged
merged 2 commits into from Oct 30, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
67 changes: 67 additions & 0 deletions src/ops.rs
Expand Up @@ -1275,5 +1275,72 @@ 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()?;
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()});
}