Reputation: 347
I have written a c++ file and i want to output it into assembly. However, I want the assembly to be optimized like the example below:
.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
How has the above assembly been generated. The one that i am able to generate is full of garbage(i don't know how else to explain it), How can i shorten it so i can optimize it manually, compile it and run it? BY garbage i am referring to multiple lines like those below. Can i delete them? :
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
Upvotes: 0
Views: 476
Reputation: 244991
You will get precisely the assembly output you desire from Visual C++ by compiling with the /FA
switch. This emits a listing containing only the instructions. Your other options include:
/FAb
to get the instructions, followed by a comment stating its actual size (in bytes)/FAc
to get the instructions, preceded by the actual bytes used to encode that instruction/FAs
to get the instructions, with comments interspersed extracted from your actual C/C++ source code, showing what was responsible for generating those chunks of assembly codeVarious combinations of these are also allowed, following the standard syntax for CL's command-line switches. For example, /FAcs
will produce a rather complex-looking listing containing the raw bytes, assembly opcodes, and commented extracts from your source code.
This can also be controlled, as Keith Nicholas mentioned, in the "Assembly Output" setting under "C/C++ Settings" in the project options within the Visual Studio GUI. Most of the available options are there, but b
isn't. You'll need to specify it manually if you want to use it. (I think it might actually be an undocumented option, but it's worked on every version of MSVC I've ever seen.)
The output of /FA
alone is very lean. The only noise you get are the comments indicating the lines of your source code that are responsible for that particular chunk of assembly instructions. This is precisely what is shown in the first example from your question. I wish there was a way to prevent these from being included, but I can't find one. It makes it very difficult to easily diff the implementation of two variants of a function. I have an app that strips them out manually.
Note, of course, that none of this has anything to do with optimization. The actual binary code that the compiler generates (assuming, that is, you aren't passing the /c
switch, which does a compile only without linking, but will still generate assembly listings) is identical, regardless of which variation of the /FA
switch that you use. None of this additional information has any effect whatsoever. It is only for your benefit, aiding you when you are analyzing the code.
As for your real question, about eliminating the "garbage" shown in your second snippet… That simply comes from having included standard-library headers, which define a bunch of symbols and other junk that the compiler has to embed in the object files in order to make it possible for the linker to do its job. There is no way to prevent this from showing up. You have only two options:
If you aren't actually using the standard library, then don't include any of its headers. This will give you much "cleaner" output when using /FA
.
If you are using the standard library, and need it to get the code to compile, then you'll just have to ignore it.
Notice that the "garbage" is only at the top of the file, making it possible to easily strip it out manually. When you're trying to analyze the generated object code, either just to understand what the compiler is doing or use it as a starting point to build your own optimized implementation, all you need to do is load the file in a text editor, search for the name of the function(s) you're interested in, and zip right to the relevant code. There will be no garbage there; just the required code.
I should point out that, if you are aiming to take the compiler-generated assembly listings, tweak the code slightly, and then run the whole shebang through an assembler (e.g., MASM), you can forget about it. There's no guarantee that it will work. The /FA
assembly listings aren't designed to be fed back into an assembler. They are informational only. Extract the information you need from them, write the assembly code using the compiler's version as a basis, and then feed your clean source files into the assembler.
Upvotes: 0
Reputation: 44316
In your project properties, C/C++ settings, Output files, Select Assembly Output. Its output will depend on what C/C++ optimization settings you select
Upvotes: 1