About the invocation of a compiled language function (ii)

Source: Internet
Author: User

Connect to the above: http://blog.csdn.net/prsniper/article/details/40652451


The address of the local variable mentioned above, the first one is [ebp-4], because of the 32-bit memory alignment reason, the second is [ebp-8], for VC7 above the version, this address may be different

For example, the first may be [ebp-8], the second fly to [ebp-14], which is vs.net VC compiler before and after each local variable plus a DWORD, the value is naturally 0xCCCCCCCC

Debug if the function ends, these DWORD values are not 0xCCCCCCCC then the code unexpectedly accesses the place that should not be visited, that is, overflow


Below we go to the function that has the return value of the default __CDECL convention to look at:

122:      ret = Fndefaultcall (4, 5, 6, &var1); 0040136B   Lea         eax,[ebp-14h]0040136e   Push        eax0040136f   push        600401371   push        500401373   push        400401375   call        @ILT +0 ( Fndefaultcall) (00401005) 0040137A   add         esp,10h0040137d   mov         dword ptr [ebp-18h],eax123:
With the knowledge of the preceding, the invocation is simple, and the address is loaded into the Eax,push to the stack, etc.

This eax to the address of the RET, this is not the variable is not initialized to use it? or EAX is the address of RET is ebp-14, what is this?

Yuan Fang said that the VC function uses EAX and edx as the return value! If you had said so earlier, I would have known ...

We're going to go in there and see what it's doing, and the key is in these places.

       p = (int *) arg4;004011cc   mov         eax,dword ptr [ebp+14h]004011cf   mov         dword ptr [ebp-10h],eax32:       *p = 7;004011d2   mov         ecx,dword ptr [ebp-10h]004011d5   mov         dword ptr [ecx],733:34:       return 0;0 04011DB   xor         eax,eax35:   }004011dd   pop         EDI
The first pass in the DWORD is a pointer, assembly language all over the sky are pointers, compared to high-level language pointers are much less, VB and so simply there is no pointer to the concept,

C + + can be compatible with most of the assembly language functions, cast, then the next assignment is good understanding, *p = 7 is

The value of move p to ecx, and then mov 7 to [ECX] is the memory address that ecx points to

If it is * (int *) ARG4 = 7 is mov ecx, [ebp+14h] again mov [ECX], 7, note if it is ARG4 =7 that is not the same as the value of the modified address is 7, instead of a value of 7

The return 0 is the XOR eax, and any number XOR itself becomes 0,EAX as the return value, as stated earlier

After execution, the main function of the var1=7;ret=0;


Next, we're going to call __stdcall's function, which is the old Pascal that uses this convention, but the point is that all Windows APIs also use this Convention

So let's just find out!

124:      ret = Fnstandardcall (8, 9, ten, &var1); 00401380   Lea         ecx,[ebp-14h]00401383   Push        ecx00401384   push        0ah00401386   push        900401388   push        80040138A   call        @ILT +20 ( Fnstandardcall) (00401019) 0040138F   mov         dword ptr [ebp-18h],eax125:
From the command of the call to see, careful you will immediately find that the little girl's body seems to be missing something pendant, Amitabha, sin!

Yes, the previous function call after the end of the add esp,xxx the previous push parameters are ejected, here is not, really strange!

Then we'll track into the dark alley and see what he's done!

37:int __stdcall fnstandardcall (int arg1, short arg2, char arg3, void *arg4): {00401200 push ebp00401201        MOV ebp,esp00401203 sub esp,50h00401206 push ebx00401207 push esi00401208 push edi00401209 Lea edi,[ebp-50h]0040120c mov ecx,14h00401211 mov eax,0cccccccch00401216 re P STOs DWORD ptr [Edi]39:int var1;40:short var2;41:char Var3;42:int *p;43:44:var1 = arg1;00401218 mov eax,dword ptr [ebp+8]0040121b mov dword ptr [EBP-4],EAX45:VAR2 = arg2;0040121         E mov cx,word ptr [ebp+0ch]00401222 mov word ptr [ebp-8],cx46:var3 = arg3;00401226 mov Dl,byte ptr [ebp+10h]00401229 mov byte ptr [ebp-0ch],dl47:p = (int *) ARG4;0040122C mov eax,dw Ord ptr [ebp+14h]0040122f mov dword ptr [ebp-10h],eax48: *p = 11;00401232 mov ecx,dword ptr [EBP]     -10H]00401235 mov    DWORD ptr [Ecx],0bh49:50:return 0;0040123b xor eax,eax51:}0040123d pop edi0040123e Pop esi0040123f pop ebx00401240 mov esp,ebp00401242 pop ebp00401243 ret 10h
The above things and the default __cdecl convention a touch, once Thai said: "mentor says, Tittle!"

Finally is the key, the former RET, turned to RET 10h, ran to this, or said merge here, Yuan Fang said: "The truth of the matter is actually so!"

This so-called maintenance stack, is just finished, who will clean the scene!

This is not entirely superficial, such as the API just pass in the parameters, get the return value, so this is a lazy to the caller of the Convention.


Then the next is Fastcall, as the name suggests should be a quick call, how a quick Method? See call

125:126:      ret = Fnfastcall (one, one, and &var1); 00401392   Lea         edx,[ebp-14h]00401395   Push        edx00401396   push        0dh00401398   mov         edx,0ch0040139d   mov         ecx,0bh004013a2   call        @ Ilt+25 (Fnfastcall) (0040101e) 004013a7   mov         dword ptr [ebp-18h],eax127:
obediently, there are only two push, the first second parameter is directly transmitted ECX and edx, the other with the __stdcall a touch!

Is it okay to push or not? This question should be asked, why must push to be able to do it! Let's follow it up in detail:

:   int __fastcall fnfastcall (int arg1, short arg2, char arg3, void *arg4):   {00401260   push        ebp00401261   mov         ebp,esp00401263   Sub         esp,58h00401266   push        ebx00401267   push        esi00401268   push        edi00401269   push        ecx0040126a   Lea         edi,[ebp-58h]0040126d   mov         ecx,16h00401272   mov         eax,0cccccccch00401277   rep stos    dword ptr [edi]00401279   pop         ecx0040127a   mov         word ptr [ebp-8],dx0040127e   mov         dword ptr [EBP-4],ECX
The key is in the preceding instructions, when creating the function temporary stack, the compiler protects the two registers and then automatically creates two local variables to save them.

So, the compiler is not a human being, it doesn't matter! Thus, the efficiency of C + + is high, and normal programmers write programs that are much worse than assembly language, unless inline assembly or optimized

In the future when we talk about naked functions, this is the point where the code behind the function is understandable, almost identical to the previous one.

65:66:       return 0;004012a4   xor         eax,eax67:   }004012a6   pop         edi004012a7   pop         Esi004012a8   pop         ebx004012a9   mov         esp,ebp004012ab   pop         ebp004012ac   ret         8
Pay attention to the back of RET 8, because after the direct recovery of ESP, so the process of push are quietly pop


Then we say thiscall, when a member variable of a class is called, the this pointer is passed automatically, so thiscall is an implicit declaration

Let's take a look at the assembly instructions for the new object:

£ º      Pcall = new Ccall (), 004013AA   push        4004013AC   call        operator new (004015b0) 004013b1   add         esp,4004013b4   mov         dword ptr [EBP-20H],EAX004013B7   mov         dword ptr [EBP-4],0004013BE   CMP         DWORD ptr [ebp-20h],0004013c2   je          main+0a1h (004013d1) 004013c4   mov         ecx,dword ptr [ebp-20h] 004013c7   Call        @ILT +35 (ccall::ccall) (00401028) 004013CC   mov         dword ptr [EBP-2CH],EAX004013CF   jmp         main+0a8h (004013d8) 004013d1   mov         dword ptr [Ebp-2ch],0004013d8   mov         eax,dword ptr [ebp-2ch]004013db   mov         dword ptr [ebp-1ch],eax004013de   mov         dword ptr [Ebp-4], 0ffffffffh004013e5   mov         ecx,dword ptr [ebp-1ch]004013e8   mov         dword ptr [EBP-10H],ECX
At this level, new is actually a function. And as you can see, the memory size of Ccall is four bytes.

Returned after saving to Pcall that is [ebp-20], here suddenly a mov [ebp-4], 0, after we say

Then determine whether the returned pointer is a NULL,CMP instruction, if NULL jumps to 0X004013D1, that is, MOV dword ptr [ebp-2ch],0 this

If you do not continue execution for zero

mov Ecx,dword ptr [ebp-20h]

Call @ILT +35 (Ccall::ccall) (00401028)

[ebp-20] is Pcall,call is the class of the constructor, coax, the original transferred this to the ecx inside, and then follow the look at the constructor

00401079   push        ecx0040107a   Lea         edi,[ebp-44h]0040107d   mov         ecx,11h00401082   mov         eax,0cccccccch00401087   Rep STOs    dword ptr [edi]00401089   pop         ecx0040108a   mov         dword ptr [ ebp-4],ecx6:        m_var1 = 18;0040108d   mov         eax,dword ptr [ebp-4]00401090   mov         dword ptr [EAX], 12h7:    }00401096   mov         eax,dword ptr [ebp-4]
Save the ECX (that is, the thsi pointer), create a temporary stack, create a temporary variable instead of ECX, [ebp-4], because M_VAR1 is the first member, the class occupies only 4 bytes

So the direct transfer to EAX that [ebp-4], and then the value of ebp-4 to EAX, you can see the compiler around a large section of bend, which is why the previous talk about the game view of the time

I use C as much as possible, instead of C + +, as you can see, the constructor has a return value, and the return value is this!

Go back to the calling code, jump straight after normal initialization, skip the new failed

004013D1 mov dword ptr [ebp-2ch],0

Then a large pile of MOV transmission, EAX is the return value of this, passed to [ebp-2c], and then if new failure [EBP-2C] and passed in 0, and then passed to eax, and then passed to [EBP-1C]!!!

As a pursuit of the perfect technical staff, would be anxious to put Microsoft hacked!

See the new return value before the evaluation of a [ebp-4] assignment is 0, at this time to assign a value of 1, and then the [ebp-1c] transmitted to the 0 passed to ECX, and then ecx to [ebp-10], no words!

Don't look so much flying, if the normal initialization execution succeeds, [ebp-10] is a pointer to the class, if new fails the 0 is the null!


Here is the call to the member function:

129:      ret = Pcall->call (&var1), 004013EB   Lea         edx,[ebp-14h]004013ee   Push        Edx004013ef   push        11h004013f1   push        10h004013f3   push        0fh004013f5   mov         ecx, DWORD ptr [Ebp-10h]004013f8   call        @ILT +30 (ccall::call) (00401023) 004013FD   mov         dword ptr [ebp-18h ],eax
The same this pointer is passed to the ECX, and the return value is saved in the EAX register. The parameters are entered in the stack from right to left. Stack member function Auto cleanup
004010E9 push ecx004010ea Lea edi,[ebp-54h]004010ed mov ecx,15h004010f2 mov eax,0cc       Cccccch004010f7 Rep stos dword ptr [edi]004010f9 pop ECX004010FA mov dword ptr [ebp-4],ecx15: int Var1;16:short Var2;17:char Var3;18:int *p;19:var1 = ARG1;004010FD mov Eax,dwo RD PTR [ebp+8]00401100 mov dword ptr [EBP-8],EAX20:VAR2 = arg2;00401103 mov cx,word ptr [ebp+0c   H]00401107 mov word ptr [ebp-0ch],cx21:var3 = arg3;0040110b mov dl,byte ptr [ebp+10h]0040110e         mov byte ptr [ebp-10h],dl22:p = (int *) arg4;00401111 mov eax,dword ptr [ebp+14h]00401114 mov DWORD ptr [ebp-14h],eax23: *p = m_var1;00401117 mov ecx,dword ptr [ebp-14h]0040111a mov E Dx,dword ptr [ebp-4]0040111d mov eax,dword ptr [edx]0040111f mov dword ptr [Ecx],eax24:return 0         ; 00401121 XOREAX,EAX25:} 
As you can see, you still create a temporary variable to hold ECX (that is, [ebp-4]), and then use this to refer to the member variable, thiscall is more verbose than the various calling conventions above

are slow, but this is the cost of object-oriented object, development and maintenance is simpler, the sacrifice is the execution efficiency, this can only rely on hardware performance to compensate;

Similarly. NET development and maintenance debugging super easy, fault-tolerant ability is extremely powerful, also sacrificed security, in front of dis#, the source code completely exposed ...


Then again Int3 time, the following we say the last function of the knowledge, bare function!


About the invocation of a compiled language function (ii)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.