南大计算机课程,南京大学 计算机系统基础 课程实验 2018(PA0-1)

申明,本人并非是南京大学的学生,此实验一共完成其中四部分,试验环境为Manjaro(并非PA0中间的docker) + SpaceVim, 此文为记录试验的部分心得。

PA0

正如在本课程试验中间反复提到的基础设施的重要性,比如PA1 中间gdb的构建,PA2 中间的diff test 创建,同样的搭建一个良好的试验环境也可以让自己注意力集中关键的部分。

方案一:vs code

方案二: vim

不推荐不熟悉vim的用户使用此方案。

无论采用哪一个方案,务必保证可以实现符号跳转,全局符号搜索和文件搜索的功能。

PA1

PA1 主要作用是熟悉工程的架构,有一个平缓的学习曲线,和后面试验关系不大(我完成了PA4,才把这一部分补充完整的, 个人感觉debug 主要依赖于diff test), 试验的难点主要有两个方面:

表达式的求值

watchpoint 的链表操作

表达式的求值

其中表达式的求值更加麻烦,我采用的方案并不是实验指导书中间的策略,而是使用的逆波兰表达式求值。

使用逆波兰表达式写了一半的时候突然发现似乎没有办法处理单目表达式的, 也就是说对于如下的表达式都是没有办法处理

12 +-12 // 没有办法正确的处理 -12

*0x4000000 + 12 // 无法处理取地址符

其实处理的办法很简单,在使用逆波兰表达式求值之前遍历一遍表达式,如果一个运算符的左侧不是数值那么改operator必定是单目的。

不用实现函数

为了方便实现,需要把所有需要符号设置为右结合的,也就是

(the operator at the top of the operator stack has equal precedence and is left associative) 这一个条件不使用

关于结合性, 使用如下例子

12 + 13 - 14

// + - 都是左结合,对应的Reverse Polish 表达式为 12 13 14 + -

// 所有表达式设置为右结合,结果为 12 13 14 - +

表达式求值中间有一个非常坑的地方,那就是expr.c 中间定义了一个宏表示可以处理的最长的符号个数,对于如下测试样例:

(1 + (3 * 2) + (($eax - $eax) + (*$eip - 1 **$eip) + (0x5 -- 5 + *0x1000005 - *0x1000005)) * 4)

恰好超过了限制,这一个bug 非常难以发现。所以我建议大家做实验的时候首先将改宏设置为初始值的10倍

watchpoint 的链表操作

文档中间对于这一个实现描述已经非常的清楚了,每次CPU 执行的时候都检查数值watchpoint的求值是否发生变化,实现难度关键是链表的操作,如果不小心很容易造成死循环和segment fault, 我的建议是多写assert

其他的收获

Makefile的书写

先分析Makefile.git

define git_commit

-@git add .. -A --ignore-errors

-@while (test -e .git/index.lock); do sleep 0.1; done

-@(echo "> $(1)" && echo $(STUID) && id -un && uname -a && uptime && (head -c 20 /dev/urandom | hexdump -v -e '"%02x"') && echo) | git commit -F - $(GITFLAGS)

-@sync

endef

其中下面这一个最麻烦

-@(echo "> $(1)" && echo $(STUID) && id -un && uname -a && uptime && (head -c 20 /dev/urandom | hexdump -v -e '"%02x"') && echo) | git commit -F - $(GITFLAGS)

其运行结果如下:

> run

U201514545

shen

Linux shen-pc 4.20.0-1-MANJARO

#1 SMP PREEMPT Mon Dec 24 08:20:48 UTC 2018 x86_64 GNU/Linux

00:56:37 up 1:21, 1 user, load average: 0.79, 0.65, 0.47

d85114835383b139f02b1c1923a8ae33eaa5dc49

&& 分割开来都是命令,|分割则是重定向使用,整个表达式的作用就是将电脑的信息作为commit的内容,不是很懂为什么需要包含随机数到commit 中间,可能是为了发防止作弊吧。

再分析Makefile:

首先这是一个很不错的小模板,我不是很熟悉Makefile的语法,所以我认为以下几个知识点还是值的学习的。

Nemu工程的源码分析

Nemu是i386模拟器,相当于计算机硬件基础,主要实现的功能是

decode(PA2), exec(PA2), 模式设备(借助SDL2库), gdb(本轮试验完成的) 和diff test(基础设施PA2)

├── include

├── Makefile

├── Makefile.git

├── README.md

├── runall.sh

├── src

│ ├── cpu

│ │ ├── decode

│ │ │ ├── decode.c

│ │ │ └── modrm.c

│ │ ├── exec

│ │ │ ├── all-instr.h

│ │ │ ├── arith.c

│ │ │ ├── cc.c

│ │ │ ├── control.c

│ │ │ ├── data-mov.c

│ │ │ ├── exec.c

│ │ │ ├── logic.c

│ │ │ ├── prefix.c

│ │ │ ├── relop.c

│ │ │ ├── special.c

│ │ │ └── system.c

│ │ ├── intr.c

│ │ └── reg.c

│ ├── device

│ │ ├── device.c

│ │ ├── io

│ │ │ ├── mmio.c

│ │ │ └── port-io.c

│ │ ├── keyboard.c

│ │ ├── serial.c

│ │ ├── timer.c

│ │ └── vga.c

│ ├── main.c

│ ├── memory

│ │ └── memory.c

│ ├── misc

│ │ └── logo.c

│ └── monitor

│ ├── cpu-exec.c

│ ├── debug

│ │ ├── expr.c

│ │ ├── ui.c

│ │ └── watchpoint.c

│ ├── diff-test

│ │ ├── diff-test.c

│ │ ├── diff-test.h

│ │ └── ref.c

│ └── monitor.c

└── tools

├── gen-expr

│ ├── gen-expr.c

│ └── Makefile

└── qemu-diff

├── include

│ ├── common.h

│ └── protocol.h

├── Makefile

└── src

├── diff-test.c

├── gdb-host.c

└── protocol.c

在接下来试验PA2中间我会首先分析试验的难点,坑点,然后分析部分源代码和实现的技术。

目录 I 基础知识9 1 MINIX操作系统简介11 1.1 MINIX与UNIX . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.2 探索MINIX . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 1.3 编辑器:vi . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 1.4 编译器:CC . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 1.5 实习题. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 2 Intel 8086体系结构19 2.1 8086 CPU结构. . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.2 运算器与指令部件. . . . . . . . . . . . . . . . . . . . . . . . 19 2.3 寄存器组. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 2.4 主存. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 2.5 堆栈. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 2.6 系统启动. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 2.7 二进制文件结构. . . . . . . . . . . . . . . . . . . . . . . . . . 25 3 ACK 8086汇编语言27 3.1 寻址. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 3.2 数据移动指令. . . . . . . . . . . . . . . . . . . . . . . . . . . 28 3.3 常量、标号、数据与全局变量. . . . . . . . . . . . . . . . . . 29 3.4 运算指令. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 3.5 标志位操纵指令. . . . . . . . . . . . . . . . . . . . . . . . . . 31 3.6 串操作指令. . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 3.7 跳转、分支与循环. . . . . . . . . . . . . . . . . . . . . . . . 33 3.8 堆栈与子程序. . . . . . . . . . . . . . . . . . . . . . . . . . . 34 5 6 目录 4 实习:Hello World 37 4.1 Hello World程序. . . . . . . . . . . . . . . . . . . . . . . . . 37 4.2 实习题. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 II 汇编语言进阶41 5 C与汇编联合开发43 5.1 函数调用. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 5.2 全局与局部变量. . . . . . . . . . . . . . . . . . . . . . . . . . 45 5.3 编译与连接. . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 5.4 实习题. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 6 中断与I/O 49 6.1 中断. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 6.2 输入输出设备. . . . . . . . . . . . . . . . . . . . . . . . . . . 51 6.3 编写中断处理程序. . . . . . . . . . . . . . . . . . . . . . . . 51 6.4 实习题. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 7 实习:小游戏55 7.1 make工具. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 7.2 实习题. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 III 操作系统内核59 8 进程切换61 8.1 进程模型. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 8.2 进程的实现. . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 8.3 进程切换. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 8.4 中断嵌套. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 8.5 MiniOS中的进程切换. . . . . . . . . . . . . . . . . . . . . . . 68 8.6 操作系统实现原则. . . . . . . . . . . . . . . . . . . . . . . . 69 9 进程通信71 9.1 信号量. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 9.2 消息机制. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 9.3 消息机制的实现. . . . . . . . . . . . . . . . . . . . . . . . . . 76 9.4 调试消息内核. . . . . . . . . . . . . . . . . . . . . . . . . . . 78 目录7 10 实习:操作系统内核83 10.1 引导操作系统. . . . . . . . . . . . . . . . . . . . . . . . . . . 83 10.2 微内核与层次式操作系统结构. . . . . . . . . . . . . . . . . . 83 10.3 实习题. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 IV 轻量操作系统实现87 11 设备驱动程序89 11.1 设备驱动程序原理. . . . . . . . . . . . . . . . . . . . . . . . 89 11.2 键盘设备. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 11.3 屏幕设备. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 11.4 死锁的产生与预防. . . . . . . . . . . . . . . . . . . . . . . . 93 12 存储管理95 12.1 存储管理与系统调用服务进程. . . . . . . . . . . . . . . . . . 95 12.2 进程映像的创建与终止. . . . . . . . . . . . . . . . . . . . . . 97 12.3 替换进程映像. . . . . . . . . . . . . . . . . . . . . . . . . . . 98 13 文件系统101 13.1 文件与目录. . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 13.2 文件与目录管理. . . . . . . . . . . . . . . . . . . . . . . . . . 103 13.3 文件描述符. . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 14 实习:迷你操作系统109 14.1 一个简易的Shell . . . . . . . . . . . . . . . . . . . . . . . . . . 109 14.2 实习题. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 附录111 A vi常用命令113 B 虚拟机与外部的文件交换117
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值