use std::{
io,
io::Write,
mem,
ops::{Index, IndexMut},
slice,
};
use dynasmrt::{dynasm, DynasmApi, DynasmLabelApi};
#[test]
fn test_00() {
let mut ops = dynasmrt::x64::Assembler::new().unwrap();
let instrs = ops.offset();
let mut x: i64 = 23;
dynasm!(ops
; .arch x64
; mov rax, QWORD x
; ret
);
x = 24;
let buf = ops.finalize().unwrap();
let hello_fn: extern "sysv64" fn() -> u64 = unsafe { mem::transmute(buf.ptr(instrs)) };
assert_eq!(hello_fn(), 23);}
So the answer here is 23, showing that it compiled in the value of x. I am trying to figure out if there is a way to have the mov load from the address of x (rather than the literal value of x at the time of invoking the macro).
#[test]
fn test_00() {
let mut ops = dynasmrt::x64::Assembler::new().unwrap();
let instrs = ops.offset();
let mut x: i64 = 23;
/*
; mov rax, QWORD (&mut x as *mut i64 as u64 as i64)
; mov rax, [rax]
*/
dynasm!(ops
; .arch x64
; mov rax, QWORD [&mut x as *mut i64 as u64 as i64]
; ret
);
x = 24;
let buf = ops.finalize().unwrap();
let hello_fn: extern "sysv64" fn() -> u64 = unsafe { mem::transmute(buf.ptr(instrs)) };
assert_eq!(hello_fn(), 24);}
gives the compiler error of:
|
29 | ; mov rax, QWORD [&mut x as *mut i64 as u64 as i64]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `i64`
|
help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
|
29 | ; mov rax, QWORD [(&mut x as *mut i64 as u64 as i64).try_into().unwrap()]
The main issue I have with this solution is -- and I'm not an x86_64 asm expert -- is this the right way to do this? It seems if we are loading directly from an address, the CPU can start pre-fetching, but if we load a value into a register than load from the reg, it seems the CPU can not pre-fetch while a mile away.
I think the case I care about (load/store to arbitrary reg from an absolute address) is not a very common case anyway.
Thanks for the rip example above. Position-independent-code makes so much more sense. (Pure speculation) I would not be surprised if modern CPUs had silicon dedicated to find blocks of instrs where rip is not written to, and thus can pre-fetch based on offsets to rip.