如何从visual studio 2010中的c ++代码生成优化的程序集

时间:2012-12-12 03:14:09

标签: visual-studio-2010 optimization assembly

我写了一个c ++文件,我想把它输出到程序集中。但是,我希望像下面的示例一样优化程序集:

.386
.model flat, c

; Custom Build Step, including a listing file placed in intermediate directory
; but without Source Browser information
; debug:
; ml -c -Zi "-Fl$(IntDir)\$(InputName).lst" "-Fo$(IntDir)\$(InputName).obj" "$(InputPath)"
; release:
; ml -c "-Fl$(IntDir)\$(InputName).lst" "-Fo$(IntDir)\$(InputName).obj" "$(InputPath)"
; outputs:
; $(IntDir)\$(InputName).obj

; Custom Build Step, including a listing file placed in intermediate directory
; and Source Browser information also placed in intermediate directory
; debug:
; ml -c -Zi "-Fl$(IntDir)\$(InputName).lst" "-FR$(IntDir)\$(InputName).sbr" "-Fo$(IntDir)\$(InputName).obj" "$(InputPath)"
; release:
; ml -c "-Fl$(IntDir)\$(InputName).lst" "-FR$(IntDir)\$(InputName).sbr" "-Fo$(IntDir)\$(InputName).obj" "$(InputPath)"
; outputs:
; $(IntDir)\$(InputName).obj
; $(IntDir)\$(InputName).sbr

.code
_TEXT SEGMENT
_p$ = -8
_Array$ = 8
_size$ = 12
ClearUsingPointers PROC NEAR ; ClearUsingPointers, COMDAT
; Line 15
push ebp
mov ebp, esp
sub esp, 204 ; 000000ccH
push ebx
push esi
push edi
lea edi, DWORD PTR [ebp-204]
mov ecx, 51 ; 00000033H
mov eax, -858993460 ; ccccccccH
rep stosd
; Line 17
mov eax, DWORD PTR _Array$[ebp]
mov DWORD PTR _p$[ebp], eax
jmp SHORT $L280
$L281:
mov eax, DWORD PTR _p$[ebp]
add eax, 4
mov DWORD PTR _p$[ebp], eax
$L280:
mov eax, DWORD PTR _size$[ebp]
mov ecx, DWORD PTR _Array$[ebp]
lea edx, DWORD PTR [ecx+eax*4]
cmp DWORD PTR _p$[ebp], edx
jae SHORT $L278
; Line 18
mov eax, DWORD PTR _p$[ebp]
mov DWORD PTR [eax], 0
jmp SHORT $L281
$L278:
; Line 19
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0
ClearUsingPointers ENDP ; ClearUsingPointers
_TEXT ENDS
END

如何生成上述程序集。我能够生成的那个充满了垃圾(我不知道怎么解释它),我怎样才能缩短它以便我可以手动优化它,编译并运行它?垃圾我指的是下面的多行。我可以删除它们吗? :

PUBLIC  ?value@?$integral_constant@_N$0A@@tr1@std@@2_NB ; std::tr1::integral_constant<bool,0>::value
PUBLIC  ?value@?$integral_constant@_N$00@tr1@std@@2_NB  ; std::tr1::integral_constant<bool,1>::value
PUBLIC  ?value@?$integral_constant@I$0A@@tr1@std@@2IB   ; std::tr1::integral_constant<unsigned int,0>::value
PUBLIC  ?_Rank@?$_Arithmetic_traits@_N@std@@2HB     ; std::_Arithmetic_traits<bool>::_Rank
PUBLIC  ?_Rank@?$_Arithmetic_traits@D@std@@2HB      ; std::_Arithmetic_traits<char>::_Rank
PUBLIC  ?_Rank@?$_Arithmetic_traits@C@std@@2HB      ; std::_Arithmetic_traits<signed char>::_Rank
PUBLIC  ?_Rank@?$_Arithmetic_traits@E@std@@2HB      ; std::_Arithmetic_traits<unsigned char>::_Rank
;   COMDAT ?end@?$_Iosb@H@std@@2W4_Seekdir@12@B
CONST   SEGMENT
?end@?$_Iosb@H@std@@2W4_Seekdir@12@B DD 02H     ; std::_Iosb<int>::end
CONST   ENDS
;   COMDAT ?cur@?$_Iosb@H@std@@2W4_Seekdir@12@B
CONST   SEGMENT
?cur@?$_Iosb@H@std@@2W4_Seekdir@12@B DD 01H     ; std::_Iosb<int>::cur
CONST   ENDS
;   COMDAT ?beg@?$_Iosb@H@std@@2W4_Seekdir@12@B
CONST   SEGMENT
?beg@?$_Iosb@H@std@@2W4_Seekdir@12@B DD 00H     ; std::_Iosb<int>::beg
CONST   ENDS
;   COMDAT ?binary@?$_Iosb@H@std@@2W4_Openmode@12@B
CONST   SEGMENT
?binary@?$_Iosb@H@std@@2W4_Openmode@12@B DD 020H    ; std::_Iosb<int>::binary
CONST   ENDS

2 个答案:

答案 0 :(得分:1)

在项目属性,C / C ++设置,输出文件,选择装配输出中。其输出取决于您选择的C / C ++优化设置

答案 1 :(得分:0)

通过使用/FA开关进行编译,您将从Visual C ++中精确获得所需的汇编输出。这会发出一个包含指令的列表。您的其他选择包括:

  • /FAb获取说明,然后是注释,说明其实际大小(以字节为单位)
  • /FAc获取指令,前面是用于编码该指令的实际字节
  • /FAs获取说明,从实际的C / C ++源代码中提取散布的注释,显示负责生成汇编代码块的内容

遵循CL命令行开关的标准语法,也允许这些的各种组合。例如,/FAcs将生成一个相当复杂的列表,其中包含源代码中的原始字节,汇编操作码和注释摘录。

正如Keith Nicholas所提到的那样,这也可以通过&#34;装配输出&#34;设置在&#34; C / C ++设置&#34;在Visual Studio GUI中的项目选项中。大多数可用选项都在那里,但b不是。如果要使用它,您需要手动指定它。 (我认为它可能实际上是一个没有文档的选项,但它已经在我见过的每个版本的MSVC上都有效。)

/FA的输出非常精简。您获得的唯一噪音是指示源代码的行的注释,这些行负责该特定的汇编指令块。这正是您问题中第一个示例中显示的内容。我希望有办法防止这些被包括在内,但我无法找到。这使得很难轻易地实现函数的两个变体的实现。我有一个应用程序可以手动剥离它们。

当然,请注意,这些都与优化无关。编译器生成的实际二进制代码(假设,即,您没有通过/c开关,它只进行编译但没有链接,但仍会生成汇编列表)相同< / em>,无论您使用的/FA开关的变体如何。这些附加信息都不会产生任何影响。这只是为了您的利益,在您分析代码时帮助您。

关于真正的问题,关于消除&#34;垃圾&#34;在你的第二个片段中显示...这只是来自于包含标准库头,它定义了一堆符号和其他垃圾,编译器必须将其嵌入到目标文件中,以使链接器能够完成其工作。 没有办法阻止它出现。您只有两个选择:

  1. 如果您实际上使用标准库,则不要包含任何标题库。这会给你更多&#34;更清洁&#34;使用/FA时输出。

  2. 如果 使用标准库,并且需要它来编译代码,那么您只需要忽略它。

  3. 请注意&#34;垃圾&#34;仅位于文件的顶部,可以轻松地手动将其剥离。当您尝试分析生成的目标代码时,要么只是为了理解编译器正在做什么,要么将其作为构建您自己的优化实现的起点,您需要做的就是在文本编辑器中加载文件,搜索您感兴趣的功能的名称,并右键压缩到相关代码。那里没有垃圾;只需要所需的代码。

    我应该指出,如果你的目标是采用编译器生成的汇编列表,稍微调整代码,然后通过汇编程序运行整个shebang(例如,MASM),你可以忘掉它。不保证它会起作用。 /FA汇编列表并未设计为反馈到汇编程序中。它们仅供参考。从中提取所需信息,使用编译器版本作为基础编写汇编代码,然后将清理源文件提供给汇编程序。