linux的内核实验报告,“linux系统内核分析”实验报告1

"linux系统内核分析"实验报告1

通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的

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

计算机的工作方式:

现代计算机的基本体系结构都是采用冯诺依曼结构,冯诺依曼的设计思想最重要之处是"存储程序"的这个概念。计算机的工作过程,就是执行程序的过程。首先编写需要执行的程序,然后通过输入设备送到存储器保存起来,即程序存储。根据冯诺依曼的设计,计算机应能自动执行程序,而执行程序又归结为逐条执行指令。执行一条指令又可分为以下4个基本操作:取出指令:从存储器某个地址中取出要执行的指令送到CPU内部的指令寄存器暂存。

分析指令:把保存在指令寄存器中的指令送到指令译码器,译出该指令对应的微操作。

执行指令:根据指令译码,向各个部件发出相应控制信号,完成指令规定的各种操作。

为执行下一条指令作好准备,即取出下一条指令地址。

接下来通过一个简单的c程序来分析一下,程序的执行过程

这里是一个非常简单的c程序,源代码如下:

30b29fdebb44929e7a0bb7d947f59076.png

输入:gcc S o main.s main.c m32 来生成汇编代码

整洁一下汇编代码以后,查看汇编代码:

b30a889e8f20673bde362066b0ac110d.png

我在我的虚拟机中的ubuntu系统与实验楼ubuntu系统的汇编代码有点不一样

bae85219729edcea62d31dc0e46de643.png

46b8b112049c38a8f8165295fd2c873d.png

下面通过gdb单步执行来分析栈上寄存器的情况:

首先我们从main函数开始。(前两条语句在gdb执行时设置不了断点,但是执行函数的语句都有这2条,放到其他函数来说明):

在main函数上先设置一个断点,然后运行:

0ed855fdc4c740fb4c6f585c804da8f3.png

此时查看寄存器的值:

f68fffe85adfbe65f8271f16bcb7358a.png

他们的值:esp和ebp都是0xbffff568,eip是0x8048409(正好是下一条要执行的指令的地址)

接下来继续执行:

f6f3eb430e123bf2df95c1661015609d.png

把2压到栈上

59e83d0fd5617dc9e21e76cda3a65f50.png

47089f351e421b2db1320fcd5b6248ad.png

此时,esp的减4了,而ebp不变,eip继续指向下一条指令

下一条要执行call指令,这里再对函数f设置一个断点,继续执行:

cc62e161e19d62560165598dd7753dbd.png

此时,程序跳到函数f中去了

call f

调用函数 f,其实这条指令等价于

pushl %eip

movl $f, %eip

eip的值被保存在esp-4的位置上,保存eip的目的是函数调用返回时能够继续执行call f下面的语句:

35ddf69bbb71e596fe6fee22f21aacda.png

此时,esp的值为0xbffff560,ebp都是0xbffff568

跳转到函数f后,前两条语句和 main 函数相同,都是保存堆栈状态,这里详细来说明一下:

先把ebp的值保存咋esp-4的位置上

341947b6736d999a8160b6d2563569b9.png

再把esp的值赋给sbp,此时esp和ebp的值都为0xbffff55c

18e7c9a3823955bee85c3ecbbcec6c1e.png

然后继续执行,把ebp+8的内容即2这个值压栈:

cded257fa94afefe8e7b8d64d58e7e32.png

此时esp继续-4

b5448c69f837888bdd17d92c54e014aa.png

查看寄存器的值

b5b2cd02d113442b6c02475ae5347c67.png

寄存器的值:esp的值为0xbffff558,ebp的值为0xbffff55c,

接下来要跳转到函数g了,因此再对函数g设置一个断点,然后继续执行:

46951c111d8c2b4db25d5472d835f686.png

观察寄存器的值:

96a20b51b332b715e7a09489948d50df.png

同理:寄存器eip的值继续被保存了在esp-4的位置上,以便能够返回到函数f

5f340f3541e55f56c1587910f0d20f1e.png

进入g函数老的ebp的值也被保存了,新的esp和ebp相同

f4a479991112c1a91c9727029dec1a67.png

此时,esp和ebp的值都是0xbffff550

接下来继续执行,把ebp+8的值给eax

6a93865822aac8cc1288ebfada8c401a.png

查看寄存器,此时esp和ebp的值都是0xbffff550,eax的值是2

01d2c8272ef5526b8735153dbafd2db0.png

继续执行:

5d9acf7075436969ce7adc93e3a773f2.png

把3和eax的值相加结果再保存到eax中

查看寄存器

dd9e3755aabb0651f708fa9c16b8f696.png

寄存器eax的值变成5了,esp和ebp的值都是0xbffff550

然后继续执行:

9c6e1575371d94797cdedc6a0f797d13.png

把esp指向的值给ebp,查看寄存器

bc1032925e09b499f978cf510e39a1e8.png

寄存器的值:esp的值为0xbffff554,ebp的值0xbffff55c,eax还是5

然后继续执行:

f19b8e06439da654df9676d00261a02d.png

指令ret相当于指令popl %eip

5f57bf0fac78d6439e662cb69a715362.png

esp的值为0xbffff558,ebp的值0xbffff55c,eax还是5

这样又返回到函数f继续执行:

2c1c255ed80406a3e2143722bbd39ccd.png

继续执行,然后查看寄存器:

79e2eec0609c67ed2ff9d1350f29a009.png

Esp和ebp的值都是0xbffff55c,eax还是5

继续执行,leave,这条指令相当于下面两条指令:

movl %ebp, %esp

popl %ebp

查看寄存器

3fd29f6e77c632020c6db859a0e62f14.png

esp的值为0xbffff560,ebp的值0xbffff568,eax还是5

继续执行ret,弹出保存的eip的值,返回到main函数执行:

9e1fadd07874ec8e1432c1face9dd649.png

查看寄存器的值,esp的值为0xbffff564,ebp的值0xbffff568,eax还是5

6b14dff5467cb72c0bfab5bd80cf14f5.png

连续执行2步,继续执行

a6afddb22bc5ad700648a9780335fc7e.png

此时eax的值变成了6,esp和ebp的值0xbffff568

1f84da3bcaec4830cfa69d05336299f2.png

然后继续执行2步,main函数就返回了

ec7f1479a7206a0f774bc8e0934ead3b.png

总结

通过分析对应的汇编代码和观察运行栈的变化,加深了对程序执行过程的了解,也明白了计算机的工作方式:根据eip 指指令执行,同时eip自增;

如果执行的是跳转语句时,先把eip压栈,然后将需要跳转的目的地址赋给 eip,实现跳转;

若执行函数调用时,将 eip 压栈,同时将ebp压栈,然后将相应函数地址赋给 eip;

若为其他指令,则继续从 eip 指向的地址取指令执行。

原文:http://lgzkd.blog.51cto.com/936713/1745414

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值