Linux内核分析:实验一

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

计算机体系结构与程序运行过程

现代计算机大都采用的是“冯.诺依曼”体系结构,它的核心思想是:程序存储,指令和数据不加区分的放在一个存储器中。由指令指针寄存器保存着下一条将要执行指令的地址,这个寄存器在32位系统中叫eip,64位系统中叫rip。

指令是用二进制编码的,难于记忆。为了更有效的编写程序,人们就发明了汇编语言,它是对二进制指令的一种简单映射。平常我们所写的程序都需要编译成二进制,才能被机器执行。我们可以通过反汇编一个C程序,了解程序运行的过程。

反汇编C程序

实验1给出的源码很简单,如下所示:

int g( int x )
{
  return x + 3;
}

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

int main(void)
{
  return f(8) + 1;
}

我们可以使用如下命令

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

得到这个C程序的汇编码:

g函数
f函数
main函数

-S :表示仅汇编
-m32 :表示生成32位的指令格式

当我们得到一个已经编译好的C程序时,在Linux下可以使用objdump工具得到这个程序的反汇编指令。

汇编指令分析

函数的开始

可以观察到每个函数的开始部分,都有这2条指令

pushl %ebp
movl %esp, %ebp
subl $4, %esp

第一条指令是把旧的ebp保存下来,放在栈中。这是为了当函数结束时,能恢复到调用这个函数之前的栈空间。

第二条指令是将当前栈顶指针的位置保存到ebp中,因为函数的参数以及函数内部的局部变量,一般都根据ebp作为基址寻址的。

第三条指令是开辟栈空间,

函数体部分

因为实验给的源代码很简单,所以汇编指令很少。在f函数内部有一下三条指令

movl 8(%ebp), %eax
movl %eax, (%esp)
call g

第一条指令因为栈是向下增长的,8(%ebp)根据栈调用惯例,它表示f函数的第一个参数,即x。

第二条指令它以eax寄存器作为媒介,把它的值放在%esp中,也是函数g的参数。

第三条指令表示调用g函数

根据栈的使用惯例,假如fun有4个参数,如下:

void fun( int a, int b, int c, int d );

当调用fun函数的时候,会先开辟16字节空间,如下:

subl $0x10, %esp

分别将a,b,c,d的值放到这个空间里,然后将它们压栈

pushl 0x0c(%esp)  ; 这是 d 的值
pushl 0x08(%esp)  ; 这是 c 的值
pushl 0x04(%esp)  ; 这是 b 的值
pushl (%esp)      ; 这是 a 的值

函数的参数是从最后一个参数开始压栈的,第一个参数放在(%esp)中,倒数第二个参数放在4(%esp)…

函数的结束

从反汇编指令可以看出,函数的结束部分的指令为:

leave
ret

其中leave 是封装之后的指令,其实它是由两条指令组成的

movl %ebp, %esp
popl %ebp

这两句话是恢复调用这个函数之前的栈空间,因为为了调用函数f,我们在栈中开辟了空间,修改了ebp、esp等。

最后ret 指令是把函数的返回地址放到eip中,使得在执行完函数f后,程序能继续执行下去。

总结

通过分析C程序的反汇编代码,对程序在计算内部的执行过程有了一个直观的认识,在函数调用中,栈起了举足轻重的作用,很多计算机安全方面的漏洞都直接间接的利用了栈。

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值