我试图通过读取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 "..\\source.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这样的寄存器。这与我在网上遇到的例子完全不同。我怎么能理解这一点。
答案 0 :(得分:1)
你的程序实际上没有做任何事情;未使用局部变量x,并且编译器已将其删除。大多数汇编代码都是调试信息,其余的与调用main函数必须完成的操作有关。
你应该能够识别这一行:
xor eax, eax
您的main函数隐式返回零。该值在eax寄存器中返回,因此该行在eax中为零。
答案 1 :(得分:1)
正如@ user2864740所提到的,这不是学习汇编的最佳方式,但是你可以学习和理解不同的编译器如何将C / C ++转换为汇编以及如何优化代码。
在您的示例中,您将看不到任何有趣的内容,因为您的代码不包含任何功能,您也可以使用优化(-O2)进行编译。
-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