我想知道如何在我的C源文件上使用GCC来转储机器代码的助记符版本,这样我就可以看到我的代码被编译成什么。你可以用Java做到这一点,但我还没有找到一种方法与GCC。

我试图在汇编中重写一个C方法,看看GCC是如何做的,这将是一个很大的帮助。


当前回答

对于risc-v反汇编,这些标志很好:

riscv64-unknown-elf-objdump -d -S -l --visualize-jumps --disassembler-color=color --inlines

-d:拆解,最基本的标志

-S:混合源。注意:编译时必须使用-g标志

-l:行号

——可视化跳跃:花哨的箭头,不是很有用,但为什么不呢?有时候get太乱了,实际上会让阅读源代码变得更加困难。来自Peter Cordes的评论:——visualize- leaps =coloris一个选项,为不同的箭头使用不同的颜色

——disassembly -color=color:给反汇编一些颜色

——inlines:打印出内行

也许有用:

-M numeric:使用数字reg名称而不是abi名称,如果你在做cpu开发并且不记得abi名称,这很有用

-M no-aliases:不要使用伪指令,如li和call

例子: main.o:

#include <stdio.h>
#include <stdint.h>

static inline void example_inline(const char* str) {
    for (int i = 0; str[i] != 0; i++)
        putchar(str[i]);
}

int main() {
    printf("Hello world");
    example_inline("Hello! I am inlined");

    return 0;
}

如果您想混合源代码,我建议使用-O0。如果使用-O2,混合源会变得非常混乱。

命令:

riscv64-unknown-elf-gcc main.c -c -O0 -g
riscv64-unknown-elf-objdump -d -S -l --disassembler-color=color --inlines main.o

Dissasembly:

main.o:     file format elf64-littleriscv


Disassembly of section .text:

0000000000000000 <example_inline>:
example_inline():
/Users/cyao/test/main.c:4
#include <stdio.h>
#include <stdint.h>

static inline void example_inline(const char* str) {
   0:   7179                    addi    sp,sp,-48
   2:   f406                    sd  ra,40(sp)
   4:   f022                    sd  s0,32(sp)
   6:   1800                    addi    s0,sp,48
   8:   fca43c23                sd  a0,-40(s0)

000000000000000c <.LBB2>:
/Users/cyao/test/main.c:5
    for (int i = 0; str[i] != 0; i++)
   c:   fe042623                sw  zero,-20(s0)
  10:   a01d                    j   36 <.L2>

0000000000000012 <.L3>:
/Users/cyao/test/main.c:6 (discriminator 3)
        putchar(str[i]);
  12:   fec42783                lw  a5,-20(s0)
  16:   fd843703                ld  a4,-40(s0)
  1a:   97ba                    add a5,a5,a4
  1c:   0007c783                lbu a5,0(a5)
  20:   2781                    sext.w  a5,a5
  22:   853e                    mv  a0,a5
  24:   00000097                auipc   ra,0x0
  28:   000080e7                jalr    ra # 24 <.L3+0x12>
/Users/cyao/test/main.c:5 (discriminator 3)
    for (int i = 0; str[i] != 0; i++)
  2c:   fec42783                lw  a5,-20(s0)
  30:   2785                    addiw   a5,a5,1
  32:   fef42623                sw  a5,-20(s0)

0000000000000036 <.L2>:
/Users/cyao/test/main.c:5 (discriminator 1)
  36:   fec42783                lw  a5,-20(s0)
  3a:   fd843703                ld  a4,-40(s0)
  3e:   97ba                    add a5,a5,a4
  40:   0007c783                lbu a5,0(a5)
  44:   f7f9                    bnez    a5,12 <.L3>

0000000000000046 <.LBE2>:
/Users/cyao/test/main.c:7
}
  46:   0001                    nop
  48:   0001                    nop
  4a:   70a2                    ld  ra,40(sp)
  4c:   7402                    ld  s0,32(sp)
  4e:   6145                    addi    sp,sp,48
  50:   8082                    ret

0000000000000052 <main>:
main():
/Users/cyao/test/main.c:9

int main() {
  52:   1141                    addi    sp,sp,-16
  54:   e406                    sd  ra,8(sp)
  56:   e022                    sd  s0,0(sp)
  58:   0800                    addi    s0,sp,16
/Users/cyao/test/main.c:10
    printf("Hello world");
  5a:   000007b7                lui a5,0x0
  5e:   00078513                mv  a0,a5
  62:   00000097                auipc   ra,0x0
  66:   000080e7                jalr    ra # 62 <main+0x10>
/Users/cyao/test/main.c:11
    example_inline("Hello! I am inlined");
  6a:   000007b7                lui a5,0x0
  6e:   00078513                mv  a0,a5
  72:   00000097                auipc   ra,0x0
  76:   000080e7                jalr    ra # 72 <main+0x20>
/Users/cyao/test/main.c:13

    return 0;
  7a:   4781                    li  a5,0
/Users/cyao/test/main.c:14
}
  7c:   853e                    mv  a0,a5
  7e:   60a2                    ld  ra,8(sp)
  80:   6402                    ld  s0,0(sp)
  82:   0141                    addi    sp,sp,16
  84:   8082                    ret

PS.在拆卸代码中有颜色

其他回答

你试过gcc -S -fverbose-asm -O source.c然后查看生成的源代码吗?S汇编文件?

生成的汇编程序代码进入源代码。S(你可以用-o assembly -filename重写它);-fverbose-asm选项要求编译器发出一些汇编注释“解释”生成的汇编代码。-O选项要求编译器优化一点(它可以用-O2或-O3优化更多)。

如果您想了解gcc在做什么,请尝试传递-fdump-tree-但要小心:您将得到数百个转储文件。

顺便说一句,GCC是可扩展的,可以通过插件或使用MELT(一种用于扩展GCC的高级领域特定语言;我在2017年放弃了它)

你可以像objdump一样使用gdb。

本文节选自http://sources.redhat.com/gdb/current/onlinedocs/gdb_9.html#SEC64


下面是英特尔x86混合源代码+汇编的示例:

  (gdb) disas /m main
Dump of assembler code for function main:
5       {
0x08048330 :    push   %ebp
0x08048331 :    mov    %esp,%ebp
0x08048333 :    sub    $0x8,%esp
0x08048336 :    and    $0xfffffff0,%esp
0x08048339 :    sub    $0x10,%esp

6         printf ("Hello.\n");
0x0804833c :   movl   $0x8048440,(%esp)
0x08048343 :   call   0x8048284 

7         return 0;
8       }
0x08048348 :   mov    $0x0,%eax
0x0804834d :   leave
0x0804834e :   ret

End of assembler dump.

对于risc-v反汇编,这些标志很好:

riscv64-unknown-elf-objdump -d -S -l --visualize-jumps --disassembler-color=color --inlines

-d:拆解,最基本的标志

-S:混合源。注意:编译时必须使用-g标志

-l:行号

——可视化跳跃:花哨的箭头,不是很有用,但为什么不呢?有时候get太乱了,实际上会让阅读源代码变得更加困难。来自Peter Cordes的评论:——visualize- leaps =coloris一个选项,为不同的箭头使用不同的颜色

——disassembly -color=color:给反汇编一些颜色

——inlines:打印出内行

也许有用:

-M numeric:使用数字reg名称而不是abi名称,如果你在做cpu开发并且不记得abi名称,这很有用

-M no-aliases:不要使用伪指令,如li和call

例子: main.o:

#include <stdio.h>
#include <stdint.h>

static inline void example_inline(const char* str) {
    for (int i = 0; str[i] != 0; i++)
        putchar(str[i]);
}

int main() {
    printf("Hello world");
    example_inline("Hello! I am inlined");

    return 0;
}

如果您想混合源代码,我建议使用-O0。如果使用-O2,混合源会变得非常混乱。

命令:

riscv64-unknown-elf-gcc main.c -c -O0 -g
riscv64-unknown-elf-objdump -d -S -l --disassembler-color=color --inlines main.o

Dissasembly:

main.o:     file format elf64-littleriscv


Disassembly of section .text:

0000000000000000 <example_inline>:
example_inline():
/Users/cyao/test/main.c:4
#include <stdio.h>
#include <stdint.h>

static inline void example_inline(const char* str) {
   0:   7179                    addi    sp,sp,-48
   2:   f406                    sd  ra,40(sp)
   4:   f022                    sd  s0,32(sp)
   6:   1800                    addi    s0,sp,48
   8:   fca43c23                sd  a0,-40(s0)

000000000000000c <.LBB2>:
/Users/cyao/test/main.c:5
    for (int i = 0; str[i] != 0; i++)
   c:   fe042623                sw  zero,-20(s0)
  10:   a01d                    j   36 <.L2>

0000000000000012 <.L3>:
/Users/cyao/test/main.c:6 (discriminator 3)
        putchar(str[i]);
  12:   fec42783                lw  a5,-20(s0)
  16:   fd843703                ld  a4,-40(s0)
  1a:   97ba                    add a5,a5,a4
  1c:   0007c783                lbu a5,0(a5)
  20:   2781                    sext.w  a5,a5
  22:   853e                    mv  a0,a5
  24:   00000097                auipc   ra,0x0
  28:   000080e7                jalr    ra # 24 <.L3+0x12>
/Users/cyao/test/main.c:5 (discriminator 3)
    for (int i = 0; str[i] != 0; i++)
  2c:   fec42783                lw  a5,-20(s0)
  30:   2785                    addiw   a5,a5,1
  32:   fef42623                sw  a5,-20(s0)

0000000000000036 <.L2>:
/Users/cyao/test/main.c:5 (discriminator 1)
  36:   fec42783                lw  a5,-20(s0)
  3a:   fd843703                ld  a4,-40(s0)
  3e:   97ba                    add a5,a5,a4
  40:   0007c783                lbu a5,0(a5)
  44:   f7f9                    bnez    a5,12 <.L3>

0000000000000046 <.LBE2>:
/Users/cyao/test/main.c:7
}
  46:   0001                    nop
  48:   0001                    nop
  4a:   70a2                    ld  ra,40(sp)
  4c:   7402                    ld  s0,32(sp)
  4e:   6145                    addi    sp,sp,48
  50:   8082                    ret

0000000000000052 <main>:
main():
/Users/cyao/test/main.c:9

int main() {
  52:   1141                    addi    sp,sp,-16
  54:   e406                    sd  ra,8(sp)
  56:   e022                    sd  s0,0(sp)
  58:   0800                    addi    s0,sp,16
/Users/cyao/test/main.c:10
    printf("Hello world");
  5a:   000007b7                lui a5,0x0
  5e:   00078513                mv  a0,a5
  62:   00000097                auipc   ra,0x0
  66:   000080e7                jalr    ra # 62 <main+0x10>
/Users/cyao/test/main.c:11
    example_inline("Hello! I am inlined");
  6a:   000007b7                lui a5,0x0
  6e:   00078513                mv  a0,a5
  72:   00000097                auipc   ra,0x0
  76:   000080e7                jalr    ra # 72 <main+0x20>
/Users/cyao/test/main.c:13

    return 0;
  7a:   4781                    li  a5,0
/Users/cyao/test/main.c:14
}
  7c:   853e                    mv  a0,a5
  7e:   60a2                    ld  ra,8(sp)
  80:   6402                    ld  s0,0(sp)
  82:   0141                    addi    sp,sp,16
  84:   8082                    ret

PS.在拆卸代码中有颜色

在gcc或g++上使用-Wa,-adhln作为选项来生成到标准输出的清单输出。

佤邦,……是用于汇编程序部分的命令行选项(在C/++编译后在gcc/g++中执行)。它在内部调用(Windows中的as.exe)。 看到

>——帮助

作为命令行查看GCC内部汇编工具的更多帮助

如果您给GCC提供-fverbose-asm标志,它就会

在生成的程序集代码中添加额外的注释信息,使其更具可读性。 […新增的评论包括: 编译器版本和命令行选项的信息, 与汇编指令相关联的源代码行,格式为FILENAME:LINENUMBER:CONTENT OF LINE, 提示哪些高级表达式对应于各种汇编指令操作数。