美文网首页
从C语言中的函数调用过程理解计算机执行原理

从C语言中的函数调用过程理解计算机执行原理

作者: 梅花小筑 | 来源:发表于2016-02-28 00:15 被阅读446次

    本文是Mooc <Linxu操作系统分析>课程第一次作业.
    姓名:石维康
    转载请注明出处.
    经过简单的数字修改,需要编译的C语言代码如下:
    int g(int x)
    {
    return x + 2;
    }

    int f(int x)
    {
    return g(x);
    }

    int main(void)
    {
    return f(5) + 4;
    }
    编译后生成的汇编代码如下所示:

    Screen Shot 2016-02-27 at 8.02.50 PM.png

    生成的完整汇编代码如下:

    g:
      pushl   %ebp
      movl    %esp, %ebp
      movl    8(%ebp), %eax
      addl    $2, %eax
      popl    %ebp
      ret
    f:
      pushl   %ebp
      movl    %esp, %ebp
      subl    $4, %esp
      movl    8(%ebp), %eax
      movl    %eax, (%esp)
      call    g
      leave
      ret
    main:
      pushl   %ebp
      movl    %esp, %ebp
      subl    $4, %esp
      movl    $5, (%esp)
      call    f
      addl    $4, %eax
      leave
      ret
    

    完整截图(对应汇编代码函数):

    汇编代码
    
    与视频中采用相同约定,假设初始esp= ebp =0.
    先进入main函数执行到call f后,esp=3,ebp=1,堆栈目前的情况
                  编号   内容
                  | --- | --- |
    ebp           |  1 |   0  |
                  | --- | --- |
                  | --- | --- |
                  |  2  |  5  |
                  | --- | --- |
                  | --- | --- |
    esp           |  3 |   23 |
                  | --- | --- |
                  | --- | --- |
                  |  4 |      |
                  | --- | --- |
    
    
    进入f函数,执行到call g后,堆栈如下
    
    ebp=4
    
    
                  | --- | --- |
                  |  1 |   0  |
                  | --- | --- |
                  | --- | --- |
                  |  2  |  5  |
                  | --- | --- |
                  | --- | --- |
                  |  3 |   23 |
                  | --- | --- |
                  | --- | --- |
     ebp->        |  4 |   1  |
                  | --- | --- |
                  | --- | --- |
                  |  5 |   5  |
                  | --- | --- |
                  | --- | --- |
    esp->         |  6 |   14 |
                  | --- | --- |
    
    
     进入g函数执行运算,执行到addl  $2, %eax 这句. eax=5+2=7
    
    
    
                  | --- | --- |
                  |  1 |   0  |
                  | --- | --- |
                  | --- | --- |
                  |  2  |  5  |
                  | --- | --- |
                  | --- | --- |
                  |  3 |   23 |
                  | --- | --- |
                  | --- | --- |
                  |  4 |   1  |
                  | --- | --- |
                  | --- | --- |
                  |  5 |   5  |
                  | --- | --- |
                  | --- | --- |
                  |  6 |   15 |
                  | --- | --- |
                  | --- | --- |
    esp,ebp->     |  7  |  4  |
                  | --- | --- |
    
    在g函数值中,在eip指向ret语句时(即执行完popl %ebp),堆栈如下:
                  | --- | --- |
                  |  1 |   0  |
                  | --- | --- |
                  | --- | --- |
                  |  2  |  5  |
                  | --- | --- |
                  | --- | --- |
                  |  3 |   23 |
                  | --- | --- |
                  | --- | --- |
    ebp->         |  4 |   1  |
                  | --- | --- |
                  | --- | --- |
                  |  5 |   5  |
                  | --- | --- |
                  | --- | --- |
    esp->         |  6 |   15 |
                  | --- | --- |
    
    ret 后 eip=15,堆栈变成如下:
    
                  | --- | --- |
                  |  1 |   0  |
                  | --- | --- |
                  | --- | --- |
                  |  2  |  5  |
                  | --- | --- |
                  | --- | --- |
                  |  3 |   23 |
                  | --- | --- |
                  | --- | --- |
    ebp->         |  4 |   1  |
                  | --- | --- |
                  | --- | --- |
    esp->         |  5 |   5  |
                  | --- | --- |
    
    f中的leave执行完之后:
    
                  | --- | --- |
    ebp->         |  1 |   0  |
                  | --- | --- |
                  | --- | --- |
                  |  2  |  5  |
                  | --- | --- |
                  | --- | --- |
    esp->         |  3 |   23 |
                  | --- | --- |
    
    执行f中的ret后,eip=23,eax=7:
                  | --- | --- |
    ebp->         |  1 |   0  |
                  | --- | --- |
                  | --- | --- |
    esp->         |  2  |  5  |
                  | --- | --- |
    执行main中的leave后,堆栈如下,eax=11,esp=ebp=0:
    ebp,esp->     | --- | --- |
                  |  1 |   0  |
                  | --- | --- |
    
    回到初始态.
    

    我对计算机执行程序的理解:
    计算机只是机械的从PC指针指向的位置取指令并解析执行.而数据与指令都是以二进制形式进行存储.
    在C语言层面上的函数调用与返回的语义,在x86层面上是通过call指令与ret指令来完成.

    相关文章

      网友评论

          本文标题:从C语言中的函数调用过程理解计算机执行原理

          本文链接:https://www.haomeiwen.com/subject/xoiwkttx.html