02计算机组成原理-寻址方式总结
1.寻址方式总结
1.1数据寻址
去寻找本条指令的操作时的有效地址(注意地址不要局限于内存地址,像寄存器的编号也是地址 像立即数就可以直接给出)
1.2立即(数)寻址
立即(数)寻址:操作数直接包含在指令中,作为指令的一部分。这种情况下,操作数的值是一个立即数,即固定值。你直接用即可,不用再去寻址了。
立即寻址模式通常用于加载立即数到寄存器中,或者用于算术和逻辑运算。MIPS 指令集并没有像某些其他指令集那样直接支持"MOV"指令,但可以通过其他方式实现寄存器到寄存器的数据移动。
例如下图:把我们想要的立即数通过加zero寄存器里面的数据(固定是0),到我们指定的寄存器t0。不就相当于把16放到t0里面吗,从而实现把一个立即数放到相应的寄存器,这个过程我们发现被操作数16我们没有从某个地方去寻址得到的。

优点:速度快因为不用去内存里面找数据(不需要访存)
缺点:位数有限 立即数的大小是有限的
1.3直接寻址
直接寻址:指令中包含一个实际的内存地址,这个地址直接指向内存中的一个位置,从中读取或写入操作数,CPU直接使用这个地址从内存中读取操作数。在 MIPS 指令集中,直接寻址模式通常用于访问内存中的特定地址。在直接寻址中,指令中直接包含了要访问的内存地址。(EA=A)
直接寻址在 MIPS 指令集中是一种简单而直接的方式来访问内存中的特定位置。然而,由于其限制和可能的性能影响,它通常只在需要直接访问特定内存地址时使用。所以其实并不常用。

如果不采取任何计算由我们MIPS的指令格式, lw占6位,$t0占5位,假如说不采取任何计算后面的地址最多只能占21位,我们知道如果是32位机器我们最大的地址就是到232-1的,所以这里地址的表示也是会受位数的限制。
优点:简单(不需要任何复杂的计算)
缺点:限制了寻址的范围(位数不够,有的地址表示不出来)
1.4寄存器寻址
寄存器寻址:把操作数存储在某个寄存器中而不是在内存中了。所以指令中通常包含一个寄存器标识符,处理器从该寄存器中读取或写入操作数。(EA=A,这个A是寄存器编号)
寄存器寻址通常比内存寻址更快,因为寄存器位于 CPU 内部,访问它们不需要像访问内存那样经过复杂的内存子系统。
下面这个指令就是MIPS下的一个典型的寄存器寻址的指令:把寄存器t3器里存的数据和寄存器里存的数据相加放进$t1。

MIPS 指令集中的寄存器寻址非常灵活,因为大多数指令都可以接受来自寄存器或立即数的操作数。寄存器寻址不仅限于算术和逻辑运算,还可以用于数据移动、比较、跳转等操作。寄存器寻址是 MIPS 指令集中非常基础和重要的寻址模式,它允许 CPU 快速、高效地处理数据,而不需要频繁地访问内存。
优点:快,不需要访问内存,简单
缺点:个数有限,造价昂贵
1.4间接寻址
间接寻址:指令中给出的地址码是存放操作数有效地址的主存单元地址。图所示的是单级间接寻址过程,还可有多重间接寻址。EA=(A),加括号代表该地址里面存的数据。
比如说你要去菜市场买菜,但是你不知道菜市场的地址,但你的朋友知道才菜市场的地址,你就可以先去你朋友家里问道菜市场的地址,再前往菜市场。

例如上图:先去图中的有效地址,再去操作数的地址。就多麻烦了一步。
在这个过程中访问内存2次,第一次访问到图中的有效地址,再访问到操作数的地址。
寄存器间接寻址:通过寄存器间接寻址实现。这意味着指令的操作数地址不是直接给出的,而是存储在一个寄存器中,处理器会访问该寄存器内容所指向的内存地址来获取实际操作数。实际上就是把间接地址换成寄存器的编号。如下图:

寄存器间接寻址和间接寻址的区别就是存放地址的地址的地方在主存还是寄存器,但它们的操作数都是存放在主存中的。只是存操作数的地址一个是存在寄存器里一个是存放在内存中。
优点:扩大了寻址范围。
缺点:速度慢,因为要多次访问内存。寄存器间接寻址稍微好一些,但是又有寄存器的数目限制。
1.5变址寻址
变址寻址:以某个寄存器(变址寄存器)的内容为偏移量,加上指令中给出的基地址来计算操作数的实际地址。这种寻址模式在处理数组或循环时特别有用,因为它允许程序在不需要修改基址寄存器的情况下,通过改变偏移量来访问内存中的不同位置。
操作数的有效地址EA=(I)+A,其中(I)表示变址寄存器I中的内容,A一般是指令给出的。变址寄存器是面向用户的,在程序执行过程中,变址寄存器的内容可由用户改变(作为偏移(量),形式地址A不变(作为基地址) 。例下图:


优点:扩大了寻址范围,虽然形式地址A(放在指令中的)的位数有限,但是变址寄存器是32位的数,一相加就变大了;在数组处理过程中,把A设为数组的首地址 不断改变IX(变址寄存器一般用这个表示)的内容,得到一个数组某元素的地址。
缺点:寄存器数量有限
1.6基址寻址
基址寻址(Base Addressing):类似于变址寻址,但这里的基准是固定的基址寄存器(BR)---基地址(不变),加上一个偏移量(A)得到操作数地址。有效地址是通过将基址寄存器的内容与指令中给出的偏移量相加而得到的。基址寄存器的内容在程序执行过程中通常保持不变,而偏移量可以变化。EA=(BR)+A(BR是某个寄存器里面的值)。
基址寻址注意区分与变址寻址的异同,变址寄存器中是以某个寄存器(变址寄存器)的内容为偏移量(变化),加上指令中给出的基地址来计算操作数的实际地址。(不变)
多道程序分配存储空间(同时运行很多个程序)会用到基址寻址。

在MIPS架构中我们用的多的寻址是这么五种:
1.立即数寻址
2.寄存器寻址
3.基址寻址
4.PC相对寻址
5.伪直接寻址
2.并行,指令和同步
当任务之间相互独立的时候,任务的并行执行是比较容易的。而大多数时候,往往是很多任务要协作进行,共享资源进行读取操作。当多个任务共享资源并进行读写操作时,必须确保它们之间以一种有序且安全的方式进行协作,防止数据不一致和错误结果。
数据竞争(Data Race)是指在多线程或多进程环境下,当两个或多个任务同时访问和修改同一内存位置,并且至少有一个是写操作时,如果没有采取任何同步措施来控制访问顺序,则可能导致不可预测的结果。
假设我们有两个线程(或任务),线程A和线程B,它们都需要访问和修改一个共享的整数变量 x 。
cpp
int x = 0; // 共享变量,初始化为0
// 线程A的代码
void threadA() {
x = 1; // 线程A将x设置为1
}
// 线程B的代码
void threadB() {
int y = x; // 线程B读取x的值到y中
if (y == 0) {
printf("x is zero\n");
} else {
printf("x is not zero\n");
}
}
现在,假设这两个线程几乎同时运行。线程A可能刚刚将 x 设置为1,而线程B正在读取 x 的值。没有同步机制的情况下,线程B可能会读取到一个中间状态或旧的 x 的值(比如0),即使线程A已经修改了它。
为了确保数据的一致性和正确性,防止数据竞争和条件竞争(race conditions)的发生,我们发明了同步机制。
同步机制是确保在多线程或多处理器环境中正确协调共享资源访问的关键技术。这些同步机制依赖于硬件提供的同步指令,这些指令允许软件开发者在编程时创建互斥区域,确保在任何时候只有一个线程或处理器能够访问特定的代码段或数据。
加锁(lock)和解锁(unlock)是同步机制中最基础的操作。
硬件提供的同步指令是实现加锁和解锁操作的基础。
除了简单的加锁和解锁操作外,更复杂的同步机制如条件变量、信号量、读写锁(操作系统中会详细见到这些东西)等也是基于类似的原理实现的。这些机制提供了更细粒度的控制和更灵活的同步方式,以适应不同的并发场景和需求。
虽然同步机制可以有效地协调共享资源的访问,但它们也可能引入性能开销和死锁等问题。因此,在使用同步机制时,需要仔细考虑其适用场景和潜在风险,并采取适当的措施来避免或解决这些问题。
3.小结
在设计存储程序计算机时,遵循的两个核心原则是将指令视为数据来处理,并采用可修改的存储器。基于这些准则,计算机可以广泛应用于各种领域,如环境科学、经济学分析和文学创作等。构建计算机指令集需要精心权衡指令数量、执行指令所需的时钟周期数以及时钟速度等因素。针对这一挑战,设计者通常遵循三条指导原则:
- 简洁源于规整:MIPS指令集就是一个例子,它通过所有指令长度统一、算术指令固定使用三个寄存器操作数且寄存器字段位置标准化等规整性设计,实现了简洁性和一致性。
- 小即是快:为了追求更高的执行速度,MIPS架构选择仅包含32个寄存器,以减少访问时间并简化硬件设计。
- 折衷与优化:在MIPS中,体现为在保持指令长度相同的同时,提供对大地址和常数值的支持。此外,MIPS还体现了"加速大概率事件"的设计理念,例如条件分支使用PC相对寻址,以及支持大常数的立即数寻址方式。在机器语言之上的是汇编语言层,它更易于人类阅读和编写。汇编器负责将汇编代码转换成机器可以理解的二进制格式,并通过引入符号指令和隐式细节管理等方式扩展了指令集的功能,例如拆分大常量和地址、为常用指令变体定义专门的助记符等。这种隐藏底层实现细节的做法,进一步展示了计算机体系结构设计中的抽象思想。
大概先写这些吧,今天的博客就先写到这,谢谢您的观看。