Skip to main content

basic/
basic.rs

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    // encode_test()
12    // raw_encode_test()
13}
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}