Compilation Analysis of Function Call in VC Environment [Original]

xiaoxiao2021-03-06  41

Compilation Analysis of Function Call in VC Environment [Original]

Frontier: Some details in our usual programming, such as __stdcall and __cdecl compiler how to deal with us, the variables in the function, and the variables from New, which places are stored in the end, and so on. This article will analyze the assembly language executed by everyone with everyone, and master your own code by mastering this process, making yourself knowing and optimizing your code. Author: tink joints, contact e-mail:

Waterpub @ mail.9cbs.net, MSN:

Waterpub_cn@hotmail.com, my QQ group 3226292, please keep your full document.

1. Environment: The development environment I use is VC7.1, and its Release single-step debugging requires the following modifications to the project properties:

"C " - "" General "" debug information format "is changed to:" For "editing and continuing" program database (/ zi) "

"C " - "Optimization -" Optimization "is changed: disabled (/ OD)

If you are a VC6 environment, you can modify the Release version attribute as follows:

Select Win32 Release and then Project- "Setting-" C / C - "Category-" General- "Optimization-" disable (debug) - "Debug Info-" Program Database- "Link ---" Generate Debug Info hook hook

2. C language code, as follows:

/***Start********************************************* ******** /

#include "stdafx.h"

INT __CDECL Add (int A, INT B)

{

INT C;

C = a b;

Return C;

}

INT _Tmain (int Argc, _tchar * argv [])

{

INT IRESULT = Add (123, 456);

Printf ("/ n *********** / n");

Return 0;

}

/***end********************************************* ******** /

3. Program analysis process, F10 single-step startup program:

/***Start********************************************* ******** /

INT _Tmain (int Argc, _tchar * argv [])

{

00401020 Push EBP creates stack frames

00401021 MOV EBP, ESP is stored in the stack base, after running EBP = 0012FEE4

(Indicates that the default stack size is about 1 trillion)

00401023 SUB ESP, 44H

Empty out of a stack area, I don't know what to do, can have a high person?

×××××××××××××××××××××

In a container debug article of a VC6, I saw that the variable in Main is stored in this stack, but I found that the IRESULT address is not within the stack in VC7 debugging. I don't know what to explain.

××××××××××××××××××× 00401026 Push EBX protection site 00401027 PUSH ESI

00401028 Push EDI

INT IRESULT = Add (123, 456);

00401029 PUSH 1C8H parameter

0040102E Push 7bh

00401030 Call Add (401000H)

Perform a function call, press F11 to jump to the blue of this article

×××××××××××××××××××××

Call instruction details:

The CALL instruction is a combination of PUSH and JMP, first execute the PUSH EIP to put the current address into the stack (the function call is required to return it), then call the JMP instruction. Because the normal instructions cannot operate on the EIP, there is often a statement in many virus programs:

Call @@ get_eip @@ get_eip: POP EBP; get EIP

×××××××××××××××××××××

00401035 Add ESP, 8 release 123 and 456 variables

00401038 MOV DWORD PTR [IRESULT], EAX Removes results from EAX

Printf ("/ n *********** / N"); below is a function test

0040103B Push Offset String "/ n *********** / n" (4060fch) Variable Address Add Store

00401040 Call Printf (401051H) Performs a Call call function

00401045 Add ESP, 4 variable address outlet

Return 0;

00401048 XOR Eax, Eax makes EAX 0, EAX is the value returned to the operating system

}

0040104A POP EDI

0040104B POP ESI

0040104C POP EBX recovery site

0040104D MOV ESP, EBP Balance Stack

0040104F POP EBP Release Stack Frame

00401050 RET returns the operating system call

Function definition:

INT __CDECL Add (int A, INT B)

{

00401000 PUSH EBP Create Stack Frame

00401001 MOV EBP, ESP deposit into the base address

00401003 SUB ESP, 44H opens up the stacker area used by the variable, for internal variables for functions

Before execution, ESP = 0012FE84, after execution, ESP = 0012FE40

×××××××××××××××××××××

Here you can open the memory 0x0012FE8C, see 7b 00 00 00 C8 01 00 00, this is our incoming 123 (0x0012FE8C) and 456 (0x0012FE90) variables

×××××××××××××××××××××

00401006 PUSH EBX Protection Site

00401007 Push ESI00401008 PUSH EDI

INT C;

C = a b;

00401009 MOV EAX, DWORD PTR [A] The first parameter, that is, [EBP 8]

0040100C Add Eax, DWORD PTR [B] The second parameter, that is, [EBP C]

0040100F MOV DWORD PTR [C], EAX C variable In the stack, the address is 0x0012FE80, which is the top of the variable stack area.

Return C;

00401012 MOV EAX, DWORD PTR [C] Calculation results are deposited in EAX

}

00401015 POP EDI Reply site

00401016 POP ESI

00401017 POP EBX

00401018 MOV ESP, EBP Balance Stack, Recycling Variable Stack Area

0040101A POP EBP Release Stack Frame

0040101b Ret returns to the call address, the reader turned from here to the pink

/***end********************************************* ******** /

4. About __cdecl and __stdcall: (VC project default call mode is __cdecl)

We will change the above add function to __stdcall form, the execution process is as follows, and I will make a mark with the above __cdecl calls:

/***Start********************************************* ******** /

INT _Tmain (int Argc, _tchar * argv [])

{

00401020 PUSH EBP

00401021 MOV EBP, ESP

00401023 SUB ESP, 44H

00401026 PUSH EBX

00401027 PUSH ESI

00401028 Push EDI

INT IRESULT = Add (123, 456);

00401029 PUSH 1C8H

0040102E Push 7bh

00401030 Call Add (401000H)

Note that there is no ADD ESP, 8, and the reason for this sentence: __ stdcall call mode The stack parameter has been released inside the function, so this sentence is not required. 00401035 MOV DWORD PTR [IRESULT], EAX

Printf ("/ n *********** / n");

00401038 Push Offset String "/ N *********** / N" (4060fch)

0040103D Call Printf (40104EH)

00401042 Add ESP, 4

Return 0;

00401045 xor Eax, EAX

}

00401047 POP EDI

00401048 POP ESI

00401049 POP EBX

0040104A MOV ESP, EBP

0040104c POP EBP

0040104D RET function part:

INT __STDCALL ADD (int A, int b)

{

00401000 PUSH EBP

00401001 MOV EBP, ESP

00401003 SUB ESP, 44H

00401006 PUSH EBX

00401007 PUSH ESI

00401008 Push EDI

INT C;

C = a b;

00401009 MOV Eax, DWORD PTR [A]

0040100C Add Eax, DWORD PTR [B]

0040100F MOV DWORD PTR [C], EAX

Return C;

00401012 MOV EAX, DWORD PTR [C]

}

00401015 POP EDI

00401016 POP ESI

00401017 POP EBX

004018 MOV ESP, EBP

0040101A POP EBP

0040101B RET 8

This sentence is the __stdcall call mode in the stack parameters

The statement released inside the function!

/***end********************************************* ******** /

Description: For the passage of the function or the address, everyone has analyzed here, I believe that beginners can see a lot of details.

5. Initialization of global variables:

#include "stdafx.h"

Const char szname [] = "

http://blog.9cbs.neet/waterpub ";

Class CTestClass

{

PUBLIC:

CTestClass ()

{

Printf ("ctestclass :: ctestclass () / n");

}

~ Ctestclass ()

{

Printf ("ctestclass :: ~ ctestclass () / n");

}

}

Const ctestclass tobject;

INT _Tmain (int Argc, _tchar * argv [])

{

Printf ("/ n *********** / n");

Return 0;

}

How to initialize the szname in this program, why didn't you perform the corresponding anti-excitement?

Szname has been initialized because the main function starts, and all we can't run this place. When the user starts this EXE program, enter the C / C runtime library code (

Crtstartup, which initializes static variables and global variables, and then transfer to the main function.

We now set a breakpoint on the green section, then run, the program is disconnected here. Press (Ctrl Alt C: VC7.1 shortcuts, VC6 has the corresponding menu item), point to the bottom-up call function, can be seen from this: The program is executed by the operating system when executing the "MainCrtStartup" function, simplifies the code I posted below, some very intuitive in English:

/***Start********************************************* ******** /

INT WinMainCrtStartup (Void)

{

Int initret;

Int mainret;

OsversionInfoa * POSVI; int ManagedApp;

POSVI = (OSVersionInfoa *) _ Alloca (Sizeof (osversioninfoa)); // uses this function to avoid the assignment runtime detection of global storage buffers

// Operating system version related code

POSVI-> dwosversionInfosize = sizeof (OsversionInfoa);

(void) getversionExa (POSVI);

_SPLATFORM = POSVI-> dwplatformID;

_winmajor = POSVI-> DWMAJORVERSION;

_winminor = POSVI-> dwminorversion;

_SVER = (POSVI-> dwbuildnumber) & 0x07FFF;

IF (_OSPLATFORM! = VER_PLATFORM_WIN32_NT)

_SVER | = 0x08000;

_winver = (_winmajor << 8) _winminor;

/ / Whether it is a managed program?

ManagedApp = Check_managed_app ();

#ifdef _mt

IF (! _heap_init (1)) / * Multi-threaded in this way is initialized * /

#ELSE / * _MT * /

IF (! _heap_init (0)) / * Single-threaded use this mode to initialize the pile * /

#ENDIF / * _MT * /

FAST_ERROR_EXIT (_RT_HEAPINIT); / * WRITE Message and Die * /

#ifdef _mt

IF (! _mtinit ()) / * Initialize Multi-Thread * /

FAST_ERROR_EXIT (_RT_THREAD); / * Write Message and Die * /

#ENDIF / * _MT * /

/ *

* Initialize the runtime checks stuff

* /

#ifdef _RTC

_RTC_Initialize (); // Initialization Runtime

#ENDIF / * _RTC * /

/ *

* The following is the remaining initialization code (including the initialization of the global variable of my program is here, huh, huh)

* Initialization, call main or winmain (executed in TRY)

* /

__Try {

IF (_IOINIT () <0) / * IO initialization, it should be input and output, not clear * /

_AMSG_EXIT (_RT_LOWIOINIT);

#ifdef wprflag

/ * GET WIDE CMD LINE INFO * /

_wcmdln = (wchar_t *) __ crtgetCommandLinew (); // String to run the parameters

/ * Get Wide Environ Info * /

_wenvptr = (wchar_t *) __ crtGetenvironmentStringsw (); / / String of the environment variable

IF (_wsetargv () <0)

_AMSG_EXIT (_RT_SPACEARG);

IF (_wsetenvp () <0)

_AMSG_EXIT (_RT_SPACEENV);

#ELSE / * WPRFLAG * /

/ * Get cmd line info * /

_ACMDLN = (char *) getcommandlinea (); / * get environ info * /

_aenvptr = (char *) __ crtGetenvironmentStrings ();

IF (_setargv () <0)

_AMSG_EXIT (_RT_SPACEARG);

IF (_setenvp () <0)

_AMSG_EXIT (_RT_SPACEENV);

#ENDIF / * WPRFLAG * /

Initret = _CINIT (TRUE); / * Global variable is initialized, it is here! ! ! * /

IF (initret! = 0)

_AMSG_EXIT (Initret);

#ifdef _winmain_

STARTUPINFO.DWFLAGS = 0;

GetStartupInfo (& Startupinfo);

#ifdef wprflag

LPSZCOMMANDLINE = _wwincmdln ();

MainRet = wwinmain

#ELSE / * WPRFLAG * /

LPSZCOMMANDLINE = _wincmdln ();

MainRet = WinMain

#ENDIF / * WPRFLAG * /

GetModuleHandlea (NULL),

NULL,

LPSZCommandline,

Startupinfo.dwflags & Startf_useshowWindow

? Startupinfo.wshowWindow

: SW_SHOWDEFAULT

);

#ELSE / * _WINMAIN_ * /

#ifdef wprflag

__winitenv = _wenviron;

Mainret = WMAIN (__ argc, __wargv, _wenviron);

#ELSE / * WPRFLAG * /

__INITENV = _ENVIRON

Mainret = main (__ argc, __ARGV, _ENVIRON);

// The main call is called here because the runtime code is in the exe file, so you can call the main function (there is no difference with the ordinary function. If you read Win32 compilation, you know that the main or Winmain name is not fixed. Dead)!

#ENDIF / * WPRFLAG * /

#ENDIF / * _WINMAIN_ * /

IF (! managementApp)

exit (mainret);

_cexit ();

}

__except (_xcptfilter (getExceptionCode (), getExceptioninformation ()) // Abnormally here is here, such as lost DLL files

{

/ *

* SHOULD Never Reach Here

* /

MainRet = getExceptioncode ();

IF (! managementApp)

_exit (mainret);

_c_exit ();

} / * end of try - Except * /

Return mainRet;

}

/***end********************************************* ******** /

6.WIN32 startup process

Since the console program we analyze, what is the difference between Win32? The difference is still there (the core code of the launchler is in the CRT0.C file), I have explained the specific analysis method, and Win32 is left to everyone, :) 7. Error may have, Or can be written better, but this dish is only this level, laughing and generous, please ask the master to do not finger. Articles may be modified at any time if you have any questions or good ideas, to my blog (

Http://blog.9cbs.net/waterpub) message, don't stay here, I have less, :)

8. Shenzhen Nanshan Science and Technology Park Science and Technology Industry Building 2005-02-22 17:00:00

转载请注明原文地址:https://www.9cbs.com/read-55166.html

New Post(0)