首页 > 其他分享 >nju pa

nju pa

时间:2023-01-12 00:11:57浏览次数:40  
标签:info int EXPR cmd char pa nju NULL

PA

目录

PA1

RTFSC

优美地退出

make run启动nemu后直接输入q退出,得到如下最后一行的错误

Welcome to riscv32-NEMU!
For help, type "help"
(nemu) log
Unknown command 'log'
(nemu) q
make: *** [/home/ubuntu/ics2022/nemu/scripts/native.mk:38: run] Error 1

是由于is_exit_status_bad函数返回了-1,main函数直接返回了此函数返回的结果,make检测到该可执行文件返回了-1,因此报错。通过分析该函数得到解决方案:在输入q中途退出nemu后,将nemu_state.state设成NEMU_QUIT即可

// nemu/src/monitor/sdb/sdb.c
void sdb_mainloop() {
		...
      
    int i;
    for (i = 0; i < NR_CMD; i ++) {
      if (strcmp(cmd, cmd_table[i].name) == 0) {
        if (cmd_table[i].handler(args) < 0) { 
          if (strcmp(cmd, "q") == 0) {
            nemu_state.state = NEMU_QUIT; // set "QUIT" state when q
          }
          return;
        }
        break;
      }
    }

    if (i == NR_CMD) { printf("Unknown command '%s'\n", cmd); }
  }
}

此时再通过make run运行后中途键入q命令退出模拟器将不会再报该错误

简易调试器

单步执行 si [N]

第一步,在cmd_table注册一条命令si

// nemu/src/monitor/sdb/sdb.c
static struct {
  const char *name;
  const char *description;
  int (*handler) (char *);
} cmd_table [] = {
  { "help", "Display information about all supported commands", cmd_help },
  { "c", "Continue the execution of the program", cmd_c },
  { "q", "Exit NEMU", cmd_q },
  { "si", "Continue the execution in N steps, default 1", cmd_si },

  /* TODO: Add more commands */

};

第二步,编写cmd_si,即si具体要执行的东西

static int cmd_si(char *args) {
  /* extract the first argument */
  char *arg = strtok(NULL, " ");
  int n;

  if (arg == NULL) {
    n = 1;
  } else {
    n = strtol(arg, NULL, 10);
  }
  cpu_exec(n);
  return 0;
}

打印寄存器 info r

第一步,注册命令

{ "info", "Display the info of registers & watchpoints", cmd_info },

第二步,编写cmd_info,其中调用的isa_reg_display函数就是PA文档里介绍的,简易调试器为了屏蔽ISA的差异. 框架代码已经为大家准备了的API之一

static int cmd_info(char *args) {
  /* extract the first argument */
  char *arg = strtok(NULL, " ");
  if (arg == NULL) {
    printf("Usage: info r (registers) or info w (watchpoints)\n");
  } else {
    if (strcmp(arg, "r") == 0) {
      isa_reg_display();
    } else if (strcmp(arg, "w") == 0) {
      // todo
    } else {
      printf("Usage: info r (registers) or info w (watchpoints)\n");
    }
  }
  
  return 0;
}

第三步,实现提前设计好的isa_reg_display

// nemu/src/isa/$ISA/reg.c
void isa_reg_display() {
  int reg_num = ARRLEN(regs);
  int i;

  for (i = 0; i < reg_num; i++) {
    printf("%-8s%-#20x%-20d\n", regs[i], cpu.gpr[i], cpu.gpr[i]);
  }
}

扫描内存 x N EXPR

第一步,注册命令

{ "x", "Usage: x N EXPR. Scan the memory from EXPR by N bytes", cmd_x },

第二步,编写cmd_x,注意这里有两个参数N和EXPR,因此需要分别检查参数是否存在,并转换类型。然后就是利用vaddr_read每次读取4个字节并打印。打印格式参照了一下gdb的x命令,每行打印4个4字节

static int cmd_x(char *args) {
  char *arg1 = strtok(NULL, " ");
  if (arg1 == NULL) {
    printf("Usage: x N EXPR\n");
    return 0;
  }
  char *arg2 = strtok(NULL, " ");
  if (arg1 == NULL) {
    printf("Usage: x N EXPR\n");
    return 0;
  }

  int n = strtol(arg1, NULL, 10);
  vaddr_t expr = strtol(arg2, NULL, 16);

  int i, j;
  for (i = 0; i < n;) {
    printf(ANSI_FMT("%#010x: ", ANSI_FG_CYAN), expr);
    
    for (j = 0; i < n && j < 4; i++, j++) {
      word_t w = vaddr_read(expr, 4);
      printf("%#010x ", w);
      expr += 4;
    }
    puts("");
  }
  
  return 0;
}

表达式求值 p EXPR

第一步,注册命令

{"p", "Usage: p EXPR. Calculate the expression, e.g. p $eax + 1", cmd_p}

第二步,编写cmd_p

TODO()

标签:info,int,EXPR,cmd,char,pa,nju,NULL
From: https://www.cnblogs.com/nosae/p/17045249.html

相关文章