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. Java 解决约瑟夫问题

    约瑟夫问题(有时也称为约瑟夫斯置换,是一个出现在计算机科学和数学中的问题.在计算机编程的算法中,类似问题又称为约瑟夫环.又称“丢手绢问题”.) 有这样一个故事,15个教徒和15个非教徒在深海遇险必须讲 ...

  2. windows XP 神key

    微软内部泄露的XP的CD-KEY和无限次激活码!亲测!!! Windows XP专业版最新注册码HTXH6-2JJC4-CDB6C-X38B4-C3GF3RT4H2-8WYHG-QKK6K-WWHJ2 ...

  3. Android Studio Error:CreateProcess error=216

    Error:CreateProcess error=216, This version of %1 is not compatible with the version of Windows you' ...

  4. gitlab使用个人版v16.11

    title: gitlab使用个人版v16.11 date: 2016-11-13 20:53:00 tags: [gitlab] --- 1.安装gitbash 附上地址链接:git 2.配置git ...

  5. 新型的Hbb项目目录结构

    - Hbb - ComponentPacket (底层组件包) 数据库组件 网络组件 格式化组件 - Resources (存放所有图片资源文件) - ToolClass (工具类/Helper 独立 ...

  6. 使用VS2010编译Qt 5.6.1过程记录

    由于Qt官方发布的Qt 5.6.1二进制安装包没有对应VS2010版本的,而我的电脑上只安装了VS2010,因此只能自己编译. 本文记录本人的编译安装过程,以及其中遇到的一些问题. 本文使用VS201 ...

  7. Ubuntu14.04 64位配置Caffe 教程(基于CUDA7.5)

    最新博客地址已转到: http://blog.csdn.net/zzlyw?viewmode=contents   ------------------------------------------ ...

  8. leetcode一些常用函数

    6移位操作 “>> 右移,高位补符号位” 这里右移一位表示除2“>>> 无符号右移,高位补0”: 与>>类似“<< 左移” 左移一位表示乘2,二位 ...

  9. 设计模式--建造者模式Builder(创建型)

    一.首先看建造者模式的UML图: 二.再来看一个建造者模式的例子 class Builder { public: virtual void BuildHead() {} virtual void Bu ...

  10. gnu coreutils-8.25 for win32 static - Beta

    gnu.win32-coreutils-8.25.7z 2.7 Mb bc-1.06.tar.gz coreutils-8.25.tar.xz diffutils-3.5.tar.xz gawk-4. ...