#### 扩展练习 Challenge 1（需要编程）

扩展proj4,增加syscall功能，即增加一用户态函数（可执行一特定系统调用：获得时钟计数值），当内核初始完毕后，可从内核态返回到用户态的函数，而用户态的函数又通过系统调用得到内核态的服务（通过网络查询所需信息，可找老师咨询。如果完成，且有兴趣做代替考试的实验，可找老师商量）。需写出详细的设计和分析报告。完成出色的可获得适当加分。

提示：
规范一下 challenge 的流程。

kern_init 调用 switch_test，该函数如下：

```
	static void
	switch_test(void) {
		print_cur_status();          // print 当前 cs/ss/ds 等寄存器状态
		cprintf("+++ switch to  user  mode +++\n");
		switch_to_user();            // switch to user mode
		print_cur_status();
		cprintf("+++ switch to kernel mode +++\n");
		switch_to_kernel();         // switch to kernel mode
		print_cur_status();
	}
```

switch_to_\* 函数建议通过 中断处理的方式实现。主要要完成的代码是在 trap 里面处理 T_SWITCH_TO\* 中断，并设置好返回的状态。

在 lab1 里面完成代码以后，执行 make grade 应该能够评测结果是否正确。

#### 扩展练习 Challenge 2（需要编程）
用键盘实现用户模式内核模式切换。具体目标是：“键盘输入3时切换到用户模式，键盘输入0时切换到内核模式”。
基本思路是借鉴软中断(syscall功能)的代码，并且把trap.c中软中断处理的设置语句拿过来。

注意：

　1.关于调试工具，不建议用lab1_print_cur_status()来显示，要注意到寄存器的值要在中断完成后tranentry.S里面iret结束的时候才写回，所以再trap.c里面不好观察，建议用print_trapframe(tf)

　2.关于内联汇编，最开始调试的时候，参数容易出现错误，可能的错误代码如下
   ```
   asm volatile ( "sub $0x8, %%esp \n"
     "int %0 \n"
     "movl %%ebp, %%esp"
     : )
  ```
  要去掉参数int %0 \n这一行

3.软中断是利用了临时栈来处理的，所以有压栈和出栈的汇编语句。硬件中断本身就在内核态了，直接处理就可以了。

4. 参考答案在mooc_os_lab中的mooc_os_2014 branch中的labcodes_answer/lab1_result目录下
