本作业的网站链接:MIT 6.828 Homework 1: boot xv6

问题

Exercise: What is on the stack?

While stopped at the above breakpoint, look at the registers and the stack contents:

(gdb) info reg

...

(gdb) x/24x $esp

...

(gdb)

Write a short (3-5 word) comment next to each non-zero value on the stack explaining what it is. Which part of the stack printout is actually the stack?

Here are some questions to help you along:

  • Begin by restarting qemu and gdb, and set a break-point at 0x7c00, the start of the boot block (bootasm.S). Single step through the instructions (type si at the gdb prompt). Where in bootasm.S is the stack pointer initialized? (Single step until you see an instruction that moves a value into %esp, the register for the stack pointer.)
  • Single step through the call to bootmain; what is on the stack now?
  • What do the first assembly instructions of bootmain do to the stack? Look for bootmain in bootblock.asm.
  • Continue tracing via gdb (using breakpoints if necessary -- see hint below) and look for the call that changes eip to 0x10000c. What does that call do to the stack? (Hint: Think about what this call is trying to accomplish in the boot sequence and try to identify this point in bootmain.c, and the corresponding instruction in the bootmain code in bootblock.asm. This might help you set suitable breakpoints to speed things up.)

解答

本题目要求解释内核启动时栈中的数据。由于PC启动顺序是BIOS -> boot loader -> kernel,要想知道内核启动时栈中数据的来源,需要知道前面BIOS和boot loader如何使用栈。因此,下面先解答文中提出的早期BIOS和boot loader启动的问题,再来解释内核启动时栈中的数据。

问题1:栈指针的初始值是什么?

在地址0x7c00处设置断点,使用c命令运行至此,然后使用si命令执行一步,最后查看寄存器信息,结果如下所示。可知栈指针的初始值为0x6f20,并且地址0x6f20存的数据为0xf000d239.

(gdb) b *0x7c00
Breakpoint 1 at 0x7c00
(gdb) c
Continuing.
[ 0:7c00] => 0x7c00: cli Thread 1 hit Breakpoint 1, 0x00007c00 in ?? ()
(gdb) si
[ 0:7c01] => 0x7c01: xor %ax,%ax
0x00007c01 in ?? ()
(gdb) info reg
eax 0xaa55 43605
ecx 0x0 0
edx 0x80 128
ebx 0x0 0
esp 0x6f20 0x6f20
ebp 0x0 0x0
esi 0x0 0
edi 0x0 0
eip 0x7c01 0x7c01
eflags 0x2 [ ]
cs 0x0 0
ss 0x0 0
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
(gdb) x/xw 0x6f20
0x6f20: 0xf000d239

问题2:当调用bootmain时栈中数据是什么?

单步执行到call bootmain处,发现esp寄存器的值为0x7c00,也就是boot block的起始地址。当执行完call指令后,esp寄存器的值变为0x7bfc,call指令的下一条指令的地址,也是bootmain函数的返回地址。

(gdb) si
=> 0x7c43: mov $0x7c00,%esp
0x00007c43 in ?? ()
1: /x $ebp = 0x0
2: /x $esp = 0x6f20
(gdb) si
=> 0x7c48: call 0x7d3b
0x00007c48 in ?? ()
1: /x $ebp = 0x0
2: /x $esp = 0x7c00
(gdb) si
=> 0x7d3b: push %ebp Thread 1 hit Breakpoint 2, 0x00007d3b in ?? ()
1: /x $ebp = 0x0
2: /x $esp = 0x7bfc

问题3:bootmain的第一条指令做了什么?

从bootblock.asm文件可以看到bootmain的第一条指令将ebp寄存器的值压栈。

    7d3b:	55                   	push   %ebp

这导致esp寄存器的值减4,由0x7bfc变为0x7bf8,而栈顶存储的元素也就是ebp寄存器的值,亦即为0.

问题4:那个修改eip的值为0x10000c的call语句对栈做了什么?

修改eip的值为0x10000c的语句是call *0x10018,其中地址0x10018处存储的内容为0x10000c,所以此语句做的事情是:先将返回地址0x7d8d压栈,然后跳到0x10000c的位置。

问题5:解释内核启动时栈中的数据

按照题目要求,执行gdb后,在地址0x0010000c处设置断点。然后

  1. 查看寄存器信息
(gdb) info reg
eax 0x0 0
ecx 0x0 0
edx 0x1f0 496
ebx 0x10074 65652
esp 0x7bdc 0x7bdc
ebp 0x7bf8 0x7bf8
esi 0x10074 65652
edi 0x0 0
eip 0x10000c 0x10000c
eflags 0x46 [ PF ZF ]
cs 0x8 8
ss 0x10 16
ds 0x10 16
es 0x10 16
fs 0x0 0
gs 0x0 0
  1. 查看栈中数据
(gdb) x/24x $esp
0x7bdc: 0x00007d8d 0x00000000 0x00000000 0x00000000
0x7bec: 0x00000000 0x00000000 0x00000000 0x00000000
0x7bfc: 0x00007c4d 0x8ec031fa 0x8ec08ed8 0xa864e4d0
0x7c0c: 0xb0fa7502 0xe464e6d1 0x7502a864 0xe6dfb0fa
0x7c1c: 0x16010f60 0x200f7c78 0xc88366c0 0xc0220f01
0x7c2c: 0x087c31ea 0x10b86600 0x8ed88e00 0x66d08ec0
  1. 解释栈中数据

    注意,栈实际上从0x7c00向下增长,大于0x7c00的地址存储的是BIOS和boot loader的代码。
0x7bdc:	0x00007d8d	// function return address after calling kernel
0x7be0: 0x00000000 // reserved value
0x7be4: 0x00000000 // reserved value
0x7be8: 0x00000000 // reserved value
0x7bec: 0x00000000 // reserved value
0x7bf0: 0x00000000 // ebx's value when calling bootmain
0x7bf4: 0x00000000 // esi's value when calling bootmain
0x7bf8: 0x00000000 // edi's value when calling bootmain
0x7bfc: 0x00007c4d // function return address after calling bootmain
0x7c00: 0x8ec031fa // cli (The following is instructions of bootblock)
0x7c04: 0x8ec08ed8
0x7c08: 0xa864e4d0
0x7c0c: 0xb0fa7502
0x7c10: 0xe464e6d1
0x7c14: 0x7502a864
0x7c18: 0xe6dfb0fa
0x7c1c: 0x16010f60
0x7c20: 0x200f7c78
0x7c24: 0xc88366c0
0x7c28: 0xc0220f01
0x7c2c: 0x087c31ea
0x7c30: 0x10b86600
0x7c34: 0x8ed88e00
0x7c38: 0x66d08ec0

备注

  1. 第一次执行gdb时,没能运行到.gdbinit文件,有以下打印信息:
warning: File "/home/along/src/6.828/src/xv6-public/.gdbinit" auto-loading has been declined by your `auto-load safe-path' set to "$debugdir:$datadir/auto-load".
To enable execution of this file add
add-auto-load-safe-path /home/along/src/6.828/src/xv6-public/.gdbinit
line to your configuration file "/home/along/.gdbinit".

按照提示,在/home/along/.gdbinit文件中增加以上语句后,再运行gdb就正常了。

《MIT 6.828 Homework 1: boot xv6》解题报告的更多相关文章

  1. 《MIT 6.828 Homework 2: Shell》解题报告

    Homework 2的网站链接:MIT 6.828 Homework 2: shell 题目 下载sh.c文件,在文件中添加相应代码,以支持以下关于shell的功能: 实现简单shell命令,比如ca ...

  2. 《MIT 6.828 Lab1: Booting a PC》实验报告

    <MIT 6.828 Lab1: Booting a PC>实验报告 本实验的网站链接见:Lab 1: Booting a PC. 实验内容 熟悉x86汇编语言.QEMU x86仿真器.P ...

  3. 《MIT 6.828 Lab 1 Exercise 12》实验报告

    本实验的网站链接:MIT 6.828 Lab 1 Exercise 12. 题目 Exercise 12. Modify your stack backtrace function to displa ...

  4. 《MIT 6.828 Lab 1 Exercise 11》实验报告

    本实验的网站链接:MIT 6.828 Lab 1 Exercise 11. 题目 The above exercise should give you the information you need ...

  5. 《MIT 6.828 Lab 1 Exercise 10》实验报告

    本实验的网站链接:MIT 6.828 Lab 1 Exercise 10. 题目 Exercise 10. To become familiar with the C calling conventi ...

  6. 《MIT 6.828 Lab 1 Exercise 8》实验报告

    本实验的网站链接:MIT 6.828 Lab 1 Exercise 8. 题目 Exercise 8. Read through kern/printf.c, lib/printfmt.c, and ...

  7. 《MIT 6.828 Lab 1 Exercise 7》实验报告

    本实验链接:mit 6.828 lab1 Exercise 7. 题目 Exercise 7. Use QEMU and GDB to trace into the JOS kernel and st ...

  8. 《MIT 6.828 Lab 1 Exercise 4》实验报告

    本实验链接:mit 6.828 lab1 Exercise 4. 题目 Exercise 4. Read about programming with pointers in C. The best ...

  9. 《MIT 6.828 Lab 1 Exercise 3》实验报告

    本实验的网站链接:mit 6.828 lab1 Exercise 3. 题目 Exercise 3. Take a look at the lab tools guide, especially th ...

随机推荐

  1. 022_STM32中断优先级分组解析

    (0)STM32有十六个优先级 (一)STM32分组为:组0-4 (二)分组配置在寄存器SCB->AIRCR中: (三)解析第二点 1. 组0就是4位都用来设置成响应优先级,2^4=16位都是响 ...

  2. ueditor自动上传Word中的图片

    如何做到 ueditor批量自动上传word图片? 1.前端引用代码 <!DOCTYPEhtmlPUBLIC"-//W3C//DTD XHTML 1.0 Transitional//E ...

  3. 正则regex

    Regual expression 普通正常字符 字符匹配 . 表示任意字符 匹配次数 位置锚定 分组及引用

  4. Java集合总结(三):堆与优先级队列

    堆 满二叉树:满二叉树是指,除了最后一层外,每个节点都有两个孩子,而最后一层都是叶子节点,都没有孩子. 完全二叉树:完全二叉树不要求最后一层是满的,但如果不满,则要求所有节点必须集中在最左边,从左到右 ...

  5. rxjs入门指南

    使用场景 在复杂的,频繁的异步请求场景,使用rxjs. 在依赖的多个异步数据,决定渲染的情景,使用rxjs. 总之:在前台频繁的.大量的.和后台数据交互的复杂项目里面,使用rxjs(web端,iOS, ...

  6. array_merge与array+array的区别

    结果:

  7. Cash Machine (POJ 1276)(多重背包——二进制优化)

    链接:POJ - 1276 题意:给你一个最大金额m,现在有n种类型的纸票,这些纸票的个数各不相同,问能够用这些纸票再不超过m的前提下凑成最大的金额是多少? 题解:写了01背包直接暴力,结果T了,时间 ...

  8. devstack cinder-volume服务状态为down

    cinder-manage service list 查看到有一个 xxx状态 Binary Host Zone Status State Updated At RPC Version Object ...

  9. Python2.7编码问题:UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position...解决方法

    解决方法: 在Python程序最前面加上以下语句: import sys reload(sys) sys.setdefaultencoding('utf-8')

  10. yquery-操作样式属性

    前几天回家,参加了全国的成人高考,都说学历是找工作的敲门砖,其实一点都不假,尤其是现在的社会竞争力那么强,你不学就会被淘汰.像要过自己想要的生活,就必须努力学习,努力赚钱,买自己想买的,过自己想过的. ...