Original: http://www.cnblogs.com/rain-lei/p/3622057.html
Function call Everyone is not strange, the caller passed some parameters to the callee, then executed the caller's code, and finally the caller returned the result to the caller, there is a familiar word, that is, the function call occurs on the stack, then in the computer inside exactly how to achieve it? For the program, the compiler allocates a memory for it, logically divided into code snippets, data segments, heaps, stack code snippets: Save program text, instruction pointer EIP is point to code snippet, can read executable non-writable data segment: Save the initialized global variables and static variables, Readable writable non-executable BSS: Uninitialized global variables and static variable heap (heap): Dynamically allocating memory, growing in the direction of increased address, readable writable executable stack (stack): Storing local variables, function parameters, current state, function call information, etc., to reduce the direction of the address of the growth, very very important , Readable writable executable
Register DeviceEAX: Accumulate (accumulator) register, commonly used for function return value EBX: base register, which accesses memory for base address ECX: Counter (Counter) register, commonly used as the counter in string and loop operation edx: Data register, Commonly used in multiplication and I/O pointers esi: source Change Register DSI: Destination register ESP: stack pointer register, pointing to Stack top EBP: Base point pointer Register, pointing to current stack bottom EIP: instruction register, pointing to the address of the next instruction
Source Code
int Print_out (int begin,IntEnd) {printf ("%d", begin++);int *P p = (int*) (Int (&begin)-4);if (Begin <=End) *p-=5;Return1;}int Add (int A,Intb) {Return a +b;}int Pass (int A,int B,Intc) {Char buffer[4] = {0};int sum =0;int *Ret RET = (int*) (buffer+28);//(*ret) + = 0xA; sum = a + B +CReturnsum;}IntMain () {Print_out (0,2); printf "\n" ); int a = 1 int B = 2int C; c = add (a, b); pass (A, B, c); int __sum; __asm {mov __sum, eax} printf ( "%d\n" "pause" );}
Initialization of functions
28:IntMain ()29: {011c1540 Push EBP// stack, save EBP, note push operation implied esp-4011c1541 mov ebp,esp // Pass the value of ESP to EBP, set the current ebp011c1543 sub esp,0f0h // space for the function, the range is (EBP, ebp-0xf0) 011c1549 push ebx011c154a push esi011c154b push edi011c154c Lea edi,[ebp-0f0h] // EDI is assigned ebp-0xf0011c1552 mov ecx, 3Ch //011c1557 mov eax,0cccccccch011c155c rep stos dword ptr Es:[edi] //rep instruction is to repeat the instructions above. The value of ECX is the number of repetitions. //stos instruction is to copy the value in EAX to the address that Es:edi points to, and then edi+4
This command is used at the beginning of a general function, where the state register is saved, the stack register is saved, and the function memory space is initialized.
function Call
30:print_out (2///// first argument stack 013d1562 call Print_out (13d10fah)// return address stack, in this case 013d1567, Then call the Print_out function 013d1567 add ESP,/// Two arguments out of the stack // note in the Invoke command, the implied action is to stack the address of the next instruction, the so-called return address
the initialization of Print_out is exactly the same as the initialization of the main function except that the VS may add some security checks
The called function returns
013d141c mov eax,1 // return value passed in eax 013d1421 pop edi 013d1422 pop esi 013d1423 pop eb x // register out stack 013d1424 add esp,0d0h // The following 3 commands are called vs __rtc_checkesp, check stack overflow 013D142A cmp ebp,esp013d142c call @ILT +315 (__rtc_ CHECKESP) (13d1140h) 013d1431 mov esp,ebp //EBP is passed to ESP, That is, restore the value of the ESP before the call 013d1433 pop ebp // pop EBP, restore the value of EBP 013d1434 RET // write the return address into the EIP equivalent to the pop eip
Call instruction implied operation push Eip,ret instruction implicit operation Pop EIP, two instructions completely correspond to write here we can analyze the main function called Print_out function before and after the stack (stacks) What happened, the following with a series of diagram description
The next step is the return process, starting with the 013d1431 line code aboveBefore and after the Print_out function call, the stack frame of the main function is exactly the same, perfect! Now let's see what the Print_out function does.
int *p;p = (int*) (4); if (begin <=5;
According to the above call print_out function, you can know that P is actually pointing to the function of the return address addr, and then put addr-5, what happens? And look back at the disassembly code,
first argument stack 013d1562 call Print_out (13d10fah)// return address stack, in this case 013d1567, then Print_out function 013d1567 Add ESP,// Two actual arguments out of stack
The analysis shows that the value of the return address addr is 013d1567, addr-5 is 013d1562, the return address points to the call instruction, and the result is that the Print_out function is called again, so that the Print_out function implements all the numbers printed from begin to end , it can be said that the loop called the Print_out function for the Add function, mainly to show that the return value is stored in the register EAX. In addition, VS itself will provide some security checks Checkstackvar security checks http://blog.csdn.net/masefee/article/details/5630154, pass parameters through ECX and edx, local variables have arrays when used __security_check_cookie returns an address check that uses the __RTC_CHECKESP stack check when the array length is greater than or equal to 5, using the printf function
【. NET Advanced function call--function stack