汇编的c ++似乎包含多余的指令 [英] Assembled c++ appears to contain superfluous instructions

查看:107
本文介绍了汇编的c ++似乎包含多余的指令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个仅包含以下内容的cpp文件:

I have a cpp file containing only the following:

void f(int* const x)
{
  (*x)*= 2;
}

我使用:

g++ -S -masm=intel -O3 -fno-exceptions -fno-asynchronous-unwind-tables f.cpp

这导致f.s包含:

    .section    __TEXT,__text,regular,pure_instructions
    .macosx_version_min 10, 12
    .intel_syntax noprefix
    .globl  __Z1fPi
    .p2align    4, 0x90
__Z1fPi:                                ## @_Z1fPi
## BB#0:
    push    rbp
    mov rbp, rsp
    shl dword ptr [rdi]
    pop rbp
    ret


.subsections_via_symbols

如果删除pushmovpop指令并进行汇编(在Mac上,我使用的是Clang),则生成的目标文件要小4个字节.链接和执行结果具有相同的行为和相同大小的可执行文件.

If I remove the push, mov, and pop instructions and assemble (on a mac, I'm using Clang), the resulting object file is 4 bytes smaller. Linking and executing results in the same behaviour and the same sized executable.

这表明这些指令是多余的-为什么编译器会麻烦将它们放入?这仅仅是链接器留下的优化吗?

This suggests that those instructions are superfluous - why does the compiler bother putting them in? Is this simply an optimization that is left to the linker?

推荐答案

CLANG/CLANG ++ 既是本机编译器,也是支持多个目标的交叉编译器.在OS/X上,默认情况下,目标通常是x86_64-apple-darwin(对于64位代码)和i386-apple-darwin(对于32位代码)的变体.您看到的代码类似于以下形式:

CLANG/CLANG++ is both a native compiler and a cross compiler that supports multiple targets. On OS/X the targets by default are usually a variant of x86_64-apple-darwin for 64-bit code and i386-apple-darwin for 32-bit code. The code you are seeing that resembles this form:

push    rbp
mov rbp, rsp

[snip]

pop rbp
ret

用于引入堆栈框架.默认情况下, CLANG ++

Is produced to introduce stack frames. By default CLANG++ implicitly enables stack frames for the Apple Darwin targets. This differs from the Linux targets like x86_64-linux-gnu and i386-linux-gnu. Stack frames can come in handy for some profiling and unwind libraries and can aid debugging on the OS/X platforms which is why I believe they opt to turn them on by default.

您可以使用选项-fomit-frame-pointer使用 CLANG ++ 显式省略帧指针.如果您使用构建命令

You can explicitly omit frame pointers with CLANG++ using the option -fomit-frame-pointer. If you use the build command

g++ -S -masm=intel -O3 -fno-exceptions -fno-asynchronous-unwind-tables \
    -fomit-frame-pointer f.cpp 

输出将类似于:

    shl     dword ptr [rdi]
    ret


查看具有不同目标的代码

如果对 CLANG ++ 使用不同的目标,则会发现行为有所不同.这是x86-64 Linux目标,我们没有明确省略帧指针:


A Look at Code with Different Targets

If you use different targets with CLANG++ you'd discover the behavior is different. This is an x86-64 Linux target where we don't explicitly omit the frame pointer:

clang++ -target x86_64-linux-gnu -S -masm=intel -O3 -fno-exceptions \
    -fno-asynchronous-unwind-tables f.cpp 

哪个生成:

    shl     dword ptr [rdi]
    ret

这是您最初的x86-64 Apple Darwin目标:

This is your original x86-64 Apple Darwin target:

clang++ -target x86_64-apple-darwin -S -masm=intel -O3 -fno-exceptions \
    -fno-asynchronous-unwind-tables f.cpp 

哪个生成:

    push    rbp
    mov     rbp, rsp
    shl     dword ptr [rdi]
    pop     rbp
    ret

然后是x86-64 Apple目标,其中省略了框架指针:

And then the x86-64 Apple target with frame pointers omitted:

clang++ -target x86_64-apple-darwin -S -masm=intel -O3 -fno-exceptions \
    -fno-asynchronous-unwind-tables -fomit-frame-pointer f.cpp 

哪个生成:

    shl     dword ptr [rdi]
    ret

您可以在

You can do a comparison of these targets on Godbolt. The first column of generated code is similar to the question - Apple target with implicit frame pointers. The second is Apple target without frame pointers and the third is an x86-64 Linux target.

这篇关于汇编的c ++似乎包含多余的指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆