1、实现基本的信息输出
课程使用RS232接口进行输出,其通过两根信号线:发送信号、接收信号,便能实现与外部的数据输入输出通信,qemu有实现对这种接口的模拟
本实验用它来做临时的调试使用,以便于将操作系统运行过程中的信息能够输出到某个地方,方便及时查看
大体的工作就两部分:
- 写一系列寄存器初始化
- 查询设备不忙时发送数据。
换行与回车
- 换行(\n):将光标移到下一行,列号不变
- 回车(\n):将光标移到本行的开头
因此,如果需要将光标移到下一行开始,需要使用\r\n。 不过,不同的显示终端对于\n的解释不同。
2、实现字符串格式化输出
主要实现了%s的格式化输出,重点在可变参数的获取
在函数内部,可以通过一定的方式取出这些没有名称的参数。流程依次为:
- 定义va_list类型的变量,如ap,用于存放取可变参数的一些信息
- 使用va_start(ap, 最后一个有名字的参数-参数2):初始化ap
- 依次使用va_arg(ap, type)获取传入的可变部分的参数
- 使用va_end(ap)结束可变参数的取参,释放相应的资源
当有更多参数时,如func_arg(a, b, c, d, e),则栈中压入的参数从上(高地址)到下(低地址)依次为e, d, c, b , a。在函数内部,只有func_arg(int a, ....)中的a参数有名字可以引用,而要获取其它参数,则需要借助a找到对应的栈位置,然后再在栈中依次往上(高地址)逐个去取出相应的参数
3、格式化输出
通过状态机的方式来格式化字符串
-
状态机的两个状态:
- NORMAL: 这个状态表示当前正在处理普通字符(即不需要格式化的字符)。这些字符会被直接写入到字符串缓存中。也就是说,当遇到普通字符(如字母、数字、标点符号等)时,不需要进行特殊处理,只需将它们原样添加到输出字符串中。
- READ_FMT: 这个状态表示当前遇到了一个格式化标记(例如
%s
,%d
等),需要从可变参数列表中取出对应的参数并将其转换为字符串形式,然后写入字符串缓存中。比如遇到%s
时,从可变参数列表中获取一个字符串,并将其内容写入缓存。
-
工作流程:
- 当
kernel_vsprintf
函数开始处理一个字符串时,它会从第一个字符开始,逐个检查字符。 - 如果遇到普通字符(不以
%
开头),状态为 NORMAL,直接将字符写入缓存。 - 如果遇到
%
开头的格式标记,状态切换到 READ_FMT,并继续处理格式标记后面的字符,直到读取完完整的格式标记(例如%s
或%d
等)。 - 一旦完成格式化数据的处理,状态会切回到 NORMAL,继续处理后续字符。
- 当