NJU-ICS 2024学习随笔PA1_1(基础设施)
因为这一步意义重大,所以我打算单列出来。
这是才是正式开始 ”写代码“
2024.9.19
停了几天,一个是刚感冒好,多休息休息,一个是有点懒。
我今天发现我基础设施我跳过了,今天就开始写写基础设施。
单步执行
首先查到 strtok 的用法以及参数的解释,加上注释就可以看明白cmd_help的第一句话了

就是获得第一个参数
接下来看一下文档中说的 sscanf 吧(确实是个好东西啊,之前都是cin惯了)
接下来要开始尝试写写了
首先是指令分割

获得第一个参数。
(但是这里注意以下,如果用户有更多的输入,即不合法的参数输入,应该check一下,所以一次获取两个参数来判断是否合法)
然后是正确输入的时候,调用cpu_exec函数,参数为 n( n 的取值可以用 sscanf 从 arg 获得)。
若是没有任何参数,则视 n 为 1。
完整代码

今天就到这里吧,十一点半了,收拾收拾准备睡觉了。
突然不想睡了。我现在的主要问题是我在vim上复制之后没法到本地粘贴,我研究研究怎么搞,要不然全是截图太丑陋了。
如何在vim使用系统剪切板
12点多了,但是解决了,主要出现了一下问题:
1、输入指令vim --version | grep "clipboard“时发现
~$ vim --version | grep "clipboard"
-clipboard +keymap +printer +vertsplit
+eval -mouse_jsbterm -sun_workshop -xterm_clipboard
发现 clipboard 前面是 -
2、输入指令sudo apt-get install vim vim-gtk3
但是我发现我这边出现了报错Temporary failure resolving 'mirrors.tuna.tsinghua.edu.cn'。
我尝试了包括且不限于修改网络适配器,安装有关https的包(但是发现已经安装了)。。。
所以我尝试sudo apt-get update,第一次失败了。重启后又试了一次,也失败了,但是我第二次调用就好了,我也不知道为什么,我什么都没做。。。。
再次输入指令sudo apt-get install vim vim-gtk3,就更新成功了。
~$ vim --version | grep "clipboard"
+clipboard +keymap +printer +vertsplit
+eval -mouse_jsbterm -sun_workshop +xterm_clipboard
心累,不懂网络,也不懂技术,事情发生不知道什么原因。
但是之前看jyy的操作系统课说,计算机任何事情发生都能找到原因。
所以我希望后面我能懂,这些报错发生的原因是什么。
2024.9.20
跟同学抱怨昨天发生的事情之后,收到了这样的回复“不如用vscode ssh进去”。我恍然大悟,才发现我跟着文档做,忘记了我最趁手的工具,vscode。
于是,讲一下如何用 vscode ssh 到虚拟机上的系统中。(系统Ubuntu 22.04)这里写了如何用vscode免密连接到虚拟机上
打印寄存器状态
首先再nemu目录下输入指令make run。可以看到
Welcome to riscv32-NEMU!
For help, type "help"
这个就是提示我的 reg.c 在 isa 的哪个目录下。这里显示的是在 riscv32。
所以找到该目录下的 reg.c 并打开,看到如下:
const char *regs[] = {
"$0", "ra", "sp", "gp", "tp", "t0", "t1", "t2",
"s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5",
"a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7",
"s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6"
};
void isa_reg_display() {
}
所以这里 isa_reg_display() 函数已经给出,只需要在里面写一个for循环输出 regs 的值就行了。
我是这样写的
void isa_reg_display() {
for(int i = 0; i < 32; i ++){
printf("%5s%10d\n",regs[i],*regs[i]);
}
}
然后回到 sdb.c 文件中添加指令 info。
在结构体前加
static int cmd_info(char *argc);
在结构体的TODO后添加
{ "info", "Print program status", cmd_info }
在结构体后添加 cmd_info 函数(这里已经写好了打印监视点信息的条件,后续添加内容,现在的就是什么都不做直接返回)
static int cmd_info(char *argc){
char *arg = strtok(NULL, " "); /*Extract the first argument*/
char *arg0 = strtok(NULL, " "); /*Check whether exist more argument*/
/*If the input does not match the format*/
if(arg0 != NULL){
printf("Does not match the input format: info SUBCMD. error:1\n");
return 0;
}
//Print register status
else if(*arg == 'r'){
isa_reg_display();
return 0;
}
//Print watchpoint info
else if(*arg == 'w'){
return 0;
}
else{
printf("Unknown command '%s'\n", arg);
return 0;
}
return 0;
}
make run之后,输入info r命令,有以下输出:
Welcome to riscv32-NEMU!
For help, type "help"
(nemu) info r
$0 36
ra 114
sp 115
gp 103
tp 116
t0 116
t1 116
.....(我只是省略了)
(nemu) info r w
Does not match the input format: info SUBCMD. error:1
(nemu) info w
(nemu) info k
Unknown command 'k'
扫描内存
1、首先,得找到内存相关的函数都放在哪里了,可以从 /nemu/src/memory 中找到paddr和vaddr,猜测应该对应的是物理地址和虚拟地址。
发现两个文件中都有read函数。看起来应该就是都内存的了。
word_t vaddr_read(vaddr_t addr, int len) {
return paddr_read(addr, len);
}
word_t paddr_read(paddr_t addr, int len) {
if (likely(in_pmem(addr))) return pmem_read(addr, len);
IFDEF(CONFIG_DEVICE, return mmio_read(addr, len));
out_of_bound(addr);
return 0;
}
addr应该是起始地址,len应该就是长度了
2、介绍一下 strtol() 函数,用来字符串转换进制的。这样字符串转进制的工具就有了。
所以,接下来是错误的判断
error3:输入不符合规范
error4:第一个参数不是整数
error5:第二个参数不是十六进制
3、然后是输出,调用 paddr_read() (因为vaddr_read()也是直接调用这玩意)
获得该地址为起点,长度为len字节的内容。
完整代码如下:
static int cmd_x(char *argc){
char *arg0 = strtok(NULL, " "); /*Extract the first argument*/
char *arg1 = strtok(NULL, " "); /*Extract the second argument*/
char *arg2 = strtok(NULL, " "); /*Check whether exist more argument*/
/*Check if arg0 is an digit*/
if(arg0 == NULL){
printf("Does not match the input format: x N EXPR. error:3\n");
return 0;
}
char *str;
int n = strtol(arg0, &str, 10);
if(!n){
printf("N is not a digit. error:4\n");
return 0;
}
/*Check if arg1 is a hexadecimal number*/
if(arg1 == NULL){
printf("Does not match the input format: x N EXPR. error:3\n");
return 0;
}
paddr_t addr = strtol(arg1, &str, 16);
// sscanf(arg1, "%x", &addr);
if(!addr){
printf("EXPR is not a hexadecimal number. error:5\n");
return 0;
}
/*If the input does not match the format*/
if(arg2 != NULL){
printf("Does not match the input format: x N EXPR. error:3\n");
return 0;
}
/*Print current address and value*/
for(int i = 0; i < n; i ++){
paddr_t k = paddr_read(addr + i * 4, 4);
printf("0x%08x 0x%08x\n", addr + i * 4, k);
}
return 0;
}
输出为:
(nemu) x
Does not match the input format: x N EXPR. error:3
(nemu) x 10
Does not match the input format: x N EXPR. error:3
(nemu) x a 0x80000000
N is not a digit. error:4
(nemu) x 10 0x80000000 2
Does not match the input format: x N EXPR. error:3
(nemu) x 10 0x80000000
0x80000000 0x00000297
0x80000004 0x00028823
0x80000008 0x0102c503
0x8000000c 0x00100073
0x80000010 0xdeadbeef
0x80000014 0x73737373
0x80000018 0x73737373
0x8000001c 0x73737373
0x80000020 0x73737373
0x80000024 0x73737373
内容的正确性检验 :
可以使用0x800000000和0x80000001为起始地址,len为6,去看看重合的地址部分是否符合逻辑。
我的是这样的。代码我就不放了,可以根据上文提到的函数自行修改。
(nemu) x 10 0x80000000
0x80000000
0x00000097 0x00000002 0x00000000 0x00000000 0x00000023 0x00000088
0x80000001
0x00000002 0x00000000 0x00000000 0x00000023 0x00000088 0x00000002
基础设施部分结束,赢麻了!

浙公网安备 33010602011771号