其他部分
1. 主要难点
1.1 NEMU是如何模拟指令执行的过程
这一个阶段就是阅读源代码,代码框架中间定义了大量的宏,比如
#define IDEXW(id, ex, w) {concat(decode_, id), concat(exec_, ex), w}
#define IDEX(id, ex) IDEXW(id, ex, 0)
#define EXW(ex, w) {NULL, concat(exec_, ex), w}
#define EX(ex) EXW(ex, 0)
#define EMPTY EX(inv)
这些宏初次遇到的时候会让人感觉很抓狂,但是试验完成之后还是感觉这只是让人抓狂的冰山一角。
接下来分析一下一条指令是是如何执行完成的
ui.c 经过一些列的初始化之后进入到ui_mainloop函数,is_batch_mode是命令行参数控制的内容,具体位置在nexus-am/am/arch/x86-nemu/img/run中间。
void ui_mainloop(int is_batch_mode) {
if (is_batch_mode) {
cmd_c(null);
return;
}
// .....
cpu-exec.c 中间的cpu_exec.c中间的函数主要用于处理IO辅助代码和gdb的检查点的分析
void cpu_exec(uint64_t n) {
if (nemu_state == NEMU_END || nemu_state == NEMU_ABORT) {
printf("Program execution has ended. To restart the program, exit NEMU and run again.\n");
return;
}
// ....
exec.c 终于到达真正的硬件层级,exec_wrapper主要处理内容是更新指令执行完成之后eip的更新和统计必要的执行信息。
void exec_wrapper(bool print_flag) {
vaddr_t ori_eip = cpu.eip;
//....
现在分析一下更新eip的原理和错误的处理eip 会导致的问题:
第一个: 跳转指令(jmp, call , ...) 会导致exec_warp 中间的debug 语句异常
int instr_len = decoding.seq_eip - ori_eip;
sprintf(decoding.p, "%*.s", 50 - (12 + 3 *