Function stack frame (analyzed by assembly), function Assembly Analysis

Source: Internet
Author: User

Function stack frame (analyzed by assembly), function Assembly Analysis

I haven't written a blog for a long time. I started my internship at the school and found a very bad place. I took the bus for nearly two hours and went back and forth in a day. I said it was an internship, but it was just like a training, I don't mean any internship at all, spicy chicken.

This time I will explain how to call C ++ functions. After studying C language for so long, I must have heard of stacks (data structures, address space stacks, and so on ), function calls are closely related to stacks.

BecauseThe stack in the address space is grown from a high address to a low address.That isThe address of the back end of the stack is relatively low, and the address at the bottom of the stack is higher than the address at the top of the stack., The following is a test code

 1 #include<stdio.h>                                                                 2  3 #include<stdlib.h> 4  5 void bug() 6 { 7     printf("haha I ma a bug!!"); 8     exit(100); 9 }10 int func(int x, int y)11 {12     int *p = &x;13     p--;14     *p = (int)bug;15     printf("x:%d,y:%d\n", x, y);16     int c = 0xcccc;17     return c;18 }19 20 21 22 int main()23 {24 25     printf("I am main\n");26     int a = 0xaaaa;27     int b = 0xbbbb;28     func(a, b);29     printf("I should run here\n");30     return 0;31 }

The running result of this Code does not execute the second printf of the main function, but runs to the bug function. This is because I modified the return address part of the function stack frame.

It was originally intended to be viewed through the linux system, but the stack frame Implementation of centos7 seems to be somewhat different, and the same code cannot run on centos7.

The following is a Disassembly

 1 int main() 2 { 3 00A118E0  push        ebp   4 00A118E1  mov         ebp,esp   5 00A118E3  sub         esp,0D8h   6 00A118E9  push        ebx   7 00A118EA  push        esi   8 00A118EB  push        edi   9 00A118EC  lea         edi,[ebp-0D8h]  10 00A118F2  mov         ecx,36h  11 00A118F7  mov         eax,0CCCCCCCCh  12 00A118FC  rep stos    dword ptr es:[edi]  13 14     printf("I am main\n");15 00A118FE  push        offset string "I am main\n" (0A16CF0h)  16 00A11903  call        _printf (0A1132Ah)  17 00A11908  add         esp,4  18     int a = 0xaaaa;19 00A1190B  mov         dword ptr [a],0AAAAh  20     int b = 0xbbbb;21 00A11912  mov         dword ptr [b],0BBBBh  22     func(a, b);23 00A11919  mov         eax,dword ptr [b]  24 00A1191C  push        eax  25 00A1191D  mov         ecx,dword ptr [a]  26 00A11920  push        ecx  27 00A11921  call        func (0A11366h)  28 00A11926  add         esp,8  29     printf("I should run here\n");30 00A11929  push        offset string "I should run here\n" (0A16CFCh)  31 00A1192E  call        _printf (0A1132Ah)  32 00A11933  add         esp,4  33     return 0;34 00A11936  xor         eax,eax  35 }

BecauseThe main function itself is really a function! Therefore, before executing the program, the operating system needs to save the current running status, which is similar to function call.

1 00A118E0 push ebp is to press the operating system status to stack

2 00A118E1 mov ebp, esp and move the bottom pointer of the stack to a new position

3 00A118E3 sub esp, 0D8h extends the new stack frame. You cannot always bring the new stack bottom together with the stack top?

The process diagram will be provided when talking about the func function, which is easier to understand. The subsequent push is to save the scene and prepare for execution.

1     printf("I am main\n");2 00A118FE  push        offset string "I am main\n" (0A16CF0h)  3 00A11903  call        _printf (0A1132Ah)  4 00A11908  add         esp,4  

This part is the system call to call printf, because library functions are more of a second call to the Operating System (encapsulation? Because I do not understand this part very well, I will not explain in detail how _ printf's system calls actually work.

    int a = 0xaaaa;00A1190B  mov         dword ptr [a],0AAAAh      int b = 0xbbbb;00A11912  mov         dword ptr [b],0BBBBh  

In the assignment phase, dual characters are given here, So dword assigns values through pointers ~, Ptr is the pointer, and mov dst src is the pointer given to the front, that is, dst = src.

1 func (a, B); 2 00A11919 mov eax, dword ptr [B] 3 00A1191C push eax join the value assignment statement in the previous sentence to form the parameter pressure stack y = b4 00a111_mov ecx, dword ptr [a] 5 00A11920 push ecx combined with the value assignment statement of the previous sentence to form a parameter pressure stack x = a6 00A11921 call func (0A11366h) call function call, call the address of the fun function 7 00A11926 add esp, 8 push so many don't move the top pointer of the stack?

This is the main part of the story. The stack frame during function call! Surprisingly, the passed arguments are placed in the frame of the main function stack. Let's take a look at the compilation of func.

 1 int func(int x, int y) 2 { 3 00A11770  push        ebp   4 00A11771  mov         ebp,esp   5 00A11773  sub         esp,0D8h   6 00A11779  push        ebx   7 00A1177A  push        esi   8 00A1177B  push        edi   9 00A1177C  lea         edi,[ebp-0D8h]  10 00A11782  mov         ecx,36h  11 00A11787  mov         eax,0CCCCCCCCh  12 00A1178C  rep stos    dword ptr es:[edi]  13     int *p = &x;14 00A1178E  lea         eax,[x]  15 00A11791  mov         dword ptr [p],eax  16     p--;17 00A11794  mov         eax,dword ptr [p]  18 00A11797  sub         eax,4  19 00A1179A  mov         dword ptr [p],eax  20     *p = (int)bug;21 00A1179D  mov         eax,dword ptr [p]  22 00A117A0  mov         dword ptr [eax],offset bug (0A1127Bh)  23     printf("x:%d,y:%d\n", x, y);24 00A117A6  mov         eax,dword ptr [y]  25 00A117A9  push        eax  26 00A117AA  mov         ecx,dword ptr [x]  27 00A117AD  push        ecx  28 00A117AE  push        offset string "x:%d,y:%d\n" (0A16B3Ch)  29 00A117B3  call        _printf (0A1132Ah)  30 00A117B8  add         esp,0Ch  31     int c = 0xcccc;32 00A117BB  mov         dword ptr [c],0CCCCh  33     return c;34 00A117C2  mov         eax,dword ptr [c]  35 }
 1 int func(int x, int y) 2 { 3 00A11770  push        ebp   4 00A11771  mov         ebp,esp   5 00A11773  sub         esp,0D8h   6 00A11779  push        ebx   7 00A1177A  push        esi   8 00A1177B  push        edi   9 00A1177C  lea         edi,[ebp-0D8h]  10 00A11782  mov         ecx,36h  11 00A11787  mov         eax,0CCCCCCCCh  12 00A1178C  rep stos    dword ptr es:[edi]  

That's right. This part stores the status of the main function, which registers are saved here are not described in detail (the push command is usually used to save the status). Here, it is better to read the information by step.

In simple terms, this is probably the case of two stack frames.

So it's easy. We don't have to use statements like y = 100 to assign values to y and change the code.

1 int func(int x, int y)2 {3     int *p = &x;4     p++;5     *p = 100;6     printf("x:%d,y:%d\n", x, y);7     int c = 0xcccc;8     return c;9 }

Don't worry! It's not over yet! The compilation is explained!

1 int * p = & x; 2 0009178E lea eax, [x] This is the offset address, Get x for the current ebp offset address 3 00091791 mov dword ptr [p], eax simply assigns a value of 4 p --; 5 00091794 mov eax, dword ptr [p]. He assigns a value back and forth to the register. In fact, the address is reduced by 4 6 00091797 sub eax, 4 7 0009179A mov dword ptr [p], eax 8 * p = (int) bug; 9 0009179D mov eax, dword ptr [p] transfers the address of the Function bug with a value of 10 000917A0 mov dword ptr [eax] and offset bug (09127Bh) offset is also used to take the offset or is it different from lea's 11 printf ("x: % d, y: % d \ n", x, y); 12 000917 A6 mov eax, dword ptr [y] This is not a system call, because I do not know very well 13 000917A9 push eax 14 000917AA mov ecx, dword ptr [x] 15 000917AD push ecx 16 000917AE push offset string "x: % d, y: % d \ n" (096B3Ch) 17 000917B3 call _ printf (09132Ah) 18 000917B8 add esp, 0Ch 19 int c = 0 xcccc; 20 000917BB mov dword ptr [c], 0 CCCCh local variable created under ebp ~ Look at the picture! 21 return c; 22 000917C2 mov eax, dword ptr [c]

The parameter is not displayed, right? There are only two real parameters. Will they be changed after writing? No ~

    x = 10;000A178E  mov         dword ptr [x],0Ah      y = 10;000A1795  mov         dword ptr [y],0Ah  

I changed the code to this and it will change. Here, I didn't change the items in the previously saved registers, so I got a new part.

Dword ptr [x] is no longer an eax or ebx ~

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.