assembly - 为什么要为默认字符串多一条汇编程序指令

标签 assembly rust compilation

我发现了有趣的行为。

String 上调用 default 比在空 &str 上调用 to_string 多一条指令>。为什么?

pub fn string_default() -> String {
    Default::default()
}

pub fn string_to_string() -> String {
    "".to_string()
}
example::string_default:
        mov     rax, rdi
        mov     rcx, qword ptr [rip + .L__unnamed_1]
        xorps   xmm0, xmm0
        movups  xmmword ptr [rdi + 8], xmm0
        mov     qword ptr [rdi], rcx
        ret

example::string_to_string:
        mov     rax, rdi
        xorps   xmm0, xmm0
        movups  xmmword ptr [rdi + 8], xmm0
        mov     qword ptr [rdi], 1
        ret

.L__unnamed_1:
        .asciz  "\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000"

UPD:构建配置文件“发布”

UPD (2):在 rust 1.52.0 之前,两个函数的汇编代码是相同的(4 条指令)。在 1.51.0 和更早版本中,mov qword 出现在 xorps 之前。

最佳答案

&str.to_string() 通过调用 &[u8]::to_owned( ) 依次调用 &[u8]::to_vec() 并最终调用 RawVec::with_capacity_in

String::new()String::default() 通过 Vec::new() 创建 Vec 内部包装 RawVec::SELF,一个常量值。

您可以将示例简化为

fn slice_to_vec() -> Vec<u8> {
    let b: &[u8] = &[];
    let v = b.to_vec();
}
// example::slice_to_vec:
//        mov     rax, rdi
//        mov     qword ptr [rdi], 1
//        xorps   xmm0, xmm0
//        movups  xmmword ptr [rdi + 8], xmm0
//        ret

对比

pub fn vec() -> Vec<u8> {
    Vec::new()
}
// example::vec:
//        mov     rax, rdi
//        mov     rcx, qword ptr [rip + .L__unnamed_1]
//        mov     qword ptr [rdi], rcx
//        xorps   xmm0, xmm0
//        movups  xmmword ptr [rdi + 8], xmm0
//        ret
//
// .L__unnamed_1:
//         .asciz  "\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000"

我无法解释为什么会发生这种情况,但是 1.52 发生在 upgrade the LLVM version 上由 Rust 使用,所以也许这改变了生成的程序集。

关于assembly - 为什么要为默认字符串多一条汇编程序指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70071588/

相关文章:

assembly - x86 汇编中寄存器上使用的入栈/出栈指令的功能是什么?

assembly - x86 汇编添加不同大小的操作数

assembly - AAA 在 8086 指令集中如何工作?

callback - 如何 : Idiomatic Rust for callbacks with gtk (rust-gnome)

compilation - 为什么 "8g foo.go -o foo.8"在 go 语言命令行中对我不起作用?

python - 与 astype(int) 相比,numpy around/rint 慢

rust - 如何在rust中返回带有引用的结构?

graphics - 如何更新 gfx-rs 中的索引缓冲区?

C 程序在编译和链接后生成包含 edata 部分的 EXE 文件?

c# - Mono AOT 编译 - 如何获取 .so 文件?