NJU-ICS 2024学习随笔PA1_1(基础设施)

因为这一步意义重大,所以我打算单列出来。

这是才是正式开始 ”写代码“

 

2024.9.19

停了几天,一个是刚感冒好,多休息休息,一个是有点懒。

我今天发现我基础设施我跳过了,今天就开始写写基础设施。

单步执行

首先查到 strtok 的用法以及参数的解释,加上注释就可以看明白cmd_help的第一句话了

就是获得第一个参数

接下来看一下文档中说的 sscanf 吧(确实是个好东西啊,之前都是cin惯了)

接下来要开始尝试写写了

首先是指令分割

获得第一个参数。

(但是这里注意以下,如果用户有更多的输入,即不合法的参数输入,应该check一下,所以一次获取两个参数来判断是否合法)

然后是正确输入的时候,调用cpu_exec函数,参数为 nn 的取值可以用 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 中找到paddrvaddr,猜测应该对应的是物理地址和虚拟地址。

发现两个文件中都有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

内容的正确性检验

可以使用0x8000000000x80000001为起始地址,len为6,去看看重合的地址部分是否符合逻辑。

我的是这样的。代码我就不放了,可以根据上文提到的函数自行修改。

(nemu) x 10 0x80000000
0x80000000
0x00000097  0x00000002  0x00000000  0x00000000  0x00000023  0x00000088  
0x80000001
0x00000002  0x00000000  0x00000000  0x00000023  0x00000088  0x00000002  

 基础设施部分结束,赢麻了!

posted @ 2024-09-20 00:36  euphria  阅读(196)  评论(0)    收藏  举报