Visual Studio Options for Cleaner Assembly

Experimenting with Visual Studio compiler options has been an interest of mine lately. The goal is to get cleaner assembly in IDA. While writing C code I sometimes wonder "how would this C code translate to assembly?". Google gave me some decent command line options for CL but I still couldn't get the code I wanted. Luckily, I stumbled upon some extremely helpful slides by OpenSecurityTraining.com. Sadly, the slides are zipped and haven't been indexed by Google. Below are the options for Visual Studio C++ for cleaner assembly.
(right click on .c or .cpp)
Source File > Properties

Configuration Properties > C/C++ > General
> Debug Information Format - Program DataBase (/Zi)
> Warning Level - Level3 (/W3)

Configuration Properties > C/C++ > Code Generation
> Enable Minimal Rebuilt - No
> Enable C++ Exception - No
> Basic Runtime Checks - Default
> Buffer Security Check - No (/GS-)

Configuration Properties > C/C++ > Advanced
> Compile As - Compile as C Code (/TC)

Configuration Properties > Linker > General
> Enable Incremental Linking - No (/INCREMENTAL:NO)

So how does each one of these options effect a "Hello World" when we change one option, compile and then change the next?

#include

int main(void)
{
printf("Hello world!");
return 0;
}

Compiled using Visual Studio 2010 C++ default settings.

.text:00411380 main proc near ; CODE XREF: j_main j
.text:00411380
.text:00411380 var_C0 = dword ptr -0C0h
.text:00411380
.text:00411380 push ebp
.text:00411381 mov ebp, esp
.text:00411383 sub esp, 0C0h
.text:00411389 push ebx
.text:0041138A push esi
.text:0041138B push edi

//////////////////////////////////////////////////////////////////////////////

.text:0041138C lea edi, [ebp+var_C0]
.text:00411392 mov ecx, 30h
.text:00411397 mov eax, 0CCCCCCCCh
.text:0041139C rep stosd

//////////////////////////////////////////////////////////////////////////////
// Initialization of local variables to a nonzero value. This helps identify
// bugs that do not appear when running in debug mode. There is a greater
// chance that stack variables will still be zero in a debug build compared
// to a release build because of compiler optimizations of stack variables in
// a release build. Once a program has used an area of its stack, it is never
// reset to 0 by the compiler. Therefore, subsequent, uninitialized stack
// variables that happen to use the same stack area can return values left
// over from the prior use of this stack memory.
// Source http://msdn.microsoft.com/en-us/library/8wtf2dfz.aspx
//////////////////////////////////////////////////////////////////////////////

.text:0041139E mov esi, esp
.text:004113A0 push offset aHelloWorld ; "Hello world!"
.text:004113A5 call ds:__imp__printf
.text:004113AB add esp, 4
.text:004113AE cmp esi, esp
.text:004113B0 call j__RTC_CheckEsp
.text:004113B5 xor eax, eax
.text:004113B7 pop edi
.text:004113B8 pop esi
.text:004113B9 pop ebx
.text:004113BA add esp, 0C0h
.text:004113C0 cmp ebp, esp
.text:004113C2 call j__RTC_CheckEsp

//////////////////////////////////////////////////////////////////////////////
// In debug versions of executables, the Microsoft Visual Studio compilers
// insert a call to RTC_CheckEsp() after each function call. Prior to the
// function call, the contents of the stack pointer register (ESP/RSP) are
// saved into a general-purpose register. This function compares the contents
// of that general-purpose register with the stack pointer to verify that the
// stack pointer was restored correctly. This error usually occurs when a
// function is declared using one calling-convention and actually implemented
// using another. If there is a mismatch, the library generates an error message
// and a breakpoint.
// Source: http://blogs.phoenix.com/phoenix_technologies_bios/2008/11/bios-undercover-porting-cc-to-phoenix-uefi.html
//////////////////////////////////////////////////////////////////////////////

.text:004113C7 mov esp, ebp
.text:004113C9 pop ebp
.text:004113CA retn
.text:004113CA main endp

Size 27,136 bytes.

Configuration Properties > C/C++ > General > Debug Information Format - Program DataBase (/Zi)


//////////////////////////////////////////////////////////////////////////////
// Produces a program database (PDB) that contains type information and symbolic
// debugging information for use with the debugger. The symbolic debugging
// information includes the names and types of variables, as well as functions and
// line numbers.

// /Zi does not affect optimizations. However, /Zi does imply /debug; see /DEBUG
// (Generate Debug Info) for more information.
// Source: http://msdn.microsoft.com/en-us/library/958x11bc%28v=vs.80%29.aspx
//////////////////////////////////////////////////////////////////////////////

.text:00401010 main proc near ; CODE XREF: j_main j
.text:00401010 push ebp
.text:00401011 mov ebp, esp
.text:00401013 push esi
.text:00401014 mov esi, esp
.text:00401016 push offset aHelloWorld ; "Hello world!"
.text:0040101B call ds:__imp__printf
.text:00401021 add esp, 4
.text:00401024 cmp esi, esp
.text:00401026 call _RTC_CheckEsp
.text:0040102B xor eax, eax
.text:0040102D pop esi
.text:0040102E cmp ebp, esp
.text:00401030 call _RTC_CheckEsp
.text:00401035 pop ebp
.text:00401036 retn
.text:00401036 main endp

Size 26,624 bytes.

Configuration Properties > C/C++ > Code Generation > Enable Minimal Rebuilt - No (/GM-)
* No changes in code or size.

Configuration Properties > C/C++ > Code Generation > Enable C++ Exception - No
* No changes in code or size.

Configuration Properties > C/C++ > Code Generation > Basic Runtime Checks - Default


//////////////////////////////////////////////////////////////////////////////
// Used to enable and disable the run-time error checks feature, in conjunction
// with the runtime_checks pragma.
// Source:http://msdn.microsoft.com/en-us/library/8wtf2dfz.aspx
//////////////////////////////////////////////////////////////////////////////

.text:00401010 main proc near ; CODE XREF: j_main j
.text:00401010 push ebp
.text:00401011 mov ebp, esp
.text:00401013 push offset aHelloWorld ; "Hello world!"
.text:00401018 call ds:__imp__printf
.text:0040101E add esp, 4
.text:00401021 xor eax, eax
.text:00401023 pop ebp
.text:00401024 retn
.text:00401024 main endp

Size 18,432 bytes

Configuration Properties > C/C++ > Code Generation > Buffer Security Check - No (/GS-
* No changes in code or size.

Project Name > Properties > Configuration Properties > Linker > General
> Enable Incremental Linking - No (/INCREMENTAL:NO)


//////////////////////////////////////////////////////////////////////////////
// The /INCREMENTAL option controls how the linker handles incremental linking.
// By default, the linker runs in incremental mode. To override a default
// incremental link, specify /INCREMENTAL:NO. An incrementally linked program is
// functionally equivalent to a program that is nonincrementally linked. However,
// because it is prepared for subsequent incremental links, an incrementally
// linked executable (.exe) file or dynamic-link library (DLL). Is larger than a
// nonincrementally linked program because of padding of code and data. (Padding
// allows the linker to increase the size of functions and data without recreating
// the .exe file.) May contain jump thunks to handle relocation of functions to
// new addresses.
// Source: http://msdn.microsoft.com/en-us/library/4khtbfyf%28v=vs.80%29.aspx
//////////////////////////////////////////////////////////////////////////////

.text:00401000 main proc near ; CODE XREF: __tmainCRTStartup+1BA p
.text:00401000 push ebp
.text:00401001 mov ebp, esp
.text:00401003 push offset aHelloWorld ; "Hello world!"
.text:00401008 call ds:__imp__printf
.text:0040100E add esp, 4
.text:00401011 xor eax, eax
.text:00401013 pop ebp
.text:00401014 retn
.text:00401014 main endp

Size 8,192 bytes

Configuration Properties > C/C++ > Optimization - Minimum Size (/01)

//////////////////////////////////////////////////////////////////////////////
// The /O options control various optimizations that help you create code for
// maximum speed or minimum size. /O1 optimizes code for minimum size.
// Source: http://msdn.microsoft.com/en-us/library/k1ack8f1.aspx
//////////////////////////////////////////////////////////////////////////////

.text:00401000 main proc near ; CODE XREF: __tmainCRTStartup+1BA p
.text:00401000 push offset aHelloWorld ; "Hello world!"
.text:00401005 call ds:__imp__printf
.text:0040100B pop ecx
.text:0040100C xor eax, eax
.text:0040100E retn
.text:0040100E main endp
.text:0040100E

Size 8,192 bytes

2 comments:

  1. Hi : Thank you for your post, I try is work fine :)

    ReplyDelete
  2. Straight out of a Richie Rich comic book comes Irona, the robot maid! This time she's here to help you do the floors. robot vacuum

    ReplyDelete