#![allow(dead_code)] use std::process::Command; use xed::{ Insn, MemOperand, MemOperandDisplacement, Operand, Reg, XedAddressWidth, XedInsnIClass, XedMachineMode, XedState, MAX_INSN_BYTES, }; fn main() { decode_test() // encode_test() // raw_encode_test() } fn raw_encode_test() { let operands = unsafe { [ xed_sys2::xed_reg(Reg::XED_REG_RAX), xed_sys2::xed_reg(Reg::XED_REG_RDI), ] }; unsafe { xed_sys2::xed_tables_init() }; let mut insn = unsafe { core::mem::zeroed::() }; let state = xed_sys2::xed_state_t { mmode: XedMachineMode::XED_MACHINE_MODE_LONG_64, stack_addr_width: XedAddressWidth::XED_ADDRESS_WIDTH_64b, }; unsafe { xed_sys2::xed_inst( &mut insn, state, XedInsnIClass::XED_ICLASS_XOR, 64, operands.len() as u32, operands.as_ptr(), ) } let mut req = unsafe { core::mem::zeroed::() }; unsafe { xed_sys2::xed_encoder_request_zero_set_mode(&mut req, &insn.mode) }; let convert_result = unsafe { xed_sys2::xed_convert_to_encoder_request(&mut req, &mut insn) }; assert_ne!(convert_result, 0); let mut buf = [0u8; MAX_INSN_BYTES]; let mut enc_len = 0; let encode_res = unsafe { xed_sys2::xed_encode(&mut req, buf.as_mut_ptr(), buf.len() as u32, &mut enc_len) }; dbg!(encode_res); dbg!(&buf[..enc_len as usize]); } fn encode_test() { let xed_state = XedState::new( XedMachineMode::XED_MACHINE_MODE_LONG_64, XedAddressWidth::XED_ADDRESS_WIDTH_64b, ); let insn = Insn { iclass: XedInsnIClass::XED_ICLASS_ADD, effective_operand_width_in_bits: 64, operands: [ Operand::Reg(Reg::XED_REG_RAX), Operand::Mem(MemOperand { base: None, width_in_bits: 64, seg: None, sib: None, displacement: Some(MemOperandDisplacement { displacement: -5, width_in_bits: 32, }), address_width_in_bits: 64, }), ] .into_iter() .collect(), }; let result = xed_state.encode(&insn).unwrap(); let output_file_path = "/tmp/.xed_enc_test"; std::fs::write(output_file_path, result.as_slice()).unwrap(); let exit_code = Command::new("objdump") .args("-Mintel -D -b binary -Mx86-64 -mi386:x86-64".split(' ')) .arg(output_file_path) .spawn() .unwrap() .wait() .unwrap(); assert!(exit_code.success()); let decoded = xed_state.decode(&result).unwrap(); assert_eq!(decoded.insn, insn); } fn decode_test() { let stdin = std::io::stdin(); let mut input = String::new(); loop { input.clear(); stdin.read_line(&mut input).unwrap(); dump_operands(&input); } } fn dump_operands(assembly_line: &str) { let bytes = nasm_assemble(&format!("bits 64\n{}", assembly_line)); let xed_state = XedState::new( XedMachineMode::XED_MACHINE_MODE_LONG_64, XedAddressWidth::XED_ADDRESS_WIDTH_64b, ); let decoded_insn = xed_state.decode(&bytes).unwrap(); println!("{:#?}", decoded_insn); let encoded = xed_state.encode(&decoded_insn.insn).unwrap(); assert_eq!(encoded.as_slice(), bytes.as_slice()); } fn nasm_assemble(assembly_code: &str) -> Vec { let asm_file_path = "/tmp/.xed_example_basic_nasm.asm"; let output_file_path = "/tmp/.xed_example_basic_nasm.bin"; std::fs::write(asm_file_path, assembly_code.as_bytes()).unwrap(); let exit_code = Command::new("nasm") .arg("-f") .arg("bin") .arg(asm_file_path) .arg("-o") .arg(output_file_path) .spawn() .unwrap() .wait() .unwrap(); assert!(exit_code.success()); std::fs::read(output_file_path).unwrap() }