Я оборачиваю низкоуровневый ABI в Rust, используя функцию naked
. Вот мой код и соответствующая разборка
#![feature(asm)]
#![feature(naked_functions)]
struct MyStruct {
someVar: i64, // not important
// ...
}
impl MyStruct {
#[naked]
extern "C" fn wrap(&self) {
unsafe {
asm!("NOP" :::: "volatile");
// not sure if the volatile option is needed, but I
// figured it wouldn't hurt
}
}
}
Разобрано с LLDB:
ABIWrap`ABIWrap::{{impl}}::wrap:
* 0x100001310 <+0>: movq %rdi, -0x10(%rbp)
* 0x100001314 <+4>: movq %rsi, -0x8(%rbp)
* 0x100001318 <+8>: movq -0x10(%rbp), %rax
* 0x10000131c <+12>: movq -0x8(%rbp), %rcx
* 0x100001320 <+16>: movq %rax, -0x20(%rbp)
* 0x100001324 <+20>: movq %rcx, -0x18(%rbp)
0x100001328 <+24>: nop
0x100001329 <+25>: retq
0x10000132a <+26>: nopw (%rax,%rax)
Меня смущают 6 строк, предшествующих NOP (я пометил *
). Не должна ли директива naked
оставить, за неимением лучшего термина, голую функцию?
Я пытаюсь позволить аргументам просто проходить через эту функцию в ABI, поскольку она следует примерно тому же соглашению о вызовах, что и Rust, мне просто нужно поменять местами один или два регистра, следовательно, встроенная сборка.
Есть ли способ избавиться от этих 6 предыдущих инструкций? Я часто коллирую против ABI, и предыдущий способ, которым я коллировал против него, вызывал приличное количество накладных расходов. Я хочу убедиться, что регистры, содержащие какие-либо важные значения, не перезаписываются.
Боковое примечание: нужна ли «изменчивая» опция? Я не был уверен, но все равно добавил.
self
откуда-то. - person Simon Whitehead   schedule 15.02.2017naked
, который указывает не принимать никаких АБИ. - person Matthieu M.   schedule 15.02.2017extern "C"
делает в примере. Это влияет только на код, сгенерированный на месте вызова. Разработчик функции должен следовать объявленному ABI внутри функции. Важно отметить, что если вы не укажете ABI для голой функции, вы даже не сможете вызвать ее изнутри Rust, поскольку Rust не знает, что делать. на месте вызова. - person Joshua Little   schedule 08.05.2021