Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 易读的Golang汇编输出?_Assembly_Go - Fatal编程技术网

Assembly 易读的Golang汇编输出?

Assembly 易读的Golang汇编输出?,assembly,go,Assembly,Go,我感兴趣的是检查标准Go编译器的x86汇编输出,看看我的代码是否真的被转换为合理高效的汇编代码;希望通过分析和检查程序集输出,我可以得到一条线索,知道应该在哪里/如何重写Go代码以获得最佳性能。但是,当我使用-S标志检查代码时,Go会吐出一团乱麻!我想要两样东西: 有没有办法让Go编译器将程序集输出转储到一个文件中,而不仅仅是在终端上打印出来 还有,有没有办法让Go编译器将汇编代码分离成带标签的单独函数?我知道有些函数可能是内联的,因此不会出现在汇编代码中。我所看到的只是一个几乎不可能理解的同质

我感兴趣的是检查标准Go编译器的x86汇编输出,看看我的代码是否真的被转换为合理高效的汇编代码;希望通过分析和检查程序集输出,我可以得到一条线索,知道应该在哪里/如何重写Go代码以获得最佳性能。但是,当我使用-S标志检查代码时,Go会吐出一团乱麻!我想要两样东西:

  • 有没有办法让Go编译器将程序集输出转储到一个文件中,而不仅仅是在终端上打印出来

  • 还有,有没有办法让Go编译器将汇编代码分离成带标签的单独函数?我知道有些函数可能是内联的,因此不会出现在汇编代码中。我所看到的只是一个几乎不可能理解的同质组装体

  • 您可以将输出重定向到如下文件:

     go tool compile -S file.go > file.s
    
  • 您可以使用-N禁用优化:

     go tool compile -S -N file.go
    
  • 或者,您可以使用gccgo:

    gccgo -S -O0 -masm=intel test.go
    

    这将生成test.s。您可以使用-O0/1/2/3来查看不同的优化。

    我不建议使用
    -S
    的输出,因为Go链接器可以大量更改写入目标代码的内容。它确实让你对正在发生的事情有所了解

    go汇编程序的输出也是相当非标准的

    当我想这样做时,我总是使用它,这将给你一个很好的标准汇编输出

    用于x86/amd64的Eg

    objdump -d executable > disassembly
    
    对于ARM(使寄存器名称与Go使用的相同)


    在生成的可执行文件上运行
    go-tool-objdump


    要将输出限制为有趣的函数,请使用其
    -s
    选项。

    我对其他答案有疑问,因为生成的程序集提供了比我想要的多得多的信息,但仍然没有足够的细节。让我解释一下:它为go内部导入的所有库提供了程序集,但没有提供代码所在的行(我的代码都在文件的底部)

    以下是我从官方文件中发现的:

    $GOOS=linux-GOARCH=amd64-go-tool-compile-S x.go\or:go-build-gcflags-S x.go

    文件:

    产生:

    --- prog list "main" ---
    0000 (x.go:3) TEXT    main+0(SB),$8-0
    0001 (x.go:3) FUNCDATA $0,gcargs·0+0(SB)
    0002 (x.go:3) FUNCDATA $1,gclocals·0+0(SB)
    0003 (x.go:4) MOVQ    $3,(SP)
    0004 (x.go:4) PCDATA  $0,$8
    0005 (x.go:4) CALL    ,runtime.printint+0(SB)
    0006 (x.go:4) PCDATA  $0,$-1
    0007 (x.go:4) PCDATA  $0,$0
    0008 (x.go:4) CALL    ,runtime.printnl+0(SB)
    0009 (x.go:4) PCDATA  $0,$-1
    0010 (x.go:5) RET     ,
    
    所以我所做的基本上是:

    go工具编译-S hello.go>hello.S


    它得到了我想要的结果

    要将输出转储到文件:

    go tool objdump EXECUTABLE_FILE > ASSEMBLY_FILE
    
    如果您希望包含源Go代码(假设您有一个工作的golang设置,并且您自己构建了可执行文件):

    为了使输出更易于查看,我使用了生成以下内容的a(简而言之,它将更改控制流的指令着色-蓝色表示跳转,绿色表示调用/返回,红色表示陷阱,紫色表示填充-并在无条件控制流跳转后添加新行):

    如果您使用上面的包装器,则在管道连接到
    less
    时,您可能希望使用
    -R
    开关(或通过将其添加到环境中,例如在
    .bashrc
    中):
    导出less=“$less-R”
    ):


    或者,有一个可能是可读性最强的输出,允许您在编译器(gc、gccgo)和版本之间轻松切换。

    我发现Mac用户使用XCode开发工具的最简单方法是使用
    otool

    $ otool -tV myGoProgramBinary to disassemble
    

    1)使用
    或命令shell支持的任何东西将命令输出重定向到文件怎么样?此外,通过查看汇编代码进行分析的方法可能不是最有效的方法。你看过Go代码可用的分析工具了吗?(例如)我同意你的看法,装配输出需要一些改进。问题是Go编译器不生成实际的程序集。它生成的东西看起来很像程序集,但包含大量伪指令,这些伪指令将由链接器扩展。只有在链接完成后,才会产生实际的装配(并立即装配)。另外,请查看。Go的参考实现使用了这个assembler.PS:我正在寻找类似于GCC命令的东西:-fverbose asm
    Go build-gcflags-S test.Go>test.S
    也应该工作(根据)
    go tool comile-S file.go>file.S
    因为
    go1.5
    @IvanBlack您的评论应该得到顶级响应。您可能会发现Godbolt编译器资源管理器对于颜色高亮显示非常有用,可以将源代码行映射到asm。具有gc1.10.1和gccgo 7.2的简单函数输出。这是一个非常好的工具
    go tool objdump EXECUTABLE_FILE > ASSEMBLY_FILE
    
    go tool objdump -S EXECUTABLE_FILE
    
    go-objdump EXECUTABLE_FILE | less -R
    
    $ otool -tV myGoProgramBinary to disassemble