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

Lods stos #35

Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

@@ -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
};
}
@@ -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(())
}
@@ -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);
}

@@ -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()});
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.