NJU ICS PA 一些笔记
Do you know
本人代码水平拙劣🥲,实现部分仅供参考
PA1 - 开天辟地的篇章
RTFSC
文件:nemu/src/monitor/sdb/sdb.c
原因:退出时 nemu_state.state
不是 “正常” 的
解决办法:
static int cmd_q(char *args) {
nemu_state.state = NEMU_QUIT;
return -1;
}
监视点
基本框架
添加 w <expr>
和 d <index>
命令,来添加和删除监视点。
并且需要实现监视点池中链表的维护,监视点表达式的计算。
为了提高 NEMU 的性能,提供监视点功能的开关选项。
链表维护
监视点池中涉及监视点链表和空闲链表,通过 init_wp_pool()
来对其初始化。
void init_wp_pool() {
int i;
for (i = 0; i < NR_WP; i ++) {
wp_pool[i].NO = i;
wp_pool[i].next = (i == NR_WP - 1 ? NULL : &wp_pool[i + 1]);
}
head = NULL;
free_ = wp_pool;
}
接着,通过 new_wp()
和 free_wp()
实现监视点的管理
int new_wp(char* args){
WP *p=NULL,*q=NULL;
if (free_==NULL)
{
printf("Watchpoints Limit");
return -1;
}
p=free_;
bool success=1;
p->result = expr(args,&success);
if (!success)return -1;
p->expr = strdup(args);
free_=free_->next;
if (head!=NULL)
{
q=head;
while (q->next!=NULL)q=q->next;
q->next=p;
return 1;
}
head=p;
head->next=NULL;
return 1;
}
void free_wp(int no)
{
if (head==NULL)
{
printf("Watchpoint %d not found.\n",no);
return;
}
if (head->NO==no)
{
WP *wp=head;
head=wp->next;
wp->next=free_;
free_=wp;
return;
}
WP *p=NULL;
if (head!=NULL)
{
p=head;
while (1){
if (p->next->NO==no){
WP *wp=p->next;
p->next=wp->next;
wp->next=free_;
free_=wp;
return;
}
if (p->next==NULL)
{
printf("Watchpoint %d not found.\n",no);
return;
}
p=p->next;
}
}
}
监视点求值
为了判断监视点的值是否发生变化,还需要在结构体中添加一个成员来记录。然后通过 check_expr()
来求值和判断变化。
bool check_expr(){
bool changed=false;
if (head==NULL)return 0;
WP *p;
bool success=true;
p=head;
word_t result = expr(p->expr,&success);
if (result!=p->result && success)
{
printf("Watchpoint %d changed at 0x%x.\n",p->NO,cpu.pc);
changed=true;
}
if (changed)return 1;
return 0;
}
如何阅读手册
程序是个状态机
对于计算 1+2+...+100
的程序的状态机,它是确定性的。
(0, x, x) -> (1, 0, x) -> (2, 0, 0) -> (3, 0, 1) -> (4, 1, 1) -> (5, 1, 2) -> (6, 3, 2) -> ... -> (199,4851, 99) -> (200, 4950, 99) -> (201, 4950, 100) -> (202, 5050, 100)
理解基础设施
不必多说,使用过调试器的话肯定有所体会。
RTFM
riscv32 有哪几种指令格式?
There are four core instruction formats.1
Register-Type, Immediate-Type, Store-Type, Upper Immediate-Type.
LUI 指令的行为是什么?
LUI (load upper immediate) is used to build 32-bit constants and uses the U-type format. LUI places the 32-bit U-immediate value into the destination register rd, filling in the lowest 12 bits with zeros.

mstatus 寄存器的结构是怎么样的?
The mstatus (Machine Status) register is an MXLEN-bit read/write
register formatted as shown in figures below. It's a Control and
Status Register.
为什么要使用 -Wall
和 -Werror
?
At section 3.92, we found that:
-Werror
Turn all warnings into errors.
-Wall
This enables all the warnings about constructions
that some users consider questionable, and that are easy to avoid (or
modify to prevent the warning), even in conjunction with macros. This
also enables some language-specific warnings.
To add these options, we can leverage compilers to identify potential issues in our programs.
shell 命令
使用 find . -type f \( -name "*.c" -o -name "*.h" \) -print0 | xargs -0 wc -l
来统计行数
由于我环境经历了多次迁移,似乎把 git 弄坏了(
不过毕竟我没有提交作业的需求,就不注意这些细节了