上一篇文章里主要介绍了几种机器模型,有机器模型后需要知道计算机有什么样的基本指令,接下来就来看看指令都有哪些类型。
[注]:以下指令主要为 MIPS 指令。
类型 | 指令 |
---|---|
数据传输 | LD、ST、MFC1、MTC1、MFC0、MTC0 |
计算 | ADD、SUB、AND、OR、XOR、MUL、DIV、SLT (Set Less Than)、LUI (Load Upper Immediate) |
控制流 | BEQZ、JR、JAL、TRAP、ERET |
浮点型运算 | ADD.D、SUB.S、MUL.D、C.LT.D (Compare less than for double)、CVT.S.W (Conversion from a single precision floating point number to an integer number or interger word) |
多媒体类(单指令多数据) | ADD.PS、SUB.PS、MUL.PS、C.LT.PS |
字符串 | REP MOVSB (x86) (Copy one string into another string) |
寄存器寻址是由寄存器保存操作数本身。
Addressing Mode | Instruction | Function |
---|---|---|
Register | Add R4, R3, R2 | Regs[R4] <- Regs[R3] + Regs[R2] |
如上表指令 Add R4, R3, R2
,意味着将寄存器 R3
和 寄存器 R2
保存的值加在一起并存入寄存器 R4
中。这期间并没有堆内存的访问,这里虽然在说的是内存访问方式,但实际上不一定会对内存访问,如果有足够的寄存器的话,那么则不需要对内存访问,因为寄存器可以保存需要操作的所有数据,而且使用寄存器的效率要比访问内存快得多。
指令中在操作码字段后的数字(操作数)表示操作数本身,即为立即寻址。
Addressing Mode | Instruction | Function |
---|---|---|
Immediate | Add R4, R3, #5 | Regs[R4] <- Regs[R3] + 5 |
[注]:立即寻址是最快的寻址方式。
位移寻址用一个寄存器保存的值加上一个变量值得到一个具体地址,并根据该地址从主存中获取数据作为操作数。
Addressing Mode | Instruction | Function |
---|---|---|
Displacement | Add R4, R3, 100(R1) | Regs[R4] <- Mem[100 + Regs[R1]] |
寄存器间接寻址与位移寻址很类似,区别在于使用寄存器寻址时没有加偏移变量,只能读取存储在寄存器中地址对应的值。
Addressing Mode | Instruction | Function |
---|---|---|
Register Indiect | Add R4, R3, (R1) | Regs[R4] <- Mem[Regs[R1]] |
绝对寻址在现代计算机架构中并不常见,只有在一些古老的架构中使用,它会根据一个具体的值作为地址去主存中获取数据作为操作数。
Addressing Mode | Instruction | Function |
---|---|---|
Absolute | Add R4, R3, (0x475) | Regs[R4] <- Regs[R3] + Mem[0x475]] |
MIPS
中没有这样的寻址方式,这种寻址方式是存在其它架构中的。它的指令中的操作数可以这样获取,首先有一个保存着主存地址的寄存器,接着根据该地址去主存中获取数据,而获取的数据本身也是一个地址,然后继续用获取到的地址再去主存中拿取真正的数据,作为操作数使用。看起来很花哨。
Addressing Mode | Instruction | Function |
---|---|---|
Memory Indirect | Add R4, R3, @(R1) | Regs[R4] <- Regs[R3] + Mem[Mem[R1]]] |
程序计数器相对寻址也可以叫做 PC
指针相对寻址,该寻址方式会根据 PC
的值加上一个偏移量得到数据的具体地址,并根据该地址从主存中索引得到操作数。
这样看起来多此一举,为何不直接使用寄存器保存基地址而是使用一直在变化的 PC
寄存器呢?这可以让访问数据时不必知道代码被加载的具体位置,当不确定代码的具体的位置时,但却知道程序执行的位置或者清楚当前正在执行的指令是什么,就可以根据 PC
指针来计算数据的存储地址。
Addressing Mode | Instruction | Function |
---|---|---|
PC relative | Add R4, R3, 100(PC) | Regs[R4] <- Regs[R3] + Mem[100 + PC] |
在 x86
架构中放缩寻址也称为放缩索引基本模式 Scaled Index and Base Mode——SIB
,该寻址方式可以让给寄存器值乘以一定的倍数,按照这样的计算结果在主存中寻址。
Addressing Mode | Instruction | Function |
---|---|---|
Scaled | Add R4, R3, 100(R1)[R5] | Regs[R4] <- Regs[R3] + Mem[100 + Regs[R1] + Regs[R5] * 4] |
数据类型:
4
为二进制表示。IEEE 754
。Packed Vector Data
)Addresses
)大小:
目前常用的机器数据大小(位宽)有八位、十六位、三十二位、六十四位。
当具备了上述内容后,接下来的就需要考虑设计出不同指令的编码,设计编码有个基本需要确定的就是要设计成固定长度的指令还是可变长度的指令。而大多数精简指令集架构的指令都是固定长度的。
定长指令每条指令的长度是一样的,这样容易编码。
精简指令集架构中常见的有这些的指令都是固定长度的,如 MIPS
、PowerPC
、SPARC
、ARM
等。
[注]:MIPS 中每条指令都是 4 字节长度。
指令的长度可以变化,最大化的利用内存和 Cache
,指令不必为了凑齐固定的长度而占用无效的位。
复杂指令集中常见的有这些指令都是可变长的,如 IBM 360
、x86
、Motorola 68k
、VAX
等。
[注]:x86 指令长度可以在 1 字节到 17 字节。
现在的指令集架构逐渐在不同类型上产生一些交点,人们可以构建出主要是固定的或压缩的指令集架构。固定长度指令我们已经很清楚了,就是指令长度不变,而压缩指令则是指编码的长度比较小,存储在存储器中,当 CPU
加载指令到内存中时开始解压这些压缩指令,指令长度将会增加。
如,MIPS16
实际上是 MIPS
指令集,其中有 32
位指令和 16
位长度指令两种。THUMB
指令集是 ARM
指令集架构,同样是大部分指令长度固定或压缩的。
另外还有 PowerPC
和一些 VLIW
(Very Long Instruction Word),他们会有一个压缩的指令格式,代码在存储器中会占用很小的空间,但到了内存或者加载到 Cache
后将会解压指令,将会占用较大的空间。
超长指令可以将多个固定长度指令放进一个固定长度的捆绑指令中。如 Multiflow
、HP/STMicro Lx
指令集架构,如今 HP/STMicro
的技术主要应用于打印机中。
Intel 64
和 IA-32
指令集架构的指令编码由指令前缀、主要操作码 (最多三个字节)、寻址方式(寻址描述符由 ModeR/M
字节(8 bit
) 构成,有时候由 SIB
(Scale-Index-Base
) 表示寻址方式)、偏移(如有的话)和立即数字段(如有的话)组成。
因此,前面看到的 ADD
、MOV
等这些都只是一条指令中的前缀(这下了解了梅)。
MIPS
的每条指令长度都是 4
个字节,必须在着 4
个字节里把所有需要的内容都放进去。
下面是现实存在的几种指令架构的指令类型和基本信息以及主要应用场景。
下一篇文章《【计算机体系结构-04】流水线:基础与中级概念 (Pipelinling: Basic and Intermediate Concepts)》
觉得这篇文章对你有帮助的话,就留下一个赞吧*^v^*
请尊重作者,转载还请注明出处!感谢配合~
[作者]: Imagine Miracle
[版权]: 本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
[本文链接]: https://blog.csdn.net/qq_36393978/article/details/128733034