Assembly 将指向Rust数组的指针传递到x86-64 Asm中--指针偏移1
当我将指向数组的指针从Rust传递到x86-64 Asm时,相关寄存器(rdi、rsi)似乎关闭了1,指向数组的元素1,而不是元素0。我可以减少寄存器以访问所需的位置,但我担心意外的行为。有没有我忽略的可能的解释 下面是一个简单程序中最相关的部分来说明这一点 main.rsAssembly 将指向Rust数组的指针传递到x86-64 Asm中--指针偏移1,assembly,rust,x86-64,ffi,Assembly,Rust,X86 64,Ffi,当我将指向数组的指针从Rust传递到x86-64 Asm时,相关寄存器(rdi、rsi)似乎关闭了1,指向数组的元素1,而不是元素0。我可以减少寄存器以访问所需的位置,但我担心意外的行为。有没有我忽略的可能的解释 下面是一个简单程序中最相关的部分来说明这一点 main.rs extern crate utilities; fn main() { let input: [u8;8] = [0;8]; let output: [u64; 1] = [0;1]; let i
extern crate utilities;
fn main() {
let input: [u8;8] = [0;8];
let output: [u64; 1] = [0;1];
let input_ptr = input.as_ptr();
let output_ptr = output.as_ptr();
utilities::u8tou64(input_ptr,output_ptr);
for i in 0..8 {print!("{:02X}", input[i]);} // byte 1 will be 0xEE
println!();
println!("{:016X}", output[0].swap_bytes()); /* byte 1 position of the u64
will be 0xFF */
println!("{:02X}", unsafe{*input_ptr.offset(1)}); /* modifying byte at address
passed into rdi in Asm function modifies input_ptr.offset(1) when expected
behavior was modification of input_ptr with no offset, e.g. input[0] */
}
u8到u64.S
.globl u8_to_u64
.intel_syntax noprefix
u8_to_u64:
mov rax, 0xff
mov byte [rsi], rax
mov rax, 0xee
mov byte [rdi], rax
xor rax, rax
retq
我用
gcc-cfoo.S
组装了你的asm,因为我认为我会从byte
而不是byte ptr
得到一个组装时间错误,并且与qword寄存器不匹配
在GAS语法中,byte
计算为整数常量1
,因此mov byte[rsi],rax
相当于mov 1[rsi],rax
。这在GAS语法中有效,相当于[1+rsi]
当您使用objdump-dwrC-Mintel
反汇编foo.o
时,您会看到
0000000000000000 <u8_to_u64>:
0: 48 c7 c0 ff 00 00 00 mov rax,0xff
7: 48 89 46 01 mov QWORD PTR [rsi+0x1],rax
b: 48 c7 c0 ee 00 00 00 mov rax,0xee
12: 48 89 47 01 mov QWORD PTR [rdi+0x1],rax
16: 48 31 c0 xor rax,rax
19: c3 ret
或者使用愚蠢的额外指令,首先对寄存器执行mov:
mov eax, 0xff
mov [rsi], al
mov eax, 0xee # mov al, 0xee is shorter but false dependency on the old RAX
mov [rdi], al
xor eax,eax
ret
为什么对1字节常量使用7字节
mov r64、扩展符号\u imm32
mov字节ptr[rsi],0xff
/mov字节ptr[rdi],0xee
/xor eax,eax
短得多,效率更高。作为奖励,它将实际组装rax,而不像mov byte[rdi],后者在字节和qword操作数大小之间不匹配。(al
是RAX的低位字节)。另外,GAS的.intel\u语法类似于MASM,因此需要字节ptr
,而不是NASM样式的字节
。除非Rust使用不同的汇编程序,看起来像GAS,否则这不是你真正的asm代码。@PeterCordes我发布的程序是从我试图做的事情简化而来的。我的实际程序使用Asm将RDI指向的136字节数组转换为RSI中的17元素u64数组。我发布的内容在我构建简化程序并直接从中复制时运行。我不再传入指针,而是传入一个借用的数组引用,至少在本例中,这导致了off-by-one错误消失。看起来像是外国金融机构的窃听者。我将在代码中尝试您的建议。这纠正了问题。我曾尝试将即时信息转换为[rdi]和[rsi],但编译器对此提出了投诉。使用“mov byte ptr”而不是“mov byte”允许直接立即赋值,并消除了我无意中引入到程序中的“off by one”错误。@WDS:没有操作数大小说明符,mov[mem],imm
是不明确的,并给出了一个错误,是的。这是你第一次暗示你的语法没有达到你想要的效果。mov byte[rsi]、rax
(带有qword寄存器)没有给出错误,即使您试图指定字节操作数大小,这一事实是您的代码(对GAS)不是您想要的意思的另一个线索。
mov eax, 0xff
mov [rsi], al
mov eax, 0xee # mov al, 0xee is shorter but false dependency on the old RAX
mov [rdi], al
xor eax,eax
ret