0

我写了一个 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
4

2 回答 2

1

在您的项目属性中,C/C++ 设置,输出文件,选择程序集输出。它的输出将取决于您选择的 C/C++ 优化设置

于 2012-12-12T03:20:04.753 回答
0

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

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

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

正如 Keith Nicholas 所提到的,这也可以在 Visual Studio GUI 中项目选项的“C/C++ 设置”下的“程序集输出”设置中进行控制。大多数可用的选项都在那里,但b不是。如果要使用它,则需要手动指定它。(我认为它实际上可能是一个未记录的选项,但它适用于我见过的每个版本的 MSVC。)

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

当然,请注意,这些都与优化无关。编译器生成的实际二进制代码(假设,也就是说,您没有传递/c开关,它只在没有链接的情况下进行编译,但仍会生成程序集列表)是相同的,无论/FA您使用哪种开关变体. 这些附加信息都没有任何影响。它只是为了您的利益,在您分析代码时为您提供帮助。

至于你真正的问题,关于消除第二个片段中显示的“垃圾”......这仅仅是因为包含了标准库头文件,它定义了编译器必须按顺序嵌入到目标文件中的一堆符号和其他垃圾使链接器能够完成其工作。没有办法阻止这种情况出现。你只有两个选择:

  1. 如果您实际上并未使用标准库,则不要包含其任何标头。使用/FA.

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

请注意,“垃圾”仅位于文件的顶部,因此可以轻松地手动将其删除。当您尝试分析生成的目标代码时,或者只是为了了解编译器在做什么,或者将其用作构建您自己的优化实现的起点,您需要做的就是在文本编辑器中加载文件,搜索获取您感兴趣的函数的名称,然后直接压缩到相关代码。那里不会有垃圾;只是所需的代码。

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

于 2016-10-03T13:58:25.940 回答