MIT6.828LAB1 (5)

LAB1_Part3 The Kernel


前言

记录一下自己的学习过程
实验内容翻译:
https://gitee.com/cherrydance/mit6.828
该翻译仅供参考

练习7

使用QEMU和GDB跟踪进入JOS内核,并停在movl %eax, %cr0指令处。检查内存地址0x00100000和0xf0100000的内容。现在,使用GDB的stepi命令单步执行该指令。再次检查内存地址0x00100000和0xf0100000的内容。确保你理解刚刚发生的事情。
如果没有建立映射,新映射建立后的第一条指令将无法正常工作是什么?在kern/entry.S中将movl %eax, %cr0注释掉,跟踪进入它,看看你是否正确。

运行结果如图所示:在这里插入图片描述

可以看到,mov %eax,%cr0执行后两块地址的内容相同,这是因为地址映射。在将该指令注释之后重新运行发现在执行jmp *%eax之后出错, 出错结果如下图:
不要忘记在之后将代码修改回来。
在这里插入图片描述

练习8

我们省略了一小段代码——用于以"%o"格式打印八进制数的代码。请找到并填写这段代码片段。

我们还是先看问题

1.解释一下printf.c和console.c之间的接口。具体来说,console.c导出了哪个函数?这个函数是如何被printf.c使用的?

首先看printf.c,因为它只有三个函数,脉络清晰。即cprintf调用vcprintf,而putch看上去与这两个函数无关,我们直接进入vcprintf,往深处探索。结果如图:
在这里插入图片描述
printf.c使用console.c的cputchar()函数。

2.解释一下console.c中的以下内容。
if (crt_pos >= CRT_SIZE) {
int i;
memmove(crt_buf, crt_buf + CRT_COLS, (CRT_SIZE - CRT_COLS) * sizeof(uint16_t));
for (i = CRT_SIZE - CRT_COLS; i < CRT_SIZE; i++)
crt_buf[i] = 0x0700 | ’ ';
crt_pos -= CRT_COLS;
}

CRT_SIZE=25*80,这是一页所能显示的字符数量,如果crt_pos>=CRT_SIZE,说明当前已经显示满了,需要将最下面一行腾出来,因此会复制前1-24行到0-23的位置,将最后一行清空以便显示新的字符。

3.对于以下问题,你可能希望参考第二讲的笔记。这些笔记涵盖了x86上GCC的调用约定。
逐步跟踪以下代码的执行:
int x = 1, y = 3, z = 4;
cprintf(“x %d, y %x, z %d\n”, x, y, z);
在对cprintf()的调用中,fmt指向什么?ap指向什么?
按执行顺序列出每次调用cons_putc、va_arg和vcprintf。对于cons_putc,同时列出它的参数。对于va_arg,在调用之前和之后列出ap指向的内容。对于vcprintf,列出它的两个参数的值。

先将代码写在mon_backtrace中。然后运行
在这里插入图片描述
在回答问题前要先理解cprintf()函数,也需要对c可变参数稍微了解一下。菜鸟教程我们使用gdb进入cprint函数后,直接打印fmt和ap即可得到第一问的结果。如图所示,在这里插入图片描述
上图可以得到vcprintf在调用时的值,至于每次调用cons_putc时参数c的值和va_arg调用前后的值,需要自己耐心走一遍流程
在这里插入图片描述
这是第一次调用cons_putc时c的值,后续不再列出,对于ap的变化,不需要查看也能得知。va_arg会获取可变参数列表的下一个参数。所以开始时1 3 4调用一次就变化为3 4,一次类推。

4.运行以下代码:
unsigned int i = 0x00646c72;
cprintf(“H%x Wo%s”, 57616, &i);
输出是什么?解释一下如何按照前面练习的逐步方式得出这个输出。这是一个将字节映射到字符的ASCII表。
输出取决于x86是小端序的事实。如果x86是大端序的,为了得到相同的输出,你会将i设置为什么值?你需要将57616更改为不同的值吗?

运行结果如下图所示:
在这里插入图片描述

因为57616=0xe110,而0x00646c72在内存中为72 6c 64,将他们转化为char之后得到的值为114’r’ 108’l’ 100’d’
如果是大端,那就需要将i设置为0x726c6400且不需要改变57616的值

  1. 在下面的代码中,在’y='之后会打印什么?(注意:答案不是具体的值。)为什么会这样打印?
    cprintf(“x=%d y=%d”, 3);

结果如下
在这里插入图片描述
因为y没有指定对应的值,直接打印的随机值

如果GCC更改其调用约定,使得参数按声明顺序从后往前推送到栈上,那么你需要如何更改cprintf或其接口,以使其仍然能够接受可变数量的参数?

直接倒过来cprintf( …,const char *fmt)

到现在我们只是回答了问题,还没有补全练习8的代码。补全这个代码很简单,照着相似的上下文抄就行了,代码如下:

		case 'o':
			// Replace this with your code.
			num = getuint(&ap, lflag);
			base = 8;
			goto number;

输出结果如下:
在这里插入图片描述

总结

完成了Part3前半部分,剩下的半部分将在下一篇博客继续。
有问题欢迎各位指出。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值