X86 为什么裸锈函数中有额外的ASM指令?

X86 为什么裸锈函数中有额外的ASM指令?,x86,rust,wrapper,abi,X86,Rust,Wrapper,Abi,我利用裸版功能特性,将一个低级别的ABI包装在Rust中。这是我的代码和相关的反汇编 #![feature(asm)] #![feature(naked_functions)] struct MyStruct { someVar: i64, // not important // ... } impl MyStruct { #[naked] extern "C" fn wrap(&self) { unsafe

我利用
裸版
功能特性,将一个低级别的ABI包装在Rust中。这是我的代码和相关的反汇编

#![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)
ABIWrap`ABIWrap::{{impl}}::wrap:
*0x10000310:movq%rdi,-0x10(%rbp)
*0x10000314:movq%rsi,-0x8(%rbp)
*0x10000318:movq-0x10(%rbp),%rax
*0x10000131c:movq-0x8(%rbp),%rcx
*0x10000320:movq%rax,-0x20(%rbp)
*0x100001244:movq%rcx,-0x18(%rbp)
0x10000328:否
0x10000329:retq
0x1000032A:nopw(%rax,%rax)
NOP前面的6行(我用
*
标记)是我感到困惑的地方。由于缺少更好的术语,
指令不应该离开裸函数吗

我试图允许参数通过这个函数传递给ABI,因为它遵循与Rust大致相同的调用约定,我只需要交换一个或两个寄存器,从而交换内联程序集

有没有办法摆脱前面的6条指令?我经常反对ABI,之前我反对ABI的方式造成了相当大的开销。我想确保包含任何重要值的寄存器不会被覆盖


旁注:是否需要“volatile”选项?我不确定,但还是添加了它。

在对它进行了更多的修补之后(并找到了如何有效地反汇编我的发布版本),我发现额外的指令只在调试版本期间添加(或者至少在-O0时添加)

当使用-O2编译代码时,我发现所有程序集都是内联的,但这很容易用
#[inline(never)]
指令解决。现在参数被正确地传递,没有额外的指令破坏我的寄存器:)


现在我只需要让代码只在这些函数上运行-O2,而不是调试构建的其余部分…

我不知道-但作为一个合理性检查:您反编译了一个发布构建是吗?不,我反编译调试构建是出于我自己的好奇心,这是什么ABI?在什么平台上?看起来很奇怪,它跳回某个阴影空间来获取一些数据,这是64位Windows ABI指定的。。不过有点难说@ChaseWalden也是出于好奇(我没有研究Rust中裸函数的内部工作原理),如果不将函数嵌入到结构的实现中,会发生什么情况。如果它只是一个独立的纯函数呢?我想知道那里的“前奏曲”是否是从某个地方拉来的
self
。@ChaseWalden:我想你已经找到了答案,裸函数接受参数没有意义,因为使用这些参数需要对它们的传递方式达成一致(ABI)这与指定不采用任何ABI的
属性不一致。可能值得为此打开一个问题:)@MatthieuM:可能。。。我仍在试图弄清楚将参数移动到堆栈上的目的是什么。我几乎开始认为SimonWhitehead在上面的评论线程中所暗示的,被调用方正在“阴影空间”中存储值,这很奇怪,因为我在Mac上