Mengzelev's Blog

PA1实验报告

Word count: 2,070 / Reading time: 7 min
2018/10/04 Share

实验进度

2018/9/15:
完成阶段一,实现了单步执行、打印寄存器和扫描内存(简易版)
开始做之前忘了git checkout pa1导致工作都在pa0分支里完成了,后来在pa1分支下返工了一遍,两边的git log里都可以查到记录所以求求老师不要扣我的分qwq我下次确定一定肯定确认分支后再开始工作

2018/9/23:
完成阶段二,实现了包含()+-*/和十进制数字的表达式计算。为了处理负数将类型都实现为了long long而不是uint32_t,需要按uint32_t类型使用时进行强制类型转换。实现了表达式生成器并测试。

2018/9/29:
完成阶段三,扩展了表达式计算中的==!=>=<=><、解除引用和寄存器计算。实现了监视点添加、删除和打印信息功能。用自带的用户镜像初步测试无问题。

2018/9/30:
早上起来和同学聊天发现了自己监视点实现的隐藏bug,一开始看了半天没理解到底怎么回事,然后动手加了一堆printf语句缩小范围终于找到了出错的区间,虽然具体的原理还没理解透彻,但是靠着一知半解成功修复了隐藏bug。

必答题

不敢po上来的!

部分蓝框思考题

Q:假设你在Windows中使用Docker安装了一个GNU/Linux container, 然后在container中完成PA, 通过NEMU运行Hello World程序. 在这样的情况下, 尝试画出相应的层次图.
A:参考了docker官网上的架构图

架构
“Hello World” program
simulated x86 hardware
NEMU
bins/libs
Docker
host os (windows)
Hardware

Q:如果没有寄存器, 计算机还可以工作吗? 如果可以, 这会对硬件提供的编程模型有什么影响呢?
A:我认为没有寄存器计算机是可以工作的,但是效率会非常低,因为数据的读写只能从内存中进行,而内存的读写速度是慢于寄存器的。而且现在我们学的IA-32架构是不允许在两个内存单元之间进行数据操作的,必须用寄存器作为中间媒介。编程模型一周目的我查了一下没有看懂,但愿二周目的我能看懂吧。

Q:我们知道, 时序逻辑电路里面有”状态”的概念. 那么, 对于TRM来说, 是不是也有这样的概念呢? 具体地, 什么东西表征了TRM的状态? 在状态模型中, 执行指令和执行程序, 其本质分别是什么?
A:TRM中存在一个叫做状态寄存器的组成部分,会存储图灵机当前的状态。(状态模型又是什么)执行指令和执行程序的本质区别是程序是一大堆指令的集合。(个人理解)

Q:嗯… 如果你觉得提示还不够, 那就来一个劲爆的: 回忆程序设计课的内容, 一个程序从哪里开始执行呢?如果你不屑于回答这个问题, 不妨先冷静下来. 其实这是一个值得探究的问题, 你会在将来重新审视它.
A:我正在尝试冷静下来….

Q:阅读reg_test()的代码, 思考代码中的assert()条件是根据什么写出来的
A:我不太理解“根据什么写出来”是什么意思……反正没有对错我就说一下个人理解吧。reg_test里的assert们应该是check了一下所有寄存器的存储状态,包括整个32位、低16位和两个低8位,从而来检查CPU_state的结构是否正确。根据…根据CPU_state应有的结构写出来的?

Q:在cmd_c()函数中, 调用cpu_exec()的时候传入了参数-1, 你知道这是什么意思吗?
A:这样就不会做cpu_exec()中的for循环而直接执行if(nemu_state == NEMU_RUNNING) nemu_state = NEMU_STOP语句实现单步执行。

Q:opcode_table到底是个什么类型的数组?
A:是一个opcode_entry结构体类型的数组,通过RTFSC推测应该是模拟指令码的结构体。

Q:你可能会抑制不住编码的冲动: 与其RTFM, 还不如自己写. 如果真是这样, 你可以考虑一下, 你会如何测试自己编写的字符串处理函数?
A:其实我更愿意RTFM,有现成的为什么要造轮子
写个随机生成字符串的程序产生输入,然后将输入和输出全部都输出肉眼比对一下,大概测试个20组没问题就当过了吧。(做oj的后遗症)

Q:框架代码中定义wp_pool等变量的时候使用了关键字static, static在此处的含义是什么? 为什么要在此处使用它?
A:static是Internal Linkage的意思,是指编译过程中进行链接时由static修饰的变量不参与与外部文件的链接。这样就使外部的函数一旦使用了这几个变量,编译器就会报错,保证了与WP相关的操作都只能定义在这个文件中。(如果真是这样就有点OOP的感觉?对外只提供接口,实现都在内部,保证了数据和操作的安全性)

剩下一些思考题要么是能力不够STFW找不到满意的答案,要么是找到了看上去满意的答案然而看不懂….

遇到的问题以及对问题的思考

  • git merge的时候发生了conflict
    STFW之后发现需要先git reset –merge然后cat冲突文件查看是哪里冲突,修改相应地方之后再git merge
  • 全部写完之后才发现写错分支了
    本来以为git merge之后再给分支重命名就可以了,但是各种冲突实在太多了,所以重新写了一遍,血的教训告诉我们以后一定要在写之前反复检查git branch。因为难以找到一段完整的时间一次性写完,所以每次开始工作之前都需要git branch。
  • vim忽然“死机”
    写完一段之后下意识Ctrl+S,之后发现其实是把vim锁定了,Ctrl+Q解锁
  • vim非正常退出后再次打开与.swp文件发生冲突
    按R检查是否是自己需要的状态,然后rm .[filename].c.swp将交换文件删除(删之前一定要谨慎不然就是作死)
  • 量子态更新个人blog中,欢迎老师视奸后加分

实验心得

  • PA虽然是个时间黑洞但是真的很好玩!
  • 开始动手之前一定要认真RTFSC
  • 看不懂代码的时候手动加点测试可以帮助理解
  • 人真是越学越挑剔,曾经我可以看着全默认的ui手动缩进代码,现在编辑器要是没有(配置)喜欢的字体、自动缩进、括号匹配、甚至一键函数跳转,我可能都会当场疯掉某种意义上越挑剔也就越有学习的欲望很多大佬的故事都告诉我们,工具的改进源于对现有工具的极大不爽
  • PA1完全是写给自己用的程序而不是OJ那样的了,一定要扪心自问:你写的代码对得起你自己吗?

Acknowledegments

  • 感谢 Massimo同学 在我vim出现异常的时候告诉我是Ctrl+s把屏幕给锁死了并成功教我“急救”方法
  • 感谢 某不愿透露姓名的nb学长 帮忙看了一下表达式生成器的bug,还解决了我的一堆疑问,并且提供深夜debug陪聊服务,并给我负罪感使我以后牢记优先STFW
  • 感谢 xy同学 提供轻度剧透,使我避免了一些bug,还告诉了我一个隐藏bug的存在
  • 感谢 不学习的正经水群 交流pa心得一起快乐编程

实验报告虽然写了很多还是意犹未尽啊,为了赶ddl并尽快愉快地开始PA2先交了,等ddl过了之后会上传删掉了必做题的版本到个人blog,不定时更新

CATALOG
  1. 1. 实验进度
  2. 2. 必答题
  3. 3. 部分蓝框思考题
  4. 4. 遇到的问题以及对问题的思考
  5. 5. 实验心得
  6. 6. Acknowledegments