⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atl under the hood - part 4.mht

📁 大家知道wtl是window UI库
💻 MHT
📖 第 1 页 / 共 5 页
字号:
      the same name and tells the compiler to not decorate its name i.e. =
use C=20
      language linkage not C++ linkage. </P>
      <P>Now take a look what code compiler is generated for our do =
noting=20
      function. Here is the code which compiler generate for our =
function. </P><PRE lang=3Dasm>	<SPAN class=3Dcpp-keyword>push</SPAN>	ebp
	<SPAN class=3Dcpp-keyword>mov</SPAN>	ebp, esp
	<SPAN class=3Dcpp-keyword>pop</SPAN>	ebp
	<SPAN class=3Dcpp-keyword>ret</SPAN>	<SPAN class=3Dcpp-literal>0</SPAN>
</PRE>
      <P>Before go into further detail take a look at the last statement =
of the=20
      function i.e. ret 0. Why it is 0? Or can it be other than 0? As we =
have=20
      seen all the parameters which we pass to the function are in fact =
pushed=20
      into the stack. What will be the effect on register when you or =
compiler=20
      pushes something on stack? Take a look at the following simple =
program to=20
      see the behavior of this. I use the <CODE>printf</CODE> rather =
than=20
      <CODE>cout</CODE> to avoid the overhead of <CODE>cout</CODE>.=20
      </P><B>Program 59</B> <PRE><SPAN class=3Dcpp-preprocessor>#include =
&lt;cstdio&gt;</SPAN>

<SPAN class=3Dcpp-keyword>int</SPAN> g_iTemp;

<SPAN class=3Dcpp-keyword>int</SPAN> main() {

	fun(<SPAN class=3Dcpp-literal>5</SPAN>, <SPAN =
class=3Dcpp-literal>10</SPAN>);

	<SPAN class=3Dcpp-keyword>_asm</SPAN> mov g_iTemp, esp
	printf(<SPAN class=3Dcpp-string>"Before push %d\n"</SPAN>, g_iTemp);

	<SPAN class=3Dcpp-keyword>_asm</SPAN> push eax
	<SPAN class=3Dcpp-keyword>_asm</SPAN> mov g_iTemp, esp
	printf(<SPAN class=3Dcpp-string>"After push %d\n"</SPAN>, g_iTemp);
	<SPAN class=3Dcpp-keyword>_asm</SPAN> pop eax

	<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>The output of this program is </P><PRE lang=3Dtext>Before push =
1244980
After push 1244976
</PRE>
      <P>This program displays the value of ESP register before and =
after push=20
      some value into the stack. This clearly shows that when you push =
something=20
      into the stack then it grows downward in the memory. </P>
      <CENTER><IMG height=3D506=20
      =
src=3D"http://www.codeproject.com/atl/atl_underthehood_4/PIC4-1.GIF"=20
      width=3D338></CENTER>
      <P>Now there is a question, who is goring to restore the stack =
pointer=20
      when we pass parameter into the function, the function itself or =
the=20
      caller of that function? In fact both cases are possible and this =
is the=20
      difference between standard calling convention and c calling =
convention.=20
      Take a look at the very next statement after calling the function. =
</P><PRE lang=3Dasm>	<SPAN class=3Dcpp-keyword>push</SPAN>	<SPAN =
class=3Dcpp-literal>10</SPAN>					<SPAN class=3Dcpp-comment>; =
0000000aH</SPAN>
	<SPAN class=3Dcpp-keyword>push</SPAN>	<SPAN =
class=3Dcpp-literal>5</SPAN>
	<SPAN class=3Dcpp-keyword>call</SPAN>	_fun
	<SPAN class=3Dcpp-keyword>add</SPAN>	esp, <SPAN =
class=3Dcpp-literal>8</SPAN>
</PRE>
      <P>Here two parameters are passed in the function, so the stack =
pointer is=20
      subtract 8 bytes after pushing two values into the stack. Now in =
this=20
      program it is the responsibility of the caller of the function to =
set the=20
      stack pointer. This is called C Calling convention. In this =
calling=20
      convention you can pass variable no of argument, because caller =
knows how=20
      many parameter is being passed to the function, so it can set the =
stack=20
      pointer itself. </P>
      <P>However if standard calling convention is selected then it is =
the=20
      responsibility of the callee to clear the stack. So in this case =
variable=20
      not of argument can't be passed in the function, because there is =
no way=20
      to know the function that how much parameter is passed, so it cal =
set the=20
      stack pointer appropriately. </P>
      <P>Take a look at the following program to see the behavior of =
standard=20
      calling convention. </P><B>Program 60</B> <PRE><SPAN =
class=3Dcpp-keyword>extern</SPAN> <SPAN class=3Dcpp-string>"C"</SPAN> =
<SPAN class=3Dcpp-keyword>void</SPAN> _stdcall fun(<SPAN =
class=3Dcpp-keyword>int</SPAN>, <SPAN class=3Dcpp-keyword>int</SPAN>) {
}

<SPAN class=3Dcpp-keyword>int</SPAN> main() {

	fun(<SPAN class=3Dcpp-literal>5</SPAN>, <SPAN =
class=3Dcpp-literal>10</SPAN>);
	<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>Now take a look at the calling of function. </P><PRE =
lang=3Dasm>	<SPAN class=3Dcpp-keyword>push</SPAN>	<SPAN =
class=3Dcpp-literal>10</SPAN>					<SPAN class=3Dcpp-comment>; =
0000000aH</SPAN>
	<SPAN class=3Dcpp-keyword>push</SPAN>	<SPAN =
class=3Dcpp-literal>5</SPAN>
	<SPAN class=3Dcpp-keyword>call</SPAN>	_fun@<SPAN =
class=3Dcpp-literal>8</SPAN>
</PRE>
      <P>Here @ with the function name shows that this is standard =
calling=20
      convention and 8 show the no of bytes pushed into the stack. So no =
of=20
      argument can be calculated by dividing this no by 4. </P>
      <P>Here is the code of our do nothing function </P><PRE =
lang=3Dasm>	<SPAN class=3Dcpp-keyword>push</SPAN>	ebp
	<SPAN class=3Dcpp-keyword>mov</SPAN>	ebp, esp
	<SPAN class=3Dcpp-keyword>pop</SPAN>	ebp
	<SPAN class=3Dcpp-keyword>ret</SPAN>	<SPAN class=3Dcpp-literal>8</SPAN>
</PRE>
      <P>This function set the stack pointer itself with the help of =
"ret 8"=20
      instruction before leaving it. </P>
      <P>Now explore the code which compiler generate for us. Compiler =
inserts=20
      this code to make stack frame so it can access the parameter and =
local=20
      variable in standard way. Stack frame is a memory area reserved =
for the=20
      function to store the information about the parameter, local =
variable and=20
      return address. Stack frame is always created when new function is =
called=20
      and destroys when function returns. On 8086 architecture =
<CODE>EBP</CODE>=20
      register is used to store the address of stack frame, sometimes =
called=20
      stack pointer. </P>
      <P>So compiler first save the address of previous stack frame and =
then=20
      create new stack frame by using the value of <CODE>ESP</CODE>. And =
before=20
      return the function the value of old stack frame is preserved. =
</P>
      <P>Now take a look what is in the stack frame. Stack frame have =
all the=20
      parameter at +ve side of <CODE>EBP</CODE> and all the local =
variable at=20
      -ve side of <CODE>EBP</CODE>. </P>
      <P>So the return address of function is store at <CODE>EBP</CODE> =
and the=20
      value of previous Stack frame is store at <CODE>EBP + <SPAN=20
      class=3Dcpp-literal>4</SPAN>.</CODE> Now take a look at the =
example, which=20
      have two parameter and three local variables. </P><B>Program =
61</B> <PRE><SPAN class=3Dcpp-keyword>extern</SPAN> <SPAN =
class=3Dcpp-string>"C"</SPAN> <SPAN class=3Dcpp-keyword>void</SPAN> =
fun(<SPAN class=3Dcpp-keyword>int</SPAN> a, <SPAN =
class=3Dcpp-keyword>int</SPAN> b) {
	<SPAN class=3Dcpp-keyword>int</SPAN> x =3D a;
	<SPAN class=3Dcpp-keyword>int</SPAN> y =3D b;
	<SPAN class=3Dcpp-keyword>int</SPAN> z =3D x + y;
	<SPAN class=3Dcpp-keyword>return</SPAN>;
}

<SPAN class=3Dcpp-keyword>int</SPAN> main() {
	fun(<SPAN class=3Dcpp-literal>5</SPAN>, <SPAN =
class=3Dcpp-literal>10</SPAN>);
	<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>And now take a look at the compiler generated code of the =
function.=20
</P><PRE lang=3Dasm>	<SPAN class=3Dcpp-keyword>push</SPAN>	ebp
	<SPAN class=3Dcpp-keyword>mov</SPAN>	ebp, esp
	<SPAN class=3Dcpp-keyword>sub</SPAN>	esp, <SPAN =
class=3Dcpp-literal>12</SPAN>					<SPAN class=3Dcpp-comment>; =
0000000cH</SPAN>

	<SPAN class=3Dcpp-comment>; int x =3D a;</SPAN>
	<SPAN class=3Dcpp-keyword>mov</SPAN>	eax, DWORD PTR _a$[ebp]
	<SPAN class=3Dcpp-keyword>mov</SPAN>	DWORD PTR _x$[ebp], eax

	<SPAN class=3Dcpp-comment>; int y =3D b;</SPAN>
	<SPAN class=3Dcpp-keyword>mov</SPAN>	ecx, DWORD PTR _b$[ebp]
	<SPAN class=3Dcpp-keyword>mov</SPAN>	DWORD PTR _y$[ebp], ecx

	<SPAN class=3Dcpp-comment>; int z =3D x + y;</SPAN>
	<SPAN class=3Dcpp-keyword>mov</SPAN>	edx, DWORD PTR _x$[ebp]
	<SPAN class=3Dcpp-keyword>add</SPAN>	edx, DWORD PTR _y$[ebp]
	<SPAN class=3Dcpp-keyword>mov</SPAN>	DWORD PTR _z$[ebp], edx

	<SPAN class=3Dcpp-keyword>mov</SPAN>	esp, ebp
	<SPAN class=3Dcpp-keyword>pop</SPAN>	ebp
	<SPAN class=3Dcpp-keyword>ret</SPAN>	<SPAN class=3Dcpp-literal>0</SPAN>
</PRE>
      <P>Now what is _x, _y etc. It is define just above the function =
definition=20
      something like this </P><PRE lang=3Dtext>_a$ =3D 8
_b$ =3D 12
_x$ =3D -4
_y$ =3D -8
_z$ =3D -12
</PRE>
      <P>Means you can read this code something like this </P><PRE =
lang=3Dasm>	<SPAN class=3Dcpp-comment>; int x =3D a;</SPAN>
	<SPAN class=3Dcpp-keyword>mov</SPAN>	eax, DWORD PTR [ebp + <SPAN =
class=3Dcpp-literal>8</SPAN>]
	<SPAN class=3Dcpp-keyword>mov</SPAN>	DWORD PTR [ebp - <SPAN =
class=3Dcpp-literal>4</SPAN>], eax

	<SPAN class=3Dcpp-comment>; int y =3D b;</SPAN>
	<SPAN class=3Dcpp-keyword>mov</SPAN>	ecx, DWORD PTR [ebp + <SPAN =
class=3Dcpp-literal>12</SPAN>]
	<SPAN class=3Dcpp-keyword>mov</SPAN>	DWORD PTR [ebp - <SPAN =
class=3Dcpp-literal>8</SPAN>], ecx

	<SPAN class=3Dcpp-comment>; int z =3D x + y;</SPAN>
	<SPAN class=3Dcpp-keyword>mov</SPAN>	edx, DWORD PTR [ebp - <SPAN =
class=3Dcpp-literal>4</SPAN>]
	<SPAN class=3Dcpp-keyword>add</SPAN>	edx, DWORD PTR [ebp - <SPAN =
class=3Dcpp-literal>8</SPAN>]
	<SPAN class=3Dcpp-keyword>mov</SPAN>	DWORD PTR [ebp - <SPAN =
class=3Dcpp-literal>12</SPAN>], edx
</PRE>
      <P>Means the address of parameters a and b are <CODE>EBP + <SPAN=20
      class=3Dcpp-literal>8</SPAN></CODE> and <CODE>EBP + <SPAN=20
      class=3Dcpp-literal>12</SPAN> </CODE>respectively. And the value =
of x, y and=20
      z are store at memory location <CODE>EBP - <SPAN=20
      class=3Dcpp-literal>4</SPAN></CODE>, <CODE>EBP - <SPAN=20
      class=3Dcpp-literal>8</SPAN></CODE>, <CODE>EBP - <SPAN=20
      class=3Dcpp-literal>12</SPAN> </CODE>respectively. </P>
      <P>After armed with this knowledge lets play a game with the =
parameter of=20
      the functions. Let's take a look at this simple program. =
</P><B>Program=20
      62</B> <PRE><SPAN class=3Dcpp-preprocessor>#include =
&lt;cstdio&gt;</SPAN>

<SPAN class=3Dcpp-keyword>extern</SPAN> <SPAN =
class=3Dcpp-string>"C"</SPAN> <SPAN class=3Dcpp-keyword>int</SPAN> =
fun(<SPAN class=3Dcpp-keyword>int</SPAN> a, <SPAN =
class=3Dcpp-keyword>int</SPAN> b) {
	<SPAN class=3Dcpp-keyword>return</SPAN> a + b;
}

<SPAN class=3Dcpp-keyword>int</SPAN> main() {

	printf(<SPAN class=3Dcpp-string>"%d\n"</SPAN>, fun(<SPAN =
class=3Dcpp-literal>4</SPAN>, <SPAN class=3Dcpp-literal>5</SPAN>));
	<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>The output of this program is expected. Out put of this program =
is "9".=20
      Now change a program little bit. </P><B>Program 63</B> <PRE><SPAN =
class=3Dcpp-preprocessor>#include &lt;cstdio&gt;</SPAN>

<SPAN class=3Dcpp-keyword>extern</SPAN> <SPAN =
class=3Dcpp-string>"C"</SPAN> <SPAN class=3Dcpp-keyword>int</SPAN> =
fun(<SPAN class=3Dcpp-keyword>int</SPAN> a, <SPAN =
class=3Dcpp-keyword>int</SPAN> b) {
	<SPAN class=3Dcpp-keyword>_asm</SPAN> mov dword ptr[ebp+<SPAN =
class=3Dcpp-literal>12</SPAN>], <SPAN class=3Dcpp-literal>15</SPAN>
	<SPAN class=3Dcpp-keyword>_asm</SPAN> mov dword ptr[ebp+<SPAN =
class=3Dcpp-literal>8</SPAN>], <SPAN class=3Dcpp-literal>14</SPAN>
	<SPAN class=3Dcpp-keyword>return</SPAN> a + b;
}

<SPAN class=3Dcpp-keyword>int</SPAN> main() {

	printf(<SPAN class=3Dcpp-string>"%d\n"</SPAN>, fun(<SPAN =
class=3Dcpp-literal>4</SPAN>, <SPAN class=3Dcpp-literal>5</SPAN>));
	<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>The output of this program is "29". We know the address of =
parameter=20
      and in this program we change the value of parameter. And when we =
add=20
      those variables then new values i.e. 15 and 14 are added. </P>
      <P>VC has naked attributed for function. If you specify any =
function to=20
      naked then it won't generate prolog and epilog code for that =
function. Now=20
      what is prolog and epilog code? Prolog is an English word mean =
"Opening",=20
      yes it is a name of programming language too, which is used in AI, =
but=20
      there is no relation between that programming language and prolog =
code=20
      generated by the compiler. This is a code which compiler =
automatically=20
      inserted in the opening of the function calling to set the stack =
frame.=20
      Take a look at assembly language code generated by program 61. In =
the=20
      beginning of the function compiler automatically insert the =
following code=20

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -