Передача указателя в массив Rust в x86-64 Asm - указатель отключен одним - PullRequest
0 голосов
/ 16 декабря 2018

Когда я передаю указатели на массивы из Rust в x86-64 Asm, соответствующие регистры (rdi, rsi) отключаются на единицу, указывая на элемент 1 массива вместо элемента 0. Я могу уменьшить регистры додоступ к нужному месту, но я обеспокоен неожиданным поведением.Есть ли возможные объяснения тому, что я пропускаю?

Ниже приведены наиболее важные части простой программы, иллюстрирующие это.

main.rs

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_to_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

1 Ответ

0 голосов
/ 16 декабря 2018

Я собрал ваш asm с gcc -c foo.S, так как думал, что получу ошибку времени сборки от byte вместо byte ptr и несоответствие с регистром слов.

В GASсинтаксис byte оценивается как целочисленная константа 1, поэтому mov byte [rsi], rax эквивалентно mov 1[rsi], rax.Это допустимо в синтаксисе GAS и эквивалентно [1+rsi]

Когда вы разбираете foo.o с objdump -dwrC -Mintel, вы видите

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    

Обратите внимание на [rsi+1] и [rdi+1] режимы адресации.

Синтаксис GAS для того, что вы пытаетесь сделать:

mov   byte ptr [rsi], 0xff
mov   byte ptr [rdi], 0xee
xor   eax,eax
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
...