为什么裸 Rust 函数中有额外的 ASM 指令?
Why are there extra ASM instructions in a naked Rust function?
我正在用 Rust 包装一个低级 ABI,利用 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)
NOP 之前的 6 行(我用 *
标记)是我感到困惑的地方。 naked
指令不应该因为没有更好的术语而离开一个裸函数吗?
我试图让参数通过这个函数传递给 ABI,因为它遵循与 Rust 大致相同的调用约定,我只需要交换一个或两个寄存器,因此交换内联汇编。
有没有办法摆脱这 6 个前面的指令?我经常反对 ABI,而我以前反对它的方式造成了相当大的开销。我想确保包含任何重要值的寄存器不被覆盖。
旁注:是否需要 "volatile" 选项?我不确定,但还是添加了它。
在对此进行更多修改后(并弄清楚如何有效地反汇编我的发布版本),我发现额外的指令仅在调试构建期间添加(或至少在 -O0 时)。
在使用 -O2 编译代码时,我发现所有程序集都是内联的,但这很容易用 #[inline(never)]
指令修复。现在参数被正确传递,没有额外的指令破坏我的寄存器:)
现在我只需要将代码 运行 -O2 用于这些函数而不是调试构建的其余部分...
我正在用 Rust 包装一个低级 ABI,利用 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)
NOP 之前的 6 行(我用 *
标记)是我感到困惑的地方。 naked
指令不应该因为没有更好的术语而离开一个裸函数吗?
我试图让参数通过这个函数传递给 ABI,因为它遵循与 Rust 大致相同的调用约定,我只需要交换一个或两个寄存器,因此交换内联汇编。
有没有办法摆脱这 6 个前面的指令?我经常反对 ABI,而我以前反对它的方式造成了相当大的开销。我想确保包含任何重要值的寄存器不被覆盖。
旁注:是否需要 "volatile" 选项?我不确定,但还是添加了它。
在对此进行更多修改后(并弄清楚如何有效地反汇编我的发布版本),我发现额外的指令仅在调试构建期间添加(或至少在 -O0 时)。
在使用 -O2 编译代码时,我发现所有程序集都是内联的,但这很容易用 #[inline(never)]
指令修复。现在参数被正确传递,没有额外的指令破坏我的寄存器:)
现在我只需要将代码 运行 -O2 用于这些函数而不是调试构建的其余部分...