多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

指令寻址方式

指令寻址方式 引言本篇文章是基于MIPS指令集不同的指令集有着不同的寻址方式所以本篇文章也是仅供大家参考。指令格式寻址方式的开始我觉得应该从指令格式出发在MIPS里面有三种最基本的指令格式分别是R型寄存器型、I型立即数型和J型跳转型。这三种格式的划分依据是指令中操作数来源和寻址方式的不同而对于寻址来说I型指令和J型指令是关键我们先从I型指令说起。首先我们的指令长度均为32位的这个是MIPS指令集的一个特点也就是说无论哪种格式的指令在内存中占用的空间都是固定的4个字节这大大简化了指令的取指和译码过程。不过现在更加新的指令集是混合的既有16位也有32位例如ARM的Thumb指令集就同时支持16位和32位指令这样做的好处是在保证功能的前提下可以压缩代码体积。对于I型指令来说32位的指令集给立即数留下的空间只有16位所有一旦立即数超过了16位我们就无法存储下来这时就需要借助寄存器来间接完成大立即数的装载这也是后面要讲到的加载大立即数寻址方式。立即数是什么在c里面我们可以理解为const int a 8就是一个常数但是在指令集里面这个既可以是一个数也可以是一个地址但是地址不都是32位的嘛~~~不要着急这不是有寻址方式嘛~~~首先我们要解决怎么存下一个32位的立即数。我们的寄存器大小就是32位的我们这里采取分批操作的方式。我们先把立即数最高的16位存入一个寄存器里面同时把寄存器里面的低16位清零然后通过加法或者逻辑或的操作把立即数的低16位放入寄存器里面这个样子就保存了一个32位的立即数。那如果是64位的立即数呢那就用两个寄存器嘛~~~对于J型指令来说我们一般分两中情况第一个是直接跳转。我们这里要区分一个概念形式地址和有效地址形式地址我们一般记作A这个不是一个正常的地址而是需要通过指令集中的特定寻址方式转变成有效地址而有效地址也不是最后的真实地址因为在操作系统里面还有映射的操作但是至少有效地址是我们程序员可以看的懂得地址了。直接跳转这里很明显就是形式地址因为操作OP占了6位而直接地址占了26位我们的地址都是32位的所以不是最后的有效地址。在程序的运行里面有一个非常重要的寄存器叫程序计数器PC这个寄存器的作用就是保存下一条将要执行的指令的地址当这个指令被取出来的时候就要加1。注意一下这个加1不是数值上的加1因为一条指令的大小是32位4个字节那么我们下一个指令的地址就是加4个字节所以在地址上呈现出来的是地址加4。那么直接跳转就是将PC的最高4位和直接地址的26位拼在一起合起来一共是30位而剩下的两位全部补0原因就是我们的地址一定是4的倍数指令是4字节那么最后两位一定是0。第二个是分支寻址简单来说就是if的条件判断。这里的指令格式是I型的当条件成立的时候就会在当前的PC4下加上立即数的偏移量但是因为立即数是16位的所以我们需要通过符号扩展因为立即数有正负号扩展成32位然后因为要是4的倍数所以左移两位把最后两位置为0最后算出来的不是最终跳转地址而是相对于下一条指令的偏移量所以是PC4加上偏移量寻址模式其实在指令格式里面我们已经说明了两种寻址模式我们可以统一称之为伪直接寻址因为都是给定的是形式地址最后通过转化变成了有效地址。立即寻址操作数直接包含在指令中作为指令的一部分。这种情况下操作数的值是一个立即数即固定值。也就是我们说的I型指令。立即寻址模式通常用于加载立即数到寄存器中或者用于算术和逻辑运算这个寻址方式的最大优点就是速度快因为数据就在指令里面根本就不需要在其他地方寻找。而缺点也是相当的明显因为立即数只有16位所以可以操作的数是很有限的。直接寻址指令中包含一个实际的内存地址这个地址直接指向内存中的一个位置从中读取或写入操作数CPU直接使用这个地址从内存中读取操作数在 MIPS 指令集中直接寻址模式通常用于访问内存中的特定地址。在直接寻址中指令中直接包含了要访问的内存地址这个访问的速度就要慢很多因为需要访问一次内存间接寻址指令中给出的地址码是存放操作数有效地址的内存单元地址也就是说我们拿到主存中的地址之后我们还要继续访问一次内存才可以得到操作数并且有些情况之下我们还会涉及到多重访问这个对于内存访问的次数过多会导致速度很慢所以我们一般用到的是另一种间接寻址。但是优点也就是我们的操作数存储在内存里面这个操作数可以是32位的也可以是64位的大小就不会受到指令大小的限制。寄存器间接寻址通过寄存器间接寻址实现。这意味着指令的操作数地址不是直接给出的而是存储在一个寄存器中处理器会访问该寄存器内容所指向的内存地址来获取实际操作数。这个样子会减少一次内存的访问从而转化为一次寄存器的访问。但是这个也是有缺点的因为MIPS指令集里面只有32个寄存器而且还要排除一些特定的寄存器比如变址寄存器$zero.....所以寄存器的数量会有限制。变址寻址我们在c语言里面访问数组的时候大多数会涉及到循环一个一个内存地址的访问正是我们变址寻址需要解决的。这里我们涉及到了一个变址寄存器这个寄存器里面存储的是偏移量而偏移量具体是多少是由我们用户来交涉的所以这个变址寻址是完全面对于用户的一个寻址方式。 他的公式是EAI A这个I就是我们寄存器里面的变量表示的是偏移量而A表示的是基地址是保持不变的相当于是数组的起始地址。基址寻址这个和变址寻址非常的相似这里涉及到了一个新的寄存器就是基址寄存器BR这个寄存器里面保存的就是基地址因此有公式就是EA BR A这里不变的是A也就是偏移量。比如有一个这个结构体struct Person {int age; // 偏移 0double score; // 偏移 8};那么当我们每一次访问score的时候都是偏移8个字节而起始地址会发生变化这个时候我们就会涉及到基址寻址。总结以上就是我们基础的地址寻址方式本篇文章到这里就结束了希望可以帮助大家理解~~~
返回列表