assembly 在编译器资源管理器中为Rust和C生成的二进制反汇编之间的差异

oalqel3c  于 2022-11-13  发布在  其他
关注(0)|答案(2)|浏览(175)

我在编译器资源管理器中观察了Rust和C中为相同程序生成的汇编程序,在“二进制”模式下查看整个链接的可执行文件,而不仅仅是编译器为特定函数生成的汇编程序。

Rust program(在神弩箭上)
pub fn square(num: i32) -> i32 {
    num * num
}

fn main () {
    let n = 4;
    let _x = square(n);
}
C program(在神箭上)
int square(int num) {
    return num * num;
}

int main() {
    int n = 4;
    int x = square(n);
}

但是这两个程序生成的反汇编代码有很大的不同。我可以部分理解C程序生成的汇编代码,这对我来说要短得多,也更容易理解。但是我不能理解Rust程序生成的汇编代码。
所以我的问题是为什么这些汇编程序的长度有这么大的差异?我是不是用错了编译器资源管理器?

mum43rcc

mum43rcc1#

Rust一个似乎显示了一堆来自Rust标准库的代码。
这只是编译器资源管理器的一个问题。它知道如何隐藏C标准库,但不知道如何隐藏Rust库。你可以看到,如果你点击“过滤器”,Rust程序中隐藏库函数的选项是灰色的。
另一个选择是取消选中“Compile to binary”。这样,编译器只会编译你的代码,并在链接到标准库之前反汇编它。代码可能会略有不同,因为它没有被链接。(感谢Stargateur的这个建议)

waxmsbnn

waxmsbnn2#

在这个清单中有很多内部的东西。
如果您启用优化(例如大小为-C opt-level=s)并在列表中搜索感兴趣的部分(即主方法),您将看到它几乎被优化掉了,因为您没有使用计算值
如果使用这些值,您将看到更有趣的内容:

pub fn square(num: i32) -> i32 {
    num * num
}

fn main () {
    let n = 4;
    let _x = square(n);
    println!("{} {}", n, _x);
}

这里没有调用方法square,因为编译器可以计算结果编译时间。RUST代码总是比相同的C代码效率更低,更复杂

example::main:
 sub rsp,0x58
 mov rax,rsp
 mov DWORD PTR [rax],0x4
 lea rcx,[rsp+0x4]
 mov DWORD PTR [rcx],0x10
 lea rdx,[rsp+0x8]
 mov QWORD PTR [rdx],rax
 lea rax,[rip+0x33e70] # 3b8f0 <core::fmt::num::imp::<impl core::fmt::Display for i32>::fmt>
 mov QWORD PTR [rdx+0x8],rax
 mov QWORD PTR [rdx+0x10],rcx
 mov QWORD PTR [rdx+0x18],rax
 lea rax,[rip+0x44755] # 4c1e8 <anon.7152d18045a77e825c19a8010d1656c2.0.llvm.7612792893684456700+0x30>
 lea rdi,[rsp+0x28]
 mov QWORD PTR [rdi],rax
 mov QWORD PTR [rdi+0x8],0x3
 mov QWORD PTR [rdi+0x10],0x0
 mov QWORD PTR [rdi+0x20],rdx
 mov QWORD PTR [rdi+0x28],0x2
 call QWORD PTR [rip+0x472bb] # 4ed78 <_GLOBAL_OFFSET_TABLE_+0x460>
 add rsp,0x58
 ret

https://godbolt.org/z/z6sheTvjd

相关问题