我一直坚持书要从厚读薄,然后从薄到厚,这两个过程都应该是逻辑上的,先提取重点概要,然后在脑子里将其展开成为完整的知识体系,可惜计算机体系太过庞大,我们就是管中窥豹,掌握一些基本的概念罢了。这暂且不提,学习知识的时候要举轻若重,使用知识的时候要举重若轻,很多很多人把细碎当作是美德,这实在是可笑的,我见过水平越差的人越是把细碎的东西当作圣物对待,保持着一贯的做题思维,而从来不去想我怎么去使用,这样的人做了研究生成为了科研人员又能怎么样呢,我们不止是要看清细节,更重要的是看清脉络和体系,这也正是计算机结构体系的魅力所在,在这个整体的架构之上,我们去从功能、需求等等方面其查看其细节,才是真正的聪明,可惜我懂这一切也懂得太晚了。
说这一切的目的不是为了嘲讽谁或者抱怨什么现象,而是提醒大家,看这么多细碎的知识点的时候,一定一定不要脱离知识体系而存在,否则真的就变成了考试,而不是学习,希望学习之后有所得才应该是学习的目的所在。
第三章
数据格式
整数寄存器
数据传送
大多数情况中,MOV指令只会更新目的操作数指定的那些寄存器字节或内存位置,唯一例外是movl指令以寄存器作为目的时,他会把该寄存器的高位4字节设置为0。
movz零扩展,movs符号扩展
我们使用movl来实现四字节零扩展为8字节目的
内存寻址
条件码
跳转表
对于缺失的情况的处理就是使用默认情况的标号,对于一些范围会先平移值范围然后通过是否大于最大值判断是否在范围之外。跳转表存放于.rodata 中。下穿会跳转到自己所在标签后,继续跳转到下一个模块的标签处,直到返回。
数组
C语言数组特性
结构体注意对齐
对齐后的数据基本数据类型需要K字节,地址必须是K的倍数,K为该数据类型的最小字节数。
该数据的起始地址需要是自己的所占字节数的倍数,就是这个意思。所以尽量大尺寸数据在前。
第四章
Y86使用小端字节顺序存储
Y86指令集
寄存器ID 15(0xF)意味着无寄存器;
状态条件
如果是AOK,继续执行,否则停止执行。
分析指令编码
算数/逻辑运算
rmmovq指令
popq指令
cmov指令
JMP指令
执行call指令
ret指令
数据流中的具体含义
其他的一些指令
流水线
局限性:寄存器天花板
异常
我们在第四章讨论的是硬件异常的处理方式,注意与后面的异常处理区别,后面更多讲的是软件方面的异常处理。
处理器不能继续正常操作的条件称作异常。
原因:停机(当前)、访问非法地址(之前)、非法指令(之前);
期望行为:
- 完成一些指令:或者当前或者之前,取决于异常类型
- 抛弃其他指令
- 调用异常处理程序:类似于异常过程调用
当发生异常情况时就停机。
rmmovq异常:期望rmmovq引起异常,但其他指令不受它的影响;
非法指令:期望没有异常发生
维护异常的顺序:
- 为流水线寄存器增加状态字段
- 取指阶段设为“AOK”、“ADK”(当取指地址错误),“HLT”(停机指令)或者“INS”(非法指令)
- 解码和执行阶段传递值
- 访存阶段传递或设置为“ADR”
- 当指令进入写回阶段时,异常被触发
避免副作用
异常出现应该禁止状态更新:
- 非法指令转换为流水线气泡(除非状态指示为异常状态)
- 数据不会被写入无效的地址
- 防止条件码进行无效更新:在访存阶段检测异常;在执行阶段禁止条件码更新;必须在相同的时钟周期内发生
- 在最后阶段处理异常:当在访存阶段探测到异常时:在下一个时钟周期将气泡插入访存阶段;当在写回阶段探测到异常时:停止异常指令
其他实际的异常处理
调用异常处理程序:
- 将PC入栈:PC指向故障指令或下一条指令;通常和异常状态一起通过流水线传输;
- 跳转到处理程序的入口地址:通常是固定地址;被定义为ISA的一部分;
在软件中将其实现,即操作系统内核中。
第五章
第五章详见
第六章
存储器没什么好说的,我们需要从硬盘中加载程序到内存中,然后我们利用程序的局部性,这个优点帮助我们建立了一个完整的存储器层次结构,以带来更短的访存时间和更好的性能,(这几句话好像听起来不是很对)。
一张图读懂DRAM!(HIT是不是应该给袁老师交点版权费,PPT全是从人家的上面扒下来的)
两图读懂DRAM!
三图看懂DRAM!
多图看懂DRAM!
局部性
数据的空间局部性和时间局部性
指令的空间局部性和时间局部性