pa1.1

本章主要是要求大家进行使用构建完成简易表达式,主要包括单步执行,打印寄存器,还有扫描内存

为什么使用static,因为使用static可以解决两个c文件有相同函数名的问题,不会造成编译问题

单步执行

但不执行,我们可以看到远吗使用的cmdc这个函数

1
2
3
4
5
static int cmd_c(char *args) {
// -1是65535最大的2的64-1
cpu_exec(-1);
return 0;
}

使用cpu_exec代表就是直接执行,使用-1,因为这是uint,无符号,-1的无符号就是最大值

1
2
3
4
5
6
7
8
9
void cpu_exec(uint64_t n) {
g_print_step = (n < MAX_INST_TO_PRINT);
switch (nemu_state.state) {
case NEMU_END: case NEMU_ABORT:
printf("Program execution has ended. To restart the program, exit NEMU and run again.\n");
return;
default: nemu_state.state = NEMU_RUNNING;
}

所以我们只需要对当前的函数,进行查找出需要执行的步数,然后调用cpu——exec来进行执行代码

使用strtok来进行抽取参数就可以

然后转换函数可以直接使用atoi

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
static int cmd_si(char *args){
/* extract the first argument */
/*get steps,default is 1*/
char *arg = strtok(NULL, " ");
int i=1;
if(arg==NULL){
/* no argument given */
i=1;
}else{
i=0;
for(int j=0;j< strlen(arg);j++){
i=i*10+arg[j]-'0';
}
}
// printf("%s",arg);
cpu_exec(i);
return 0;
}

打印寄存器

打印寄存器就更简单了. 不过既然寄存器的结构是ISA相关的, 我们希望能为简易调试器屏蔽ISA的差异. 框架代码已经为大家准备了如下的API:

1
2
// nemu/src/isa/$ISA/reg.c
void isa_reg_display(void);

执行info r之后, 就调用isa_reg_display(), 在里面直接通过printf()输出所有寄存器的值即可. 如果你从来没有使用过printf(), 请RTFM或者STFW. 如果你不知道要输出什么, 你可以参考GDB中的输出.

这个因为我们使用的riscv,所以需要去riscv里面进行修改isa——display这个函数。

直接调用isa,主要思路就是在reg里面进行遍历每一个寄存器,然后reg里面有gpr这个可以直接获取值。

1
2
3
4
5
6
void isa_reg_display() {
for (int i = 0; i < 32; ++i) {
// printf("%s %s",regs[i],isa_reg_str2val(regs[i],false));
printf("%-3s :0x%08lx | \n", regs[i], cpu.gpr[i]);
}
}

扫描内存

这个意思就是求出地址附近的10个值。如何求出值,观看rtfsc,可以发现调用vaddr,传入地址,还有字节数就行。默认riscv一个地址有4B,所以我们就传入就行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
static int cmd_x(char *args){
/* get N info,with the start of exp*/
/*
* vaddr_read(addr,len),这个len是长度的意思,单位是byte,一条指令默认4B,所以取的4
*/
char *arg= strtok(NULL, " ");


int N=atoi(arg);


paddr_t exprs=0x80000000;
// printf("0x%08x",exprs);




// printf("Address Dword block ... Byte sequence\n");

for(int i=0;i<N;i++){

printf("0x%8x 0x%08lx\n",exprs + i*4,vaddr_read(exprs + i * 4,4));
}
return 0;
}

然后地址的话,每次都是更新4,。直接+4就可以

总结

总的来说还是比较简单的,但是由于是第一次接触到这种作业,还是查了不少资料。重点还是要看jyy的2020ics的习题课