CPU的功能:控制指令执行。
指令执行有五种基本操作:取指、译码、取数、运算、存数。
数据通路五个阶段:取指、译码和读寄存器、执行、访存、回写。
解决冒险:
①操作系统:合理地管理、调度计算机的硬件资源。存储器作为一种空间资源也由OS来管理。
CPU执行的程序:总是在操作系统和用户程序之间切换。主存中同时要存储OS和用户程序。磁盘中也要存储OS和用户程序。
CPU中的存储器管理部件MMU(分页内存管理单元)协助OS完成存储器访问。
②Hello的执行过程:
③进程(线程):操作系统对运行程序的抽象
④32位程序在内存中的存放
⑤虚拟存储管理模式:分页模式
把内存分成固定长且比较小的存储块,每个进程也被划分成固定长的程序块。程序块(页/page)可装到存储器可用的存储块(页框/page frame)中。无需使用连续页框来存放一个进程,操作系统为每个进程生成一个页表,通过页表实现逻辑地址向物理地址的转换。(逻辑地址:程序中指令所用的地址;物理地址:存放指令或数据的实际内存地址)
⑥页式虚拟存储器
进程划分成相同长度的程序块(页),称为虚页;主存分为大小相同的存储块(页),称为实页;主存按页顺序编号,每个独立编址的程序空间有自己的页号顺序,通过调度辅存中程序各页可离散装入主存不同实页位置。
CPU执行指令时,首先需将逻辑地址转换为主存的物理地址,地址转换由CPU中的MMU实现。
⑦快表TLB
每次虚拟存储器的访问带来两次存储器访问,一次访问页表,一次访问所需数据(或指令),因此使用Cache存储部分活跃的表项,他包含了最近使用的那些表项,TLB内容包括:标记(虚页号)、数据块(实页号)、有效位、修改位。(TLB一般采用全相联或者组相联)
体系结构用来描述一个用于编程的抽象机器,而不是一个机器的具体实现。一般而言,一个CPU的体系结构包括一组指令集加上一些寄存器的知识,指令集与体系结构这两个术语基本上是同义词。
汇编语言是CPU原始二进制指令可工人书写和阅读的版本。与大多数汇编语言相同,MIPS汇编语言以行为单位,一行结尾表示指令的结束,约定忽略“#”字符之后的内容作为注释,一行中可以有多条指令,但中间需要使用分号分割开来。单词后面紧跟一个“:”作为一个标签,用来定义代码中的入口点和命名数据区的一个存储位置。
MIPS通用寄存器有三十二个,其中有两个的用法与其他不同。在其他的使用方面,所有寄存器都是一样的,可以再任何一个指令中使用。
在MIPS体系结构中,程序计数器不是寄存器,jal指令的返回地址是其后的下下一条指令,如前文所述紧跟调用指令的下一条指令是调用指令的延迟槽(按照规定该指令必须在分支目标指令之前执行),调用的延迟槽指令很少被浪费,因为经常可以用来建立调用的参数。
MIPS里没有状态码,状态寄存器或CPU的其他内部状态对用户级程序没有任何影响。
hi和lo这两个寄存器大小的结果端口与整数乘法运算相关,他们不是通用寄存器,除了乘除法指令之外没有其他用途。但是定义向这两个端口插入任何值的指令,这对于回复一个被终端的程序的状态是必需的。
通用寄存器的习惯命名和用法
详细细节还请参考See MIPS Run Linux 2.3处。
MIPS CPU采用了一个专用的整数乘法部件,没有集成到主流水线中,乘法单元的基本操作是将两个寄存器大小的值相乘得到一个两倍于之前寄存器大小的结果,存放在乘法单元里面,指令mfhi、mflo分两半将结果传送到指定通用寄存器。乘法的结果返回没有快到自动供随后指令使用的程度,因此乘法的结果寄存器总是互锁的,在乘法运算完成之前任何企图读取结果的操作都将导致CPU停下来等待乘法操作结束。
整数乘法器也可以执行两个通用寄存器的除法操作,这时lo寄存器用来存放结果,hi寄存器用来存放余数。
整数乘除操作从不产生异常:即使是除以零也不会发生异常,而编译器常常会产生额外的指令检查和捕获错误,特别是被零除的错误。
此外。还定义了mthi、mtlo用来将通用寄存器的值传送到乘法单元的内部寄存器,这对于从中断返回时恢复hi和lo的值是必不可少的,但在其他地方可能都不会用到。
如前文所言,MIPS只用一种寻址方式(目前已不完全正确),任何加载或存储操作的机器指令都可以写成:lw $1, offset($2)。
你可以用任何寄存器作为目标和源寄存器,偏移量offset是一个有符号的16位的数字,加载所用的程序地址是$2寄存器的值和offset的和。这种寻址方式一般已足够存取C语言结构体的一个成员,同时也支持实现以常量为索引的数组,用堆栈指针或者帧指针存取函数的局部变量,并为静态和外部变量提供一个以gp的值为中心的适当大小的全局空间。
汇编器提供一个类似简单直接寻址的方式来加载一个在连接时刻才能确定地址的内存变量的值,其余更负载的寻址方式都必须通过多个指令的序列实现。
我们在此只讨论整数数据类型。
字节byte和半字halfword的加载有两种方式,符号扩展指令lb和lh指令将数值存放在32位寄存器的低位,并将高位用符号位(字节的第七位,半字的第十五位)的值来填充。这样就正确地将一个有符号整数转换成了一个32位的有符号的整数。
无符号的指令lbu和lhu用零来扩展数据,将数据值加载到32位寄存器的低位中,并用零来填充高位。
汇编器在下面的方面为你提供帮助生成指令:
MIPS中程序地址与物理地址分开,CPU可以运行在两种特权级之一上:用户态和核心态。但是MIPS的一个特点是从核心态到用户态的变化并不改变操作的行为,只是有时候某些操作被认为非法。在用户态,地址最高位为一的任何程序地址都是非法的,而且有些指令在用户态也会导致异常。
kuseg(低端2G):用户态可用的地址,无MMU的处理器无法直接移植。
kseg0(512M):通过Cache存取,无MMU系统中用于存放程序和数据,有MMU的系统用于存放操作系统核心。
kseg1(512M):系统重启时能正常工作的地址空间,复位入口(0x1FC0 0000),用于存取初始程序ROM。
kseg2(1G):只能在核心态下使用并且要通过MMU的转换。
具体细节地址使用参考 See MIPS Run Linux 2.8处。
简单系统的寻址
MIPS的程序地址从来不会和物理地址简单相等,但简单的嵌入式只是用kseg0和kseg1的地址,他们与物理地址有着非常简单的映射关系。
从0x2000 0000(512M)开始向上的物理地址空间在上述简单情形下没有任何的映射,大多数简单的系统所有地址都映射到512M以下。可以使用TLB的方式来存取512M以上的地址。
核心与用户特权级
在核心特权级下(CPU启动时),可以做任何事情。在用户态下,2G(最高位置位的)以上的程序地址是非法的。如果CPU有MMU,就意味着所有的用户地址在真正到达物理地址之前必须经过MMU的转换,从而使得操作系统有能力防止用户程序失去控制。
另外,有些指令(特别是操作系统需要的那些CPU控制指令)在用户态是非法的。
当你改变核心态/用户态特权级模式位时,并不改变任何行为的解释,仅仅是某些功能在用户态下禁止,这就意味着核心态下可以做与用户态一样的事情。
MIPS体系结构让一些流水线的特点可见,把任务交给程序员或者编译器:
全几把是鸟语,自己看去吧,《IDT R30xx Family Software Reference Manual》Chapter3。
还是稍微复习一下,因为当时这块也只懂个大概。
在运算功能之外,处理器需要一些部件处理中断、配置选项以及需要某种机制来监控诸如高速缓存和定时器等功能,因此就产生了协处理器一词。
MIPS CPU 协处理器 CP0 功能:
协处理器:
协处理器通常表示处理器的一个可选部件,负责处理指令集的某个扩展。
MIPS CPU 控制寄存器请移步到具体标准处查看。
再后面好像就真得瞄一眼鸟语书了。
仔细阅读,不转载了。
预处理器命令
内存模型、指针、地址
助教的提示TIPS:
第一段没啥理论要看的需要用的时候查一下就行了。
这张就结合计组那张图一起看就行了。
①静态内存
全局变量、全局数组、静态变量、常量均存于已初始化数据段或未初始化数据段;
局部变量、局部数组均存于栈上;
此外,函数调用的信息也存于栈上。(可能用于链接就得拎出来)
②动态内存
动态内存分配就是程序运行在堆上进行的内存分配。
一般来说堆上分配内存的效率比栈上分配内存的效率低,因此静态内存分配是问题空间已知时较好的选择。
The Missing Semester of Your CS Education
Vim Tutorial
Learn Git Branching
GCC参数详解
An Introduction to GCC
Make命令教程
GCC Make