Pages

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

No comments:

Post a Comment