Lab 1 Exercise 10

  为了能够更好的了解在x86上的C程序调用过程的细节,我们首先找到在obj/kern/kern.asm中test_backtrace子程序的地址, 设置断点,并且探讨一下在内核启动后,这个程序被调用时发生了什么。对于这个循环嵌套调用的程序test_backtrace,它一共压入了多少信息到堆栈之中。并且它们都代表什么含义?

答:

  先找到这个子程序的地址,打开obj/kern/kern.asm。在这个文件中我们查到调用test_backtrace子程序指令的地址为0xf0100040.

  所以我们在这里设置断点,并且开始调试。

  首先看一下test_backtrace的C语言形式:

void
test_backtrace(int x)
{
cprintf("entering test_backtrace %d\n", x);
if (x > )
test_backtrace(x-);
else
mon_backtrace(, , );
cprintf("leaving test_backtrace %d\n", x);
}

    可见这个子程序是一个循环调用,在每一层循环中先打印信息 "entering test_backtrace x",然后对test_backtrace进行循环调用。当被循环调用完成,再打印信息 "leaving test_backtrace x"。所以最先进入的程序会最后退出。由于在init中对这个函数调用的次数为设置为5,所以屏幕上会打印出下列信息。

  

  下面具体看一些每次调用所执行的汇编程序,当每一次进入test_backtrace后,刚刚开始时,它要完成之前介绍过的过程调用的通用操作,如下:

     push %ebp
mov %esp, %ebp
push %ebx
sub $0x14, %esp

  这四个操作将被用于存放调用这个子程序的父程序的栈帧信息,以及为当前子程序分配新的栈帧。在Exercise 1.9中,我们已经讨论过,entry.S文件中为整个内核设置了堆栈空间的地址范围,从0xf0108000-0xf0110000。由于堆栈是向下增长的,所以在运行init函数之前,esp寄存器的值就是0xf0110000,代表堆栈尚未使用。进入i386_init函数后,如果要调用某个子程序,就会把 i386_init 程序的栈帧信息压入到这个堆栈空间中。

  在 i386_init 函数中,运行了子程序test_backtrace(5)。

  当运行test_backtrace(5)之前,esp寄存器ebp寄存器的值分别为如下:

    esp : 0xf010ffe0    ebp : 0xf010fff8

  0xf010ffe0~0xf010fff8就是当前i386_init子程序的栈帧,当计算机要调用test_backtrace(5)程序时,

  首先call指令把i386_init的返回地址压入堆栈中,所以esp变为0xf010ffdc,然后进入test_backtrace(5)子程序。

  子程序中第一句push %ebp,把i386_init的ebp寄存器的值压入堆栈中,即地址0xf010ffd8处,此时esp的值变为0xf010ffd8。

  然后 mov %esp, %ebp 把ebp的值更新为esp的值,0xf010ffd8。这个就是当前test子程序的ebp寄存器的值。即它的栈帧的高地址边界。

  然后 push %ebx 把ebx寄存器的值压入堆栈,此时esp变为0xf010ffd4。因为%ebx寄存器可能被这个子程序所使用,所以必须把它之前的值保留。

  然后 sub $0x14, %esp 把esp中的值减去0x14=20,esp的值变为0xf010ffc0。这就是给test子程序分配一个大小为20个存储单元的额外的栈帧空间,供它存储一些临时变量的值。

  所以上述4条汇编指令,执行完成后,esp,ebp寄存器的值变化为

    esp : 0xf010ffc0     ebp:0xf010ffd8

  这就是test_backtrace(5)子程序运行时的栈帧地址范围。而输入参数'5'的值存放在0xf010ffe0单元处。

  

  紧接着就是调用test_backtrace(4),由于它和test_backtrace(5)是一样的,只不过现在是在test_backtrace(5)中调用test_backtrace(4),所以调用后内存中会同时存在二者的栈帧,test_backtrace(4)的栈帧就在test_backtrace(5)的栈帧之后。test_backtrace(4)中 esp, ebp的值也可以像我们分析test_backtrace(5)一样被分析出来,如下:

     esp:0xf010ffa0    ebp:0xf010ffb8

  同理test_backtrace(3)中:

     esp:0xf010ff80   ebp:0xf010ff98

  test_backtrace(2)中:

    esp:0xf010ff60   ebp:0xf010ff78

  test_backtrace(1)中:

    esp:0xf010ff40   ebp:0xf010ff58

  test_backtrace(0)中:

      esp:0xf010ff20   ebp:0xf010ff38   

  对于任意一层调用,比如test_backtrace(i),它的esp和ebp的值假设分别为esp(i)和ebp(i)。那么在这个栈帧范围内主要存在这么几个重要的值:

  首先ebp(i)所指向的内存单元处存放着上一层程序的ebp寄存器的值,即ebp(i-1)。

  另外在esp(i)所指向的内存单元处存放着对下一层子程序调用时传入的参数,即i+1

  

MIT 6.828 JOS学习笔记13 Exercise 1.10的更多相关文章

  1. MIT 6.828 JOS学习笔记11 Exercise 1.8

    Exercise 1.8       我们丢弃了一小部分代码---即当我们在printf中指定输出"%o"格式的字符串,即八进制格式的代码.尝试去完成这部分程序. 解答: 在这个练 ...

  2. MIT 6.828 JOS学习笔记5. Exercise 1.3

    Lab 1 Exercise 3 设置一个断点在地址0x7c00处,这是boot sector被加载的位置.然后让程序继续运行直到这个断点.跟踪/boot/boot.S文件的每一条指令,同时使用boo ...

  3. MIT 6.828 JOS学习笔记12 Exercise 1.9

    Lab 1中Exercise 9的解答报告 Exercise 1.9: 判断一下操作系统内核是从哪条指令开始初始化它的堆栈空间的,以及这个堆栈坐落在内存的哪个地方?内核是如何给它的堆栈保留一块内存空间 ...

  4. MIT 6.828 JOS学习笔记8. Exercise 1.4

    Lab 1 Exercise 4 阅读关于C语言的指针部分的知识.最好的参考书自然是"The C Programming Language". 阅读5.1到5.5节.然后下载poi ...

  5. MIT 6.828 JOS学习笔记9. Exercise 1.5

    Lab 1 Exercise 5 再一次追踪一下boot loader的一开始的几句指令,找到第一条满足如下条件的指令处: 当我修改了boot loader的链接地址,这个指令就会出现错误. 找到这样 ...

  6. MIT 6.828 JOS学习笔记3. Exercise 1.2

    这篇博文是对Lab 1中的Exercise 2的解答~ Lab 1 Exercise 2: 使用GDB的'si'命令,去追踪ROM BIOS几条指令,并且试图去猜测,它是在做什么.但是不需要把每个细节 ...

  7. MIT 6.828 JOS学习笔记2. Lab 1 Part 1.2: PC bootstrap

    Lab 1 Part 1: PC bootstrap 我们继续~ PC机的物理地址空间 这一节我们将深入的探究到底PC是如何启动的.首先我们看一下通常一个PC的物理地址空间是如何布局的:        ...

  8. MIT 6.828 JOS学习笔记0. 写在前面的话

    0. 简介 操作系统是计算机科学中十分重要的一门基础学科,是一名计算机专业毕业生必须要具备的基础知识.但是在学习这门课时,如果仅仅把目光停留在课本上一些关于操作系统概念上的叙述,并不能对操作系统有着深 ...

  9. MIT 6.828 JOS学习笔记17. Lab 3.1 Part A User Environments

    Introduction 在这个实验中,我们将实现操作系统的一些基本功能,来实现用户环境下的进程的正常运行.你将会加强JOS内核的功能,为它增添一些重要的数据结构,用来记录用户进程环境的一些信息:创建 ...

随机推荐

  1. 关于ie版本判断

    //see: http://tanalin.com/en/articles/ie-version-js/ var browser = function(){ var isIE=!!window.Act ...

  2. html 杂记

    <link rel="******"  href=“****.css” type=“text/css”  media=“screen” />css样式外部链接 加个斜杠 ...

  3. 执行mvn 报错 source-1.5 中不支持 diamond运算符

    编译版本出现了问题 <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> < ...

  4. <section> 标签

    最近正在学习html5,刚接触html5,感觉有点不适应,因为有一些标签改变了,特别是div, section article这三个标签,查了一些资料,也试着用html5和css3布局网页,稍微有点头 ...

  5. C++ 与OpenCV 学习笔记

    联合体:当多个数据需要共享内存或者多个数据每次只取其一时,可以利用联合体(union) 1. 联合体是一种结构: 2. 他的所有成员相对于基地址的偏移量均为0: 3. 此结构空间要大到足够容纳最&qu ...

  6. EXCEL 2010学习笔记 —— VLOOKUP函数 嵌套 MATCH 函数

    match index vlookup 等函数都是查找引用类函数,需要查找的时候关键变量只有两个,区域+位置,区域的选择注意是否需要锁定,位置的确定可以通过输入特定的行号和列号. match() ma ...

  7. php的memcache安装,在window10下面

    1.memcached-win对应得安装包 2.解压,可以放到任意目录,以管理员身份打开cmd 3.在安装的目录下面,执行如下命令 memcached.exe -d install 安装 Memcac ...

  8. django test

    django的单元测试 官方文档:https://docs.djangoproject.com/en/dev/topics/testing/ 相对于自己封装urllib/urllib2/request ...

  9. Koa2 的安装运行记录(二)

    参考 :koa2-boilerplate    https://github.com/superalsrk/koa2-boilerplate Ajax Login and Ajax Logout in ...

  10. DevExpress 关于alertControl 改变其大小

    private void alertControl1_FormLoad(object sender, DevExpress.XtraBars.Alerter.AlertFormLoadEventArg ...