网易云课堂 Linux内核分析(一)

寇亚飞 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

实验内容

反汇编一个C语言小程序

实验的c代码 main.c:

int g(int x)
{
      return x + 5;
}
int f(int x)
{
      return g(x);
}
int main(void)
{
      return f(9) + 1;
}

使用如下命令编译成汇编代码:

gcc –S –o main.s main.c -m32

编译得到的汇编代码 main.s(去除.开头的链接行):


g:
1   pushl   %ebp
2   movl    %esp, %ebp
3   movl    8(%ebp), %eax
4   addl    $5, %eax
5   popl    %ebp
6   ret
f:
7   pushl   %ebp
8   movl    %esp, %ebp
9   subl    $4, %esp
10  movl    8(%ebp), %eax
11  movl    %eax, (%esp)
12  call    g
13  leave
14  ret
main:
15  pushl   %ebp
16      movl    %esp, %ebp
17  subl    $4, %esp
18  movl    $9, (%esp)
19  call    f
20  addl    $1, %eax
21  leave
22  ret

main.c的执行过程非常简单,程序从主函数main()开始执行,调用函数f(),在函数f()中,又调用了函数g()。
但计算机底层是如何实现的呢?
其实,学过计算机的话对计算机中的堆栈肯定不陌生,而在计算机中,上边的c语言程序就是通过堆栈实现的。下边来具体分析一下。
首先介绍一下cpu中的寄存器。
cpu中的寄存器是用来暂存指令,数据和地址。在x86指令集计算机中,寄存器按照用途可分为通用寄存器,指令指针,标志寄存器和段寄存器。通用寄存器又可分为数据寄存器,指针寄存器和变址寄存器。具体的内容可以参考维基百科
这里主要说一下上述代码中用到的寄存器。
ebp:堆栈基址指针寄存器(e代表32位):用来存放栈基址
esp:堆栈指针 :栈顶指针
eax:累加器 :可以存放立即数等执行结果
eip:指令指针 :用来指示下一条执行指令

知道了寄存器的作用,可以来分析汇编代码。首先看main函数,此时eip指向main函数中的第一条指令15,它的作用是将先将esp减4,即向下移动一个位置(栈是向下增长,假设此时为位置1),然后将ebp压入栈中。这个过程执行后eip自动指向下一条指令16,这条指令就是将ebp指向esp的位置(即为1),然后eip继续指向下一条指令17,将esp减4,即向下移动一个位置到2,接着eip指向指令18, 将数字9放入esp所指向的地址中,接下来的call指令作用是实现函数调用,即跳转,它实现了两个过程,第一个过程是将eip压栈(保存在main()函数里的执行位置),此时eip指向call指令的下一条指令,即20,esp下移到位置3,将eip20压入栈中。然后第二个过程是将f的位置放入eip中,即实现了跳转,因为程序的执行顺序都是靠eip指示的。这样程序就开始执行函数f()中的指令,这就和上述过程类似了,就不多罗嗦了。讲一下返回,pop xx 出栈指令,即将栈顶内容,也就是esp指向的内容赋予xx;leave指令就相当于执行了movl %ebp,%esp popl%ebp两条指令;ret 指令就相当于popl eip 指令,即当被调用函数执行到返回时,回到调用函数保存的eip位置。程序的结果都保存在eax中。
具体过程如下图:


学完本次课程,使我对计算机程序的执行有了更深的了解,也对堆栈有了更深的了解。它体现了存储式计算机的思想,也体现了顺序执行的特点。当程序遇到跳转时,只需要将当前的执行情况保存在栈中,便可跳转执行另一段指令,充分利用了堆栈的特性,这也让我体会到过多的函数调用可能带来的弊端,毕竟如果调用过多,则栈便会越来越深,内存就会吃不消了!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值