c++ - 通过阅读 gcc 输出来学习汇编

标签 c++ gcc assembly g++

我试图通过阅读 GCC 生成的输出来理解汇编。这是我在 C++ 中的代码:

int main() {
    int x = 8;
}

我编译它使用:

g++ -g -Wa,-alh=source.s -masm=intel -fverbose-asm -O2 -g -Wall -c -fmessage-length=0 -o source.o "..\\源.cpp"

但是我完全不理解生成的所有内容,即使有评论也是如此:

GAS LISTING C:\Users\Silkworm\AppData\Local\Temp\ccmDrbTs.s             page 1


   1                    .file   "source.cpp"
   2                    .intel_syntax noprefix
   3                 # GNU C++ (x86_64-posix-seh-rev0, Built by MinGW-W64 project) version 5.1.0 (x86_64-w64-mingw32)
   4                 #  compiled by GNU C version 5.1.0, GMP version 6.0.0, MPFR version 3.1.2-p11, MPC version 1.0.3
   5                 # GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
   6                 # options passed: 
   7                 # -iprefix C:/mingw-w64/x86_64-5.1.0-posix-seh-rt_v4-rev0/mingw64/bin/../lib/gcc/x86_64-w64-mingw3
   8                 # -D_REENTRANT ..\source.cpp -masm=intel -mtune=core2 -march=nocona
   9                 # -auxbase-strip source.o -g -g -O2 -Wall -fverbose-asm
  10                 # -fmessage-length=0
  11                 # options enabled:  -faggressive-loop-optimizations -falign-labels
  12                 # -fasynchronous-unwind-tables -fauto-inc-dec -fbranch-count-reg
  13                 # -fcaller-saves -fchkp-check-incomplete-type -fchkp-check-read
  14                 # -fchkp-check-write -fchkp-instrument-calls -fchkp-narrow-bounds
  15                 # -fchkp-optimize -fchkp-store-bounds -fchkp-use-static-bounds
  16                 # -fchkp-use-static-const-bounds -fchkp-use-wrappers
  17                 # -fcombine-stack-adjustments -fcommon -fcompare-elim -fcprop-registers
  18                 # -fcrossjumping -fcse-follow-jumps -fdefer-pop
  19                 # -fdelete-null-pointer-checks -fdevirtualize -fdevirtualize-speculatively
  20                 # -fdwarf2-cfi-asm -fearly-inlining -feliminate-unused-debug-types
  21                 # -fexceptions -fexpensive-optimizations -fforward-propagate
  22                 # -ffunction-cse -fgcse -fgcse-lm -fgnu-runtime -fgnu-unique
  23                 # -fguess-branch-probability -fhoist-adjacent-loads -fident
  24                 # -fif-conversion -fif-conversion2 -findirect-inlining -finline
  25                 # -finline-atomics -finline-functions-called-once -finline-small-functions
  26                 # -fipa-cp -fipa-cp-alignment -fipa-icf -fipa-icf-functions
  27                 # -fipa-icf-variables -fipa-profile -fipa-pure-const -fipa-ra
  28                 # -fipa-reference -fipa-sra -fira-hoist-pressure -fira-share-save-slots
  29                 # -fira-share-spill-slots -fisolate-erroneous-paths-dereference -fivopts
  30                 # -fkeep-inline-dllexport -fkeep-static-consts -fleading-underscore
  31                 # -flifetime-dse -flra-remat -flto-odr-type-merging -fmath-errno
  32                 # -fmerge-constants -fmerge-debug-strings -fmove-loop-invariants
  33                 # -fomit-frame-pointer -foptimize-sibling-calls -foptimize-strlen
  34                 # -fpartial-inlining -fpeephole -fpeephole2 -fpic -fprefetch-loop-arrays
  35                 # -free -freg-struct-return -freorder-blocks -freorder-functions
  36                 # -frerun-cse-after-loop -fsched-critical-path-heuristic
  37                 # -fsched-dep-count-heuristic -fsched-group-heuristic -fsched-interblock
  38                 # -fsched-last-insn-heuristic -fsched-rank-heuristic -fsched-spec
  39                 # -fsched-spec-insn-heuristic -fsched-stalled-insns-dep -fschedule-fusion
  40                 # -fschedule-insns2 -fsemantic-interposition -fset-stack-executable
  41                 # -fshow-column -fshrink-wrap -fsigned-zeros -fsplit-ivs-in-unroller
  42                 # -fsplit-wide-types -fssa-phiopt -fstdarg-opt -fstrict-aliasing
  43                 # -fstrict-overflow -fstrict-volatile-bitfields -fsync-libcalls
  44                 # -fthread-jumps -ftoplevel-reorder -ftrapping-math -ftree-bit-ccp
  45                 # -ftree-builtin-call-dce -ftree-ccp -ftree-ch -ftree-coalesce-vars
  46                 # -ftree-copy-prop -ftree-copyrename -ftree-cselim -ftree-dce
  47                 # -ftree-dominator-opts -ftree-dse -ftree-forwprop -ftree-fre
  48                 # -ftree-loop-if-convert -ftree-loop-im -ftree-loop-ivcanon
  49                 # -ftree-loop-optimize -ftree-parallelize-loops= -ftree-phiprop -ftree-pre
  50                 # -ftree-pta -ftree-reassoc -ftree-scev-cprop -ftree-sink -ftree-slsr
  51                 # -ftree-sra -ftree-switch-conversion -ftree-tail-merge -ftree-ter
  52                 # -ftree-vrp -funit-at-a-time -funwind-tables -fvar-tracking
  53                 # -fvar-tracking-assignments -fverbose-asm -fzero-initialized-in-bss
  54                 # -m128bit-long-double -m64 -m80387 -maccumulate-outgoing-args
  55                 # -malign-double -malign-stringops -mcx16 -mfancy-math-387 -mfentry
  56                 # -mfp-ret-in-387 -mfxsr -mieee-fp -mlong-double-80 -mmmx -mms-bitfields
  57                 # -mno-sse4 -mpush-args -mred-zone -msse -msse2 -msse3 -mstack-arg-probe
GAS LISTING C:\Users\Silkworm\AppData\Local\Temp\ccmDrbTs.s             page 2


  58                 # -mvzeroupper
  59                
  60                    .text
  61                .Ltext0:
  62                    .cfi_sections   .debug_frame
  63                    .def    __main; .scl    2;  .type   32; .endef
  64                    .section    .text.startup,"x"
  65                    .p2align 4,,15
  66                    .globl  main
  67                    .def    main;   .scl    2;  .type   32; .endef
  68                    .seh_proc   main
  69                main:
  70                .LFB0:
  71                    .file 1 "../source.cpp"
   1:../source.cpp **** 
   2:../source.cpp **** int main() {
  72                    .loc 1 2 0
  73                    .cfi_startproc
  74 0000 4883EC28      sub rsp, 40  #,
  75                    .seh_stackalloc 40
  76                    .cfi_def_cfa_offset 48
  77                    .seh_endprologue
  78                    .loc 1 2 0
  79 0004 E8000000      call    __main   #
  79      00
  80                .LVL0:
   3:../source.cpp **** int x = 8;
   4:../source.cpp **** }
  81                    .loc 1 4 0
  82 0009 31C0          xor eax, eax     #
  83 000b 4883C428      add rsp, 40  #,
  84                    .cfi_def_cfa_offset 8
  85 000f C3            ret
  86                    .cfi_endproc
  87                .LFE0:
  88                    .seh_endproc
  89                    .text
  90                .Letext0:
  91                    .section    .debug_info,"dr"
  92                .Ldebug_info0:
  93 0000 CF000000      .long   0xcf
  94 0004 0400          .word   0x4
  95 0006 00000000      .secrel32   .Ldebug_abbrev0
  96 000a 08            .byte   0x8
  97 000b 01            .uleb128 0x1
  98 000c 474E5520      .ascii "GNU C++ 5.1.0 -masm=intel -mtune=core2 -march=nocona -g -g -O2 -fmessage-length=0\0"
  98      432B2B20 
  98      352E312E 
  98      30202D6D 
  98      61736D3D 
  99 005e 04            .byte   0x4
 100 005f 2E2E5C68      .ascii "..\\source.cpp\0"
 100      656C6C6F 
 100      776F726C 
 100      642E6370 
 100      7000
 101 0071 433A5C63      .ascii "C:\\cpp_workspace\\disam\\Debug\0"
GAS LISTING C:\Users\Silkworm\AppData\Local\Temp\ccmDrbTs.s             page 3


 101      70705F77 
 101      6F726B73 
 101      70616365 
 101      5C646973 
 102 008e 00000000      .secrel32   .Ldebug_ranges0+0
 103 0092 00000000      .quad   0
 103      00000000 
 104 009a 00000000      .secrel32   .Ldebug_line0
 105 009e 02            .uleb128 0x2
 106 009f 6D61696E      .ascii "main\0"
 106      00
 107 00a4 01            .byte   0x1
 108 00a5 02            .byte   0x2
 109 00a6 CB000000      .long   0xcb
 110 00aa 00000000      .quad   .LFB0
 110      00000000 
 111 00b2 10000000      .quad   .LFE0-.LFB0
 111      00000000 
 112 00ba 01            .uleb128 0x1
 113 00bb 9C            .byte   0x9c
 114 00bc CB000000      .long   0xcb
 115 00c0 03            .uleb128 0x3
 116 00c1 7800          .ascii "x\0"
 117 00c3 01            .byte   0x1
 118 00c4 03            .byte   0x3
 119 00c5 CB000000      .long   0xcb
 120 00c9 08            .byte   0x8
 121 00ca 00            .byte   0
 122 00cb 04            .uleb128 0x4
 123 00cc 04            .byte   0x4
 124 00cd 05            .byte   0x5
 125 00ce 696E7400      .ascii "int\0"
 126 00d2 00            .byte   0
 127                    .section    .debug_abbrev,"dr"
 128                .Ldebug_abbrev0:
 129 0000 01            .uleb128 0x1
 130 0001 11            .uleb128 0x11
 131 0002 01            .byte   0x1
 132 0003 25            .uleb128 0x25
 133 0004 08            .uleb128 0x8
 134 0005 13            .uleb128 0x13
 135 0006 0B            .uleb128 0xb
 136 0007 03            .uleb128 0x3
 137 0008 08            .uleb128 0x8
 138 0009 1B            .uleb128 0x1b
 139 000a 08            .uleb128 0x8
 140 000b 55            .uleb128 0x55
 141 000c 17            .uleb128 0x17
 142 000d 11            .uleb128 0x11
 143 000e 01            .uleb128 0x1
 144 000f 10            .uleb128 0x10
 145 0010 17            .uleb128 0x17
 146 0011 00            .byte   0
 147 0012 00            .byte   0
 148 0013 02            .uleb128 0x2
 149 0014 2E            .uleb128 0x2e
 150 0015 01            .byte   0x1
GAS LISTING C:\Users\Silkworm\AppData\Local\Temp\ccmDrbTs.s             page 4


 151 0016 3F            .uleb128 0x3f
 152 0017 19            .uleb128 0x19
 153 0018 03            .uleb128 0x3
 154 0019 08            .uleb128 0x8
 155 001a 3A            .uleb128 0x3a
 156 001b 0B            .uleb128 0xb
 157 001c 3B            .uleb128 0x3b
 158 001d 0B            .uleb128 0xb
 159 001e 49            .uleb128 0x49
 160 001f 13            .uleb128 0x13
 161 0020 11            .uleb128 0x11
 162 0021 01            .uleb128 0x1
 163 0022 12            .uleb128 0x12
 164 0023 07            .uleb128 0x7
 165 0024 40            .uleb128 0x40
 166 0025 18            .uleb128 0x18
 167 0026 9642          .uleb128 0x2116
 168 0028 19            .uleb128 0x19
 169 0029 01            .uleb128 0x1
 170 002a 13            .uleb128 0x13
 171 002b 00            .byte   0
 172 002c 00            .byte   0
 173 002d 03            .uleb128 0x3
 174 002e 34            .uleb128 0x34
 175 002f 00            .byte   0
 176 0030 03            .uleb128 0x3
 177 0031 08            .uleb128 0x8
 178 0032 3A            .uleb128 0x3a
 179 0033 0B            .uleb128 0xb
 180 0034 3B            .uleb128 0x3b
 181 0035 0B            .uleb128 0xb
 182 0036 49            .uleb128 0x49
 183 0037 13            .uleb128 0x13
 184 0038 1C            .uleb128 0x1c
 185 0039 0B            .uleb128 0xb
 186 003a 00            .byte   0
 187 003b 00            .byte   0
 188 003c 04            .uleb128 0x4
 189 003d 24            .uleb128 0x24
 190 003e 00            .byte   0
 191 003f 0B            .uleb128 0xb
 192 0040 0B            .uleb128 0xb
 193 0041 3E            .uleb128 0x3e
 194 0042 0B            .uleb128 0xb
 195 0043 03            .uleb128 0x3
 196 0044 08            .uleb128 0x8
 197 0045 00            .byte   0
 198 0046 00            .byte   0
 199 0047 00            .byte   0
 200                    .section    .debug_aranges,"dr"
 201 0000 2C000000      .long   0x2c
 202 0004 0200          .word   0x2
 203 0006 00000000      .secrel32   .Ldebug_info0
 204 000a 08            .byte   0x8
 205 000b 00            .byte   0
 206 000c 0000          .word   0
 207 000e 0000          .word   0
GAS LISTING C:\Users\Silkworm\AppData\Local\Temp\ccmDrbTs.s             page 5


 208 0010 00000000      .quad   .LFB0
 208      00000000 
 209 0018 10000000      .quad   .LFE0-.LFB0
 209      00000000 
 210 0020 00000000      .quad   0
 210      00000000 
 211 0028 00000000      .quad   0
 211      00000000 
 212                    .section    .debug_ranges,"dr"
 213                .Ldebug_ranges0:
 214 0000 00000000      .quad   .LFB0
 214      00000000 
 215 0008 10000000      .quad   .LFE0
 215      00000000 
 216 0010 00000000      .quad   0
 216      00000000 
 217 0018 00000000      .quad   0
 217      00000000 
 218                    .section    .debug_line,"dr"
 219                .Ldebug_line0:
 220 0000 41000000      .section    .debug_str,"dr"
 220      02002800 
 220      00000101 
 220      FB0E0D00 
 220      01010101 
 221                    .ident  "GCC: (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 5.1.0"

这里没有一条我学到的指令,如 movl、pop,没有寄存器,如 %eax 或类似的东西。这与我在网上遇到的例子完全不同。我怎么能理解这个。

最佳答案

正如 @user2864740 所提到的,这不是学习汇编的最佳方式,但是您可以学习和理解不同的编译器如何将 C/C++ 转换为汇编以及它们如何优化您的代码。

在您的示例中,您看不到任何值得学习的有趣内容,因为您的代码不包含任何功能,而且您使用优化 (-O2) 对其进行编译。

  1. 如果您希望看到一些汇编代码以您易于理解的方式反射(reflect)您编写的内容,请不要使用优化 (-O0)。
  2. 请注意,您选择了“intel”汇编代码语法,还有 AT&T 代码语法 (check here)。如果您想看到 AT&T 风格,请从编译行中删除 -masm=intel

例如,尝试构建以下代码:

int main()
{
 int x = 8;
 int y = 18;
 int z = x + y;

 return z;
}

没有优化你会得到类似的东西:

  35                main:
  36                .LFB2:
  37                    .file 1 "assm.cpp"
   1:assm.cpp      **** int main()
  38                    .loc 1 1 0
  39 0000 55            push    %rbp    #
  40                .LCFI0:
  41 0001 4889E5        mov %rbp, %rsp  #,
  42                .LCFI1:
  43                .LBB2:
   2:assm.cpp      ****     {
   3:assm.cpp      ****      int x = 8;
  44                    .loc 1 3 0
  45 0004 C745F408      mov DWORD PTR [%rbp-12], 8  # x,
  45      000000
   4:assm.cpp      ****      int y = 18;
  46                    .loc 1 4 0
  47 000b C745F812      mov DWORD PTR [%rbp-8], 18  # y,
  47      000000
GAS LISTING /tmp/ccHUnQdo.s            page 2


   5:assm.cpp      ****      int z = x + y;
  48                    .loc 1 5 0
  49 0012 8B45F8        mov %eax, DWORD PTR [%rbp-8]    # y, y
  50 0015 0345F4        add %eax, DWORD PTR [%rbp-12]   # tmp60, x
  51 0018 8945FC        mov DWORD PTR [%rbp-4], %eax    # z, tmp60
   6:assm.cpp      ****     
   7:assm.cpp      ****      return z;
  52                    .loc 1 7 0
  53 001b 8B45FC        mov %eax, DWORD PTR [%rbp-4]    # D.2339, z
  54                .LBE2:
   8:assm.cpp      ****     }
  55                    .loc 1 8 0
  56 001e C9            leave
  57 001f C3            ret

你可以看到局部变量在堆栈上(RBP 用于访问它们)并且编译器为它们分配了 12 个字节 (x,y,z) => 在我的机器上 sizeof(int) 是 4 个字节。 RBP 指向堆栈的末尾,x 首先在堆栈上分配,因此为了访问它,编译器使用“RBP-12”(y 是堆栈上的第二个,因此它被“RBP-8”访问,等等在)。方括号表示内存访问,括号中的值表示地址。“DWORD PTR”表示内存访问大小为“双字”,即4字节(字=16位=2字节)。

使用 -O2 优化,编译器优化掉所有代码并立即返回 26(如果 32 位足以保存该值而不会丢失数据,则返回值通常放在 EAX 中):

  48                main:
  49                .LFB2:
  50                    .file 1 "assm.cpp"
   1:assm.cpp      **** int main()
  51                    .loc 1 1 0
   2:assm.cpp      ****     {
GAS LISTING /tmp/ccZvidrN.s            page 2


   3:assm.cpp      ****      int x = 8;
   4:assm.cpp      ****      int y = 18;
   5:assm.cpp      ****      int z = x + y;
   6:assm.cpp      ****     
   7:assm.cpp      ****      return z;
   8:assm.cpp      ****     }
  52                    .loc 1 8 0
  53 0000 B81A0000      mov %eax, 26    # <result>,
  53      00
  54 0005 C3            ret

关于c++ - 通过阅读 gcc 输出来学习汇编,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31979829/

相关文章:

c++ - 为什么禁止对位域的非常量引用?

C++ 调用尚未定义的函数

c++ - 匿名结构内部循环

c++ - GCC 和 clang 关于 "typename"关键字的分歧

linux - 从 gprof 输出丢失热函数

c++ - Intel x86 上的 C++ 原子是否需要内存屏障?

c++ - 错误 : cannot convert in arguement passing

c - 在反汇编代码中声明数组

c++ - 通过查看程序集比较按值传递与按引用传递的性能

c++ - 在 Ruby 和 C++ 中左移 16 位