chapter1练习(已经废弃，没删是怕以后有用)
=====================================================

.. toctree::
   :hidden:
   :maxdepth: 4

- 本节难度： **低** 

编程作业
-------------------------------

彩色化 LOG
+++++++++++++++++++++++++++++++

.. lab1 的工作使得我们从硬件世界跳入了软件世界，当看到自己的小 os 可以在裸机硬件上输出 ``hello world`` 是不是很高兴呢？但是为了后续的一步开发，更好的调试环境也是必不可少的，第一章的练习要求大家实现更加炫酷的彩色log。

.. 详细的原理不多说，感兴趣的同学可以参考 `ANSI转义序列 <https://zh.wikipedia.org/wiki/ANSI%E8%BD%AC%E4%B9%89%E5%BA%8F%E5%88%97>`_ ，现在执行如下这条命令试试

.. .. code-block:: console

..    $ echo -e "\x1b[31mhello world\x1b[0m"

.. 如果你明白了我们是如何利用串口实现输出，那么要实现彩色输出就十分容易了，只需要用需要输出的字符串替换上一条命令中的 ``hello world``，用期望颜色替换 ``31(代表红色)`` 即可。

.. .. warning::

..    以下内容仅为推荐实现，不是练习要求，有时间和兴趣的同学可以尝试。

.. 我们推荐实现如下几个等级的输出，输出优先级依次降低：

.. .. list-table:: log 等级推荐
..    :header-rows: 1
..    :align: center

..    * - 名称
..      - 颜色
..      - 用途
..    * - ERROR
..      - 红色(31)
..      - 表示发生严重错误，很可能或者已经导致程序崩溃
..    * - WARN
..      - 黄色(93)
..      - 表示发生不常见情况，但是并不一定导致系统错误
..    * - INFO
..      - 蓝色(34)
..      - 比较中庸的选项，输出比较重要的信息，比较常用
..    * - DEBUG
..      - 绿色(32)
..      - 输出信息较多，在 debug 时使用
..    * - TRACE
..      - 灰色(90)
..      - 最详细的输出，跟踪了每一步关键路径的执行

.. 我们可以输出比设定输出等级以及更高输出等级的信息，如设置 ``LOG = INFO``，则输出 ``ERROR``、``WARN``、``INFO`` 等级的信息。简单 demo 如下，输出等级为 INFO:

.. .. image:: color-demo.png

.. 为了方便使用彩色输出，我们要求同学们实现彩色输出的宏或者函数，用以代替 print 完成输出内核信息的功能，它们有着和 prinf 十分相似的使用格式，要求支持可变参数解析，形如：

.. .. code-block:: rust

..     // 这段代码输出了 os 内存空间布局，这到这些信息对于编写 os 十分重要
    
..     info!(".text [{:#x}, {:#x})", s_text as usize, e_text as usize);
..     debug!(".rodata [{:#x}, {:#x})", s_rodata as usize, e_rodata as usize);
..     error!(".data [{:#x}, {:#x})", s_data as usize, e_data as usize);

.. .. code-block:: c

..     info("load range : [%d, %d] start = %d\n", s, e, start);

.. 在以后，我们还可以在 log 信息中增加线程、CPU等信息（只是一个推荐，不做要求），这些信息将极大的方便你的代码调试。


实验要求
+++++++++++++++++++++++++++++++

.. - 实现分支：ch1。
.. - 完成实验指导书中的内容，在裸机上实现 ``hello world`` 输出。
.. - 实现彩色输出宏(只要求可以彩色输出，不要求 log 等级控制，不要求多种颜色)。
.. - 隐形要求：可以关闭内核所有输出。从 lab2 开始要求关闭内核所有输出（如果实现了 log 等级控制，那么这一点自然就实现了）。
.. - 利用彩色输出宏输出 os 内存空间布局，即：输出 ``.text``、``.data``、``.rodata``、``.bss`` 各段位置，输出等级为 ``INFO``。

实验检查
+++++++++++++++++++++++++++++++

.. - 实验目录要求(Rust)

.. .. code-block::

..    ├── os(内核实现)
..    │   ├── Cargo.toml(配置文件)
..    │   ├── Makefile (要求 make run LOG=xxx 可以正确执行，可以不实现对 LOG 这一属性的支持，设置默认输出等级为 INFO)
..    │   └── src(所有内核的源代码放在 os/src 目录下)
..    │       ├── main.rs(内核主函数)
..    │       └── ...
..    ├── reports
..    │   ├── lab1.md/pdf
..    │   └── ...
..    ├── README.md（其他必要的说明）
..    ├── ...

.. 报告命名 labx.md/pdf，统一放在 reports 目录下。每个实验新增一个报告，为了方便修改，检查报告是以最新分支的所有报告为准。

.. - 检查

.. .. code-block:: console

..    $ cd os
..    $ git checkout ch1
..    $ make run LOG=INFO

.. 可以正确执行(可以不支持LOG参数，只有要彩色输出就好)，可以看到正确的内存布局输出，根据实现不同数值可能有差异，但应该位于 ``linker.ld`` 中指示 ``BASE_ADDRESS`` 后一段内存，输出之后关机。

问答作业
-------------------------------

.. 1. 为了方便 os 处理，Ｍ态软件会将 S 态异常/中断委托给 S 态软件，请指出有哪些寄存器记录了委托信息，rustsbi 委托了哪些异常/中断？（也可以直接给出寄存器的值）

.. 2. 请学习 gdb 调试工具的使用(这对后续调试很重要)，并通过 gdb 简单跟踪从机器加电到跳转到 0x80200000 的简单过程。只需要描述重要的跳转即可，只需要描述在 qemu 上的情况。

.. 3. tips: 

..   - 事实上进入 rustsbi 之后就不需要使用 gdb 调试了。可以直接阅读代码。`rustsbi起始代码 <https://github.com/rustsbi/rustsbi-qemu/blob/main/rustsbi-qemu/src/main.rs#L146>`_ 。
..   - 可以使用示例代码 Makefile 中的 ``make debug`` 指令。
..   - 一些可能用到的 gdb 指令：
..       - ``x/10i 0x80000000`` : 显示 0x80000000 处的10条汇编指令。
..       - ``x/10i $pc`` : 显示即将执行的10条汇编指令。
..       - ``x/10xw 0x80000000`` : 显示 0x80000000 处的10条数据，格式为16进制32bit。
..       - ``info register``: 显示当前所有寄存器信息。
..       - ``info r t0``: 显示 t0 寄存器的值。
..       - ``break funcname``: 在目标函数第一条指令处设置断点。
..       - ``break *0x80200000``: 在 0x80200000 出设置断点。
..       - ``continue``: 执行直到碰到断点。
..       - ``si``: 单步执行一条汇编指令。

报告要求
-------------------------------

- 简单总结你实现的功能（200字以内，不要贴代码）。
- 完成问答题。
- (optional) 你对本次实验设计及难度/工作量的看法，以及有哪些需要改进的地方，欢迎畅所欲言。