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. .gitignore过滤个人配置

    git还是一个很好使用的版本工具.所以用eclipse做自己的小玩意儿,在多台电脑之间同步的时候我经常会使用它.. 但是有个问题..不同电脑的eclipse的个人配置稍微有那么一点点的不同..比如有几 ...

  2. 【04-10】java中的路径

    java中的路径 System.getProperty("user.dir")  获取工程的绝对路径 Class.class.getClass().getResource(&quo ...

  3. 浅谈Java中的equals和==(转)

    浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str ...

  4. linux下安装postgresql

    环境:Linux localhost.localdomain 2.6.32-431 GNU/Linux x86_64 Postgresql版本:postgresql.9.5.3 添加开启自启设置:ht ...

  5. 关于MapReduce中自定义分组类(三)

    Job类  /**    * Define the comparator that controls which keys are grouped together    * for a single ...

  6. [Machine Learning & Algorithm] 神经网络基础

    目前,深度学习(Deep Learning,简称DL)在算法领域可谓是大红大紫,现在不只是互联网.人工智能,生活中的各大领域都能反映出深度学习引领的巨大变革.要学习深度学习,那么首先要熟悉神经网络(N ...

  7. CP

    cp:copy files and directories,如果要拷贝目录,则使用-a或者-r参数,则能够拷贝目录, 如果源文件是多个,那目标文件在最后,且是目录. Cp [-aifpru] [源文件 ...

  8. css text-overflow:ellipsis 文字多余剪切

    text-overflow: ellipsis;多度剪切white-space: nowrap;禁止换行overflow: hidden;多余隐藏

  9. git error: unable to rewind rpc post data - try increasing http.postBuffer

    error: unable to rewind rpc post data - try increasing http.postBuffererror: RPC failed; curl 56 Rec ...

  10. JSPatch热更新的利器.

    如果用一句话来描述JSPatch,就是利用系统自带的JavaScriptCore.framework配合RunTime机制,进行实时的代码下载与运行.. 而且使用也很简单,启动,加载JS,运行... ...