为什么Rust会发出280行汇编代码来打印“ Hello,world”?

时间:2019-12-06 05:28:39

标签: macos assembly rust

Rust中的一个简单的三行Hello,World程序发出280行汇编文件以打印两个单词。同时,a pure assembly version of this program仅需要约15行。为什么Rust版本这么长?

这是在Mac OS上。

hello.rs

fn main() {
    println!("hello world")
}

hello.s (由rustc --emit=asm hello.rs生成):

    .section    __TEXT,__text,regular,pure_instructions
    .macosx_version_min 10, 7
    .private_extern __ZN3std2rt10lang_start17hb4e01c1e588bf694E
    .globl  __ZN3std2rt10lang_start17hb4e01c1e588bf694E
    .p2align    4, 0x90
__ZN3std2rt10lang_start17hb4e01c1e588bf694E:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register %rbp
    subq    $32, %rsp
    leaq    l___unnamed_1(%rip), %rax
    movq    %rdi, -8(%rbp)
    leaq    -8(%rbp), %rcx
    movq    %rcx, %rdi
    movq    %rsi, -16(%rbp)
    movq    %rax, %rsi
    movq    -16(%rbp), %rax
    movq    %rdx, -24(%rbp)
    movq    %rax, %rdx
    movq    -24(%rbp), %rcx
    callq   __ZN3std2rt19lang_start_internal17hcf96e32a124891dcE
    movq    %rax, -32(%rbp)
    movq    -32(%rbp), %rax
    addq    $32, %rsp
    popq    %rbp
    retq
    .cfi_endproc

    .p2align    4, 0x90
__ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17h275cd8632ff3ab7dE:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register %rbp
    subq    $16, %rsp
    callq   *(%rdi)
    callq   __ZN54_$LT$$LP$$RP$$u20$as$u20$std..process..Termination$GT$6report17hf5e270b394827df3E
    movl    %eax, -4(%rbp)
    movl    -4(%rbp), %eax
    addq    $16, %rsp
    popq    %rbp
    retq
    .cfi_endproc

    .p2align    4, 0x90
__ZN3std3sys4unix7process14process_common8ExitCode6as_i3217h7e671b2505e0c229E:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register %rbp
    movzbl  (%rdi), %eax
    popq    %rbp
    retq
    .cfi_endproc

    .p2align    4, 0x90
__ZN4core3fmt9Arguments6new_v117h39ef65f250941772E:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register %rbp
    subq    $16, %rsp
    movq    %rdi, %rax
    movq    $0, -16(%rbp)
    movq    %rsi, (%rdi)
    movq    %rdx, 8(%rdi)
    movq    -16(%rbp), %rdx
    movq    -8(%rbp), %rsi
    movq    %rdx, 16(%rdi)
    movq    %rsi, 24(%rdi)
    movq    %rcx, 32(%rdi)
    movq    %r8, 40(%rdi)
    addq    $16, %rsp
    popq    %rbp
    retq
    .cfi_endproc

    .p2align    4, 0x90
__ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h61f8ee8d3fead017E:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register %rbp
    subq    $16, %rsp
    movq    (%rdi), %rdi
    callq   __ZN4core3ops8function6FnOnce9call_once17h47f538be1b10688dE
    movl    %eax, -12(%rbp)
    movl    -12(%rbp), %eax
    addq    $16, %rsp
    popq    %rbp
    retq
    .cfi_endproc

    .p2align    4, 0x90
__ZN4core3ops8function6FnOnce9call_once17h47f538be1b10688dE:
Lfunc_begin0:
    .cfi_startproc
    .cfi_personality 155, _rust_eh_personality
    .cfi_lsda 16, Lexception0
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register %rbp
    subq    $48, %rsp
    movq    %rdi, -32(%rbp)
Ltmp0:
    leaq    -32(%rbp), %rdi
    callq   __ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17h275cd8632ff3ab7dE
Ltmp1:
    movl    %eax, -36(%rbp)
    jmp LBB5_1
LBB5_1:
    jmp LBB5_2
LBB5_2:
    movl    -36(%rbp), %eax
    addq    $48, %rsp
    popq    %rbp
    retq
LBB5_3:
    jmp LBB5_4
LBB5_4:
    movq    -16(%rbp), %rdi
    callq   __Unwind_Resume
    ud2
LBB5_5:
Ltmp2:
    movq    %rax, -16(%rbp)
    movl    %edx, -8(%rbp)
    jmp LBB5_3
Lfunc_end0:
    .cfi_endproc
    .section    __TEXT,__gcc_except_tab
    .p2align    2
GCC_except_table5:
Lexception0:
    .byte   255
    .byte   255
    .byte   1
    .uleb128 Lcst_end0-Lcst_begin0
Lcst_begin0:
    .uleb128 Ltmp0-Lfunc_begin0
    .uleb128 Ltmp1-Ltmp0
    .uleb128 Ltmp2-Lfunc_begin0
    .byte   0
    .uleb128 Ltmp1-Lfunc_begin0
    .uleb128 Lfunc_end0-Ltmp1
    .byte   0
    .byte   0
Lcst_end0:
    .p2align    2

    .section    __TEXT,__text,regular,pure_instructions
    .p2align    4, 0x90
__ZN4core3ptr18real_drop_in_place17h0ab16307507408dbE:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register %rbp
    popq    %rbp
    retq
    .cfi_endproc

    .p2align    4, 0x90
__ZN54_$LT$$LP$$RP$$u20$as$u20$std..process..Termination$GT$6report17hf5e270b394827df3E:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register %rbp
    subq    $16, %rsp
    xorl    %edi, %edi
    callq   __ZN68_$LT$std..process..ExitCode$u20$as$u20$std..process..Termination$GT$6report17h03f2ed18f1614f97E
    movl    %eax, -4(%rbp)
    movl    -4(%rbp), %eax
    addq    $16, %rsp
    popq    %rbp
    retq
    .cfi_endproc

    .p2align    4, 0x90
__ZN68_$LT$std..process..ExitCode$u20$as$u20$std..process..Termination$GT$6report17h03f2ed18f1614f97E:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register %rbp
    subq    $16, %rsp
    movb    %dil, -1(%rbp)
    leaq    -1(%rbp), %rdi
    callq   __ZN3std3sys4unix7process14process_common8ExitCode6as_i3217h7e671b2505e0c229E
    movl    %eax, -8(%rbp)
    movl    -8(%rbp), %eax
    addq    $16, %rsp
    popq    %rbp
    retq
    .cfi_endproc

    .p2align    4, 0x90
__ZN5hello4main17hef70db39c48df377E:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register %rbp
    subq    $48, %rsp
    leaq    l___unnamed_2(%rip), %rax
    xorl    %ecx, %ecx
    movl    %ecx, %r8d
    leaq    -48(%rbp), %rdi
    movq    %rax, %rsi
    movl    $1, %edx
    movl    $8, %ecx
    callq   __ZN4core3fmt9Arguments6new_v117h39ef65f250941772E
    leaq    -48(%rbp), %rdi
    callq   __ZN3std2io5stdio6_print17hd8f597a6d310dad5E
    addq    $48, %rsp
    popq    %rbp
    retq
    .cfi_endproc

    .globl  _main
    .p2align    4, 0x90
_main:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register %rbp
    subq    $16, %rsp
    movslq  %edi, %rax
    leaq    __ZN5hello4main17hef70db39c48df377E(%rip), %rdi
    movq    %rsi, -8(%rbp)
    movq    %rax, %rsi
    movq    -8(%rbp), %rdx
    callq   __ZN3std2rt10lang_start17hb4e01c1e588bf694E
    addq    $16, %rsp
    popq    %rbp
    retq
    .cfi_endproc

    .section    __DATA,__const
    .p2align    3
l___unnamed_1:
    .quad   __ZN4core3ptr18real_drop_in_place17h0ab16307507408dbE
    .quad   8
    .quad   8
    .quad   __ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17h275cd8632ff3ab7dE
    .quad   __ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17h275cd8632ff3ab7dE
    .quad   __ZN4core3ops8function6FnOnce40call_once$u7b$$u7b$vtable.shim$u7d$$u7d$17h61f8ee8d3fead017E

    .section    __TEXT,__const
l___unnamed_3:
    .ascii  "hello world\n"

    .section    __DATA,__const
    .p2align    3
l___unnamed_2:
    .quad   l___unnamed_3
    .asciz  "\f\000\000\000\000\000\000"


.subsections_via_symbols

1 个答案:

答案 0 :(得分:6)

在编译代码时,编译器可能会在不同方面做出很多潜在的取舍,例如:

  • 代码大小
  • 运行时性能
  • 已用内存
  • 易于调试
  • 编译时间

大多数编译器将为您提供一些方法,以指定您希望如何权衡这些折衷。 rustc也不例外-您可以使用opt-level代码生成选项来指定所需的内容:

  

opt-level此标志可让您控制优化级别。

     

0:没有优化,也请打开cfg(debug_assertions)。

     

1:基本优化

     

2:一些优化

     

3:所有优化

     

s:优化二进制大小

     

z:优化二进制大小,但也关闭循环矢量化。

例如,您可以指定-C opt-level=3以获得最佳性能(在大多数情况下,这也会增加编译时间)。

rustc选项-O-C opt-level=3的简写。

根据@jbm提供的godbolt link,使用-O,您可以获得19行汇编。

还请注意,大多数人不会直接致电rustc,而是将货物用作构建控制工具。 cargo build子命令允许您指定一个构建配置文件,该配置文件确定诸如所应用的优化级别之类的内容。 --release标志调用适合发布版本的优化配置文件。