测试 cl 在使用MSVC编译器(通过cl命令)生成汇编代码时,您可以使用多种选项来控制生成的汇编代码的格式和内容。以下是一些常用的选项:
/FA:生成汇编代码列表。此选项必须与/Fa一起使用来指定输出文件名。 /Fa[filename]:指定汇编代码列表的输出文件名。 /FAs:生成带符号的汇编代码。这通常会产生更易于阅读的代码,其中包含了函数名和变量名。 /FAc:生成包含源代码的汇编代码。这将把源代码和生成的汇编代码混合在一起,有助于理解汇编代码与源代码之间的关系。 /FAu:生成未优化的汇编代码。这对于理解编译器生成的代码很有帮助,因为它显示了编译器在没有优化时的行为。 /Ox 或 /Od:分别用于启用(/Ox)或禁用(/Od)优化。优化可能会显著改变生成的汇编代码。 例如,如果您想生成带符号的、未优化的汇编代码,可以使用以下命令:
1 cl /FAs /Od /Faoutput.asm stackDemo.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 ; Listing generated by Microsoft (R) Optimizing Compiler Version 19.36.32535.0 TITLE D:\WHC\blog\source\_posts\�ִ�cppʵս\02\stackDemo.obj .686P .XMM include listing.inc .model flat INCLUDELIB LIBCMT INCLUDELIB OLDNAMES PUBLIC ?foo@@YAXH@Z ; foo PUBLIC ?bar@@YAXH@Z ; bar PUBLIC _main ; Function compile flags: /Odtp ; File D:\WHC\blog\source\_posts\�ִ�cppʵս\02\stackDemo.cpp _TEXT SEGMENT _main PROC ; 13 : { push ebp mov ebp, esp ; 14 : bar(42); push 42 ; 0000002aH ; 函数的符号标签(或称为符号名)可能因为编译器对函数名称进行的“名称修饰”(Name Mangling) ; 或“名称重整”而不一样。名称修饰是编译器用来区分具有相同名称但参数列表不同的函数的一种机制。 ; 这种机制在C++中尤为重要,因为C++支持函数重载,允许有多个同名函数,只要它们的参数列表不同。 call ?bar@@YAXH@Z ; bar add esp, 4 ; 15 : } xor eax, eax pop ebp ret 0 _main ENDP _TEXT ENDS ; Function compile flags: /Odtp ; File D:\WHC\blog\source\_posts\�ִ�cppʵս\02\stackDemo.cpp _TEXT SEGMENT _a$ = -4 ; size = 4 _n$ = 8 ; size = 4 ?bar@@YAXH@Z PROC ; bar ; 7 : { ; 设置栈框架 push ebp mov ebp, esp ; 参数压栈 push ecx ; 8 : int a = n + 1; mov eax, DWORD PTR _n$[ebp] add eax, 1 ; 非优化的汇编代码,所以这里把 n+1 计算一遍放到本地变量 a 中 mov DWORD PTR _a$[ebp], eax ; 9 : foo(a); ; 然后又把 a 放到 ecx 中再去调用 foo ; 把 a 的值取出来放到 ecx 中 mov ecx, DWORD PTR _a$[ebp] push ecx call ?foo@@YAXH@Z ; foo add esp, 4 ; 10 : } mov esp, ebp pop ebp ret 0 ?bar@@YAXH@Z ENDP ; bar _TEXT ENDS ; Function compile flags: /Odtp ; File D:\WHC\blog\source\_posts\�ִ�cppʵս\02\stackDemo.cpp _TEXT SEGMENT _a$ = 8 ; size = 4 ?foo@@YAXH@Z PROC ; foo ; 2 : { push ebp mov ebp, esp ; 3 : ; 4 : } pop ebp ret 0 ?foo@@YAXH@Z ENDP ; foo _TEXT ENDS END