南京大学计算机系统基础实验 ICSPA(2023)PA 1 阶段 3
监视点
扩展表达式求值的功能
在上一章我们已经实现了 +,-,*,/,以及括号这几个基本的表达式,现在我们还需要实现:
- 读取十六进制数,以
0x
开头。 - 读取寄存器,以
$
开头。 - 逻辑运算符,例如
!=
,&&
等。 - 解指针引用
*<expr>
。
实现方式和之前还是一样的,首先添加匹配规则,然后在 expr()
中进行处理。需要注意的是:
- 符号的优先级,我们应该要从优先级低到高进行递归计算;
- 读取寄存器所使用的框架代码
isa_reg_str2vel()
需要我们自己实现; - 解引用使用之前用过的
paddr_read()
函数。
实现监视点
我理解的监视点就是一个动态的断点。你可以设置一个表达式,当这个表达式的值发生变化的时候,程序就会停止,以供我们检查。
关于结构体的成员,我本来的想法是添加 tokens[]
成员,用来存储表达式的 token。但是后来发现,监视点以及处理 token 的很多相关变量都是 static 的,也就是说无法在声明文件外面访问,而处理指令和计算表达式的代码不在同一个文件里,如果想要能够访问的话,需要修改很多的代码,也可能不符合讲义的期望,因此我放弃了。
最终在结构体中我只额外添加了 char *e
和 word_t old_value
,前者用来存储表达式,后者用来存储旧的值。需要计算表达式的时候直接调用 expr()
计算就好了,这个函数一开始就已经在 sdb.h
中声明了,可以直接调用。
char *e
中。NEMU 禁止了 new
和 delete
指令,我也没有找到很好的办法,只能直接定义 char e[200]
了。在一个全局变量前面添加关键词 static
的作用是,将其作用域限制在该文件内。
添加了 static
的全局变量被称为静态全局变量。静态全局变量和普通全局变量的生命周期都是从程序开始到程序结束,没有区别。但是普通的全局变量可以在别的文件里使用 extern
后访问。但是静态全局变量不行,只能在声明的文件里访问。
此外,我们还需要实现指令 w
和 info w
,具体的实现方式和之前一样。
讲义还提到在 trace_and_difftest()
函数中设置新的宏 CONFIG_WATCHPOINT
,并且在 Kconfig
文件中编写对应的配置项,来控制监视点的启用。在代码中使用 #ifdef
和 #endif
将代码包裹起来,就可以根据宏是否定义来动态编译了。而具体宏的定义是不需要我们手动定义的,只需要在 Kconfig
中设置好对应的配置项 WATCHPOINT
,mconf 会自动将前缀 CONFIG_
补全,根据我们设定好的值,在头文件中生成 CONFIG_WATCHPOINT
这个宏。
调试工具与原理
这一章节的内容是在给我们普及一些软件工程的概念。
这一章的问答题有时间的时候再补充吧。
到此结束
PA 1 到此结束。