1#![allow(dead_code)]
2use std::process::Command;
3
4use xed::{
5 Insn, MemOperand, MemOperandDisplacement, Operand, Reg, XedAddressWidth, XedInsnIClass,
6 XedMachineMode, XedState, MAX_INSN_BYTES,
7};
8
9fn main() {
10 decode_test()
11 }
14
15fn raw_encode_test() {
16 let operands = unsafe {
17 [
18 xed_sys2::xed_reg(Reg::XED_REG_RAX),
19 xed_sys2::xed_reg(Reg::XED_REG_RDI),
20 ]
21 };
22 unsafe { xed_sys2::xed_tables_init() };
23 let mut insn = unsafe { core::mem::zeroed::<xed_sys2::xed_encoder_instruction_t>() };
24 let state = xed_sys2::xed_state_t {
25 mmode: XedMachineMode::XED_MACHINE_MODE_LONG_64,
26 stack_addr_width: XedAddressWidth::XED_ADDRESS_WIDTH_64b,
27 };
28 unsafe {
29 xed_sys2::xed_inst(
30 &mut insn,
31 state,
32 XedInsnIClass::XED_ICLASS_XOR,
33 64,
34 operands.len() as u32,
35 operands.as_ptr(),
36 )
37 }
38 let mut req = unsafe { core::mem::zeroed::<xed_sys2::xed_encoder_request_t>() };
39 unsafe { xed_sys2::xed_encoder_request_zero_set_mode(&mut req, &insn.mode) };
40 let convert_result = unsafe { xed_sys2::xed_convert_to_encoder_request(&mut req, &mut insn) };
41 assert_ne!(convert_result, 0);
42 let mut buf = [0u8; MAX_INSN_BYTES];
43 let mut enc_len = 0;
44 let encode_res =
45 unsafe { xed_sys2::xed_encode(&mut req, buf.as_mut_ptr(), buf.len() as u32, &mut enc_len) };
46 dbg!(encode_res);
47 dbg!(&buf[..enc_len as usize]);
48}
49
50fn encode_test() {
51 let xed_state = XedState::new(
52 XedMachineMode::XED_MACHINE_MODE_LONG_64,
53 XedAddressWidth::XED_ADDRESS_WIDTH_64b,
54 );
55 let insn = Insn {
56 iclass: XedInsnIClass::XED_ICLASS_ADD,
57 effective_operand_width_in_bits: 64,
58 operands: [
59 Operand::Reg(Reg::XED_REG_RAX),
60 Operand::Mem(MemOperand {
61 base: None,
62 width_in_bits: 64,
63 seg: None,
64 sib: None,
65 displacement: Some(MemOperandDisplacement {
66 displacement: -5,
67 width_in_bits: 32,
68 }),
69 address_width_in_bits: 64,
70 }),
71 ]
72 .into_iter()
73 .collect(),
74 };
75 let result = xed_state.encode(&insn).unwrap();
76 let output_file_path = "/tmp/.xed_enc_test";
77 std::fs::write(output_file_path, result.as_slice()).unwrap();
78 let exit_code = Command::new("objdump")
79 .args("-Mintel -D -b binary -Mx86-64 -mi386:x86-64".split(' '))
80 .arg(output_file_path)
81 .spawn()
82 .unwrap()
83 .wait()
84 .unwrap();
85 assert!(exit_code.success());
86 let decoded = xed_state.decode(&result).unwrap();
87 assert_eq!(decoded.insn, insn);
88}
89
90fn decode_test() {
91 let stdin = std::io::stdin();
92 let mut input = String::new();
93 loop {
94 input.clear();
95 stdin.read_line(&mut input).unwrap();
96
97 dump_operands(&input);
98 }
99}
100
101fn dump_operands(assembly_line: &str) {
102 let bytes = nasm_assemble(&format!("bits 64\n{}", assembly_line));
103 let xed_state = XedState::new(
104 XedMachineMode::XED_MACHINE_MODE_LONG_64,
105 XedAddressWidth::XED_ADDRESS_WIDTH_64b,
106 );
107 let decoded_insn = xed_state.decode(&bytes).unwrap();
108 println!("{:#?}", decoded_insn);
109 let encoded = xed_state.encode(&decoded_insn.insn).unwrap();
110 assert_eq!(encoded.as_slice(), bytes.as_slice());
111}
112
113fn nasm_assemble(assembly_code: &str) -> Vec<u8> {
114 let asm_file_path = "/tmp/.xed_example_basic_nasm.asm";
115 let output_file_path = "/tmp/.xed_example_basic_nasm.bin";
116 std::fs::write(asm_file_path, assembly_code.as_bytes()).unwrap();
117 let exit_code = Command::new("nasm")
118 .arg("-f")
119 .arg("bin")
120 .arg(asm_file_path)
121 .arg("-o")
122 .arg(output_file_path)
123 .spawn()
124 .unwrap()
125 .wait()
126 .unwrap();
127 assert!(exit_code.success());
128 std::fs::read(output_file_path).unwrap()
129}