PA1.3 代码+笔记

如果有什么地方有误 请多多指教;

写这个不是让同学们直接抄的,请弄懂原理哦,我觉得我解释的蛮清楚了。

遇到了问题也可以评论留言或者私信我;

 

pa1代码➕思路17元,pa2代码+思路30元,pa3仙剑奇侠传仅代码自己看13元。扫码备注邮箱,一般立刻发,如果有事24小时内发。

                PA1.3 代码+笔记_第1张图片          

1 PA1 – 开天辟地的篇章:最简单的计算机

1.3 监视点

1)监视点的结构体

typedef struct watchpoint {  
  int NO;  //编号
  struct watchpoint *next;  
  int value;  //旧值,
  int newvalue;  //新值,
  char type;  //类型监视点w or断点b
  char Enb;  //是否开启
  char str[32];  //被监视的表达式
  /* TODO: Add more members if necessary */  
  
  
} WP; 

 

  1. 实现监视点的池的管理。

new_wp是从free链表中取一个结点给head链表,且将表达式、值赋给它,修改开关,并输出该节点的编号。运用正则表达式判断是否为断点,若是则type为b,否则为w,具体见下文断点处。

 

free_wp函数是遍历head链表直到找出对应NO的结点,从head中删除,添加到free链表中。同时修改类型、表达式、值、开关。

 

3)温故而知新

框架代码中定义wp_pool等变量时使用了关键字static,在此处的含义是静态全局变量,该变量只能被本文件中的函数调用,并且是全局变量,而不能被同一程序其他文件中的函数调用。在此处使用static是为了避免它被误修改。

  1. 实现以下功能:
  1. 如讲义中所言,每当cpu_exec()执行完一条指令,调用函数judge_wp对所有表达式求值判断是否变化,若变化则返回-1,暂停,输出提示并返回。

代码如下:

cpu-exec.c中:

/* TODO: check watchpoints here. */  
     int judge=judge_wp();  
     if(judge==-1)  
     {  
             nemu_state = NEMU_STOP;  
             printf("Triggered the monitoring point\n");  
             return;  
     }  

 

watchpoint.c中:

 

结果截图:

PA1.3 代码+笔记_第2张图片

PA1.3 代码+笔记_第3张图片

 

3)使用info w来打印监视点信息。这里在cmd_info中调用了函数print_wp(),代码如下:

void print_wp()  
{  
        printf("Num\tType\tEnb \t\t Value\t\t  What\n");  
        for(int i=0;i

 

结果截图:

PA1.3 代码+笔记_第4张图片

 

3、删除监视点。在cmd_d中调用free_wp函数即可。

结果截图:

PA1.3 代码+笔记_第5张图片

 

1.4 断点

1)断点;

代码在上面已经贴出。运用正则表达式判断是否为断点格式:$eip==0x16进制数字,regcomp()函数编译正则表达式,执行成功返回0,则type为b,否则为w。

截图:

PA1.3 代码+笔记_第6张图片

 

2)一点也不能长?

       必须的。因为当我们在调试器中对代码的某一行设置断点时,会把这里本来指令的第一个字节保存起来,然后写入一条INT 3指令,机器码为0xcc,仅有一个字节,设置和取消断点时也需要保存和恢复一个字节。

       断点机制不能正常工作。因为INT3断点将被调试进程中对应地址处的字节替换为0xcc,当int3指令的长度变成2个字节,其他指令同x86,会导致这里本来指令的第一个字节被2个字节所代替,空间不够,不正确。

3)随心所欲的断点。

       将断点设置在指令的非首字节,就无法检测到断点。因为会检测函数的地址,读取它的第一个字节,判断是否等于0xCCH

4)NEMU的前世今生。

模拟器emulator和调试器debugger的不同。我觉得dubugger是一个命令行调试工具,设置断点,调试程序,测试bug,然后emulator是一个载体,就是虚拟机,是一个独立的系统,不会对电脑本身的系统造成影响,我们可以借助它兼容不同的软件。

我觉得gdbnemu中我们在实现的功能好像差不多,但是gdb是可以直接在函数某一行或是函数入口处设置断点,可以随便查看变量当前的值。

 

1.6 必答题:

1)理解基础设施;

       在调试上花费75h,简易调试器帮它节省50h。

2)查阅i386手册;

       1、EFLAGS寄存器中的CF位是什么意思?

              P34页中提到参阅附录c,CF是进位标志;

P419页中写到CF位:在最高位发生进位或者借位的时候将其置1,否则清零。

    2、ModR/M字节是什么?

P241-243页。ModR/M由Mod,Reg/Opcode,R/M三部分组成。Mod是前两位,提供寄存器寻址和内存寻址,Reg/Opcode为345位,如果是Reg表示使用哪个寄存器,Opcode表示对group属性的Opcode进行补充;R/M为678位,与mod结合起来查图得8个寄存器和24个内存寻址

    3、mov指令的具体格式是怎么样的?

     P347页。格式是DEST ←SRC.

 

3)shell命令;

       .c.h文件有3994行代码,使用命令:

find . -name "*[.h|.cpp]" | xargs wc -l 

和框架代码相比,在PA1中写了1008行代码;

    log回转代码回到过去;除去空行之外, nemu/ 目录下的所有.c 和.h 文件总共有3308行代码。

find . –name “*[.cpp|.h]” | xargs grep “^.” | wc -l

-Wall 使GCC产生尽可能多的警告信息,取消编译操作,打印出编译时所有错误或警告信息。

-Werror 要求GCC将所有的警告当成错误进行处理,取消编译操作。

使用-Wall和-Werror就是为了找出存在的错误,尽可能地避免程序运行出错,优化程序。

你可能感兴趣的:(PA,and,Lab)