【问题标题】:Examine generated assembly code?检查生成的汇编代码?
【发布时间】:2015-07-19 03:21:35
【问题描述】:

我有以下测试程序来检查 GCC 生成的代码。 rotlFixed 在标头misc.h 中提供,并将其声明为内联。它还使用模板特化来调用 GCC 内联汇编:

int main(int argc, char* argv[])
{
  byte r1 = rotlFixed(1, 1);
  byte r2 = rotlFixed(1, 255);

  word16 r3 = rotlFixed(1, 1);
  word16 r4 = rotlFixed(1, 255);
  word16 r5 = rotlFixed(1, 256);
  word16 r6 = rotlFixed(1, 65535);

  cout << r1 << "," << r2 << "," << r3 << "," << r4 << ",";
  cout << r5 << "," << r6 << endl;

  return 0;
}

根据How to get GCC to generate assembly code,我编译源文件为:

g++ -O1 -S -c cryptopp-test.cxx

但是当我猫时,我没有看到对旋转的调用:

$ cat cryptopp-test.s
    .file   "cryptopp-test.cxx"
    .section    .rodata.str1.1,"aMS",@progbits,1
.LC0:
    .string "misc.h"
.LC1:
    .string "y < THIS_SIZE"
    .text
    .globl  main
    .type   main, @function
main:
.LFB2196:
    .cfi_startproc
    subq    $8, %rsp
    .cfi_def_cfa_offset 16
    movl    $_ZZN8CryptoPP9rotlFixedIiEET_S1_jE19__PRETTY_FUNCTION__, %ecx
    movl    $692, %edx
    movl    $.LC0, %esi
    movl    $.LC1, %edi
    call    __assert_fail
    .cfi_endproc
.LFE2196:
    .size   main, .-main
    .type   _GLOBAL__sub_I_main, @function
_GLOBAL__sub_I_main:
.LFB2311:
    .cfi_startproc
    subq    $8, %rsp
    .cfi_def_cfa_offset 16
    movl    $_ZStL8__ioinit, %edi
    call    _ZNSt8ios_base4InitC1Ev
    movl    $__dso_handle, %edx
    movl    $_ZStL8__ioinit, %esi
    movl    $_ZNSt8ios_base4InitD1Ev, %edi
    call    __cxa_atexit
    addq    $8, %rsp
    .cfi_def_cfa_offset 8
    ret
    .cfi_endproc
.LFE2311:
    .size   _GLOBAL__sub_I_main, .-_GLOBAL__sub_I_main
    .section    .init_array,"aw"
    .align 8
    .quad   _GLOBAL__sub_I_main
    .section    .rodata
    .align 32
    .type   _ZZN8CryptoPP9rotlFixedIiEET_S1_jE19__PRETTY_FUNCTION__, @object
    .size   _ZZN8CryptoPP9rotlFixedIiEET_S1_jE19__PRETTY_FUNCTION__, 54
_ZZN8CryptoPP9rotlFixedIiEET_S1_jE19__PRETTY_FUNCTION__:
    .string "T CryptoPP::rotlFixed(T, unsigned int) [with T = int]"
    .local  _ZStL8__ioinit
    .comm   _ZStL8__ioinit,1,1
    .hidden __dso_handle
    .ident  "GCC: (GNU) 5.1.1 20150618 (Red Hat 5.1.1-4)"
    .section    .note.GNU-stack,"",@progbits

我显然做错了什么,因为我要检查的调用丢失了。

如何生成列表?或者,如果我正在生成它,如何显示所有相关部分?

提前致谢。


如果重要的话,系统是 Fedora 22 x86_64 和 GCC 5.1.1:

$ uname -a
Linux localhost.localdomain 4.0.4-301.fc22.x86_64 #1 SMP Thu May 21 13:10:33 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
$ gcc --version
gcc (GCC) 5.1.1 20150618 (Red Hat 5.1.1-4)
...

相关,这是导致我想查看生成的代码How to force const propagation through an inline function?的潜在问题@

【问题讨论】:

  • 尝试编译可执行文件并将其转储为objdump -d

标签: c++ assembly g++


【解决方案1】:

看起来 g++ 已将您的 main() 优化为 "y &lt; THIS_SIZE" 的断言失败

如果您想了解更多信息,您应该向我们展示rotlFixed() 的实现。

【讨论】:

  • 哦,这很有趣。那我加个代码吧基本模板代码使用了断言。特化使用不带断言的内联汇编,并由__GNU_C__ 保护。
  • 据我所知,__GNU_C__ 不会被定义——我想你想使用__GNUC__
  • “据我所知,__GNU_C__ 不会被定义......” - 我的错......我只是区分了来源 - 它的 @987654328 @。是的,我是马里兰州的毕业生和粉丝。早在 1980 年代中期,我就曾尝试为足球穿红衫。伙计,那些家伙打得太厉害了……
【解决方案2】:

标志-O1 正在优化您的函数调用rotlFixed(...)。使用-O0 进行操作。

另外,如果您使用的是-S,则不需要-c

【讨论】:

  • 我正在验证的部分内容是选择使用内联汇编程序的模板专业化。在 -O0 处,选择专用函数,因为编译器不会将 static const 值传播到具有 immediate 约束的程序集中。
【解决方案3】:

如果你想看到编译器优化后的机器码,把它放到一个没有main()的文件中并编译它。然后编译器会认为它正在构建一个要从其他地方调用的函数。

通过在 main() 中拥有所有内容的方式,编译器会看到您从不使用结果并丢弃未使用的函数。

【讨论】:

    【解决方案4】:

    您确实想将-fverbose-asm 传递给g++gcc-S-O

    您可能还想获得代码的预处理形式(带有gcc -C -E)。

    -fverbose-asm 要求 GCC 编译器在生成的汇编代码中发出 cmets。

    你显然至少需要一些优化-O1;否则生成的汇编程序将包含大量无用代码(使其可读性降低)。

    您可能想要传递 -fdump-tree-all(或其他 -fdump 标志)来获取数百个描述 GCC 内部各种内部表示的转储文件。

    您可以使用MELT 自定义 GCC。

    【讨论】:

      猜你喜欢
      • 2012-03-04
      • 2014-02-03
      • 2014-10-29
      • 2021-07-18
      • 2016-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-29
      相关资源
      最近更新 更多