[嵌入式系统-37]:龙芯1B 开发学习套件 -7-MIPS指令集

目录

一、MIPS指令分类

二、常用指令详解

三、常用MIPS指令集及格式:

四、CPU内部的32个寄存器:


一、MIPS指令分类

MIPS(Microprocessor without Interlocked Pipeline Stages)指令集是一种广泛用于教学和嵌入式系统的指令集体系结构。MIPS指令可以分为以下几类:

  1. 算术指令(Arithmetic Instructions):这些指令执行算术运算,如加法、减法、乘法和除法。例如,ADD(加法)、SUB(减法)、MUL(乘法)和DIV(除法)等。

  2. 逻辑指令(Logical Instructions):这些指令执行逻辑运算,如逻辑与、逻辑或、逻辑非和位运算等。例如,AND(逻辑与)、OR(逻辑或)、NOT(逻辑非)和XOR(异或)等。

  3. 数据传输指令(Data Transfer Instructions):这些指令用于数据的加载和存储,包括从内存到寄存器的加载和从寄存器到内存的存储。例如,LW(加载字)、SW(存储字)等。

  4. 分支指令(Branch Instructions):这些指令用于控制程序的流程,包括条件分支和无条件分支。例如,BEQ(分支相等)、BNE(分支不相等)、J(跳转)等。

  5. 跳转指令(Jump Instructions):这些指令用于无条件改变程序的执行位置。例如,J(跳转)、JR(寄存器跳转)等。

  6. 访存指令(Memory Access Instructions):这些指令用于直接访问内存,而不是通过寄存器。例如,LBU(加载字节无符号)、SB(存储字节)等。

  7. 特权指令(Privileged Instructions):这些指令只能在特权模式下执行,用于操作系统和硬件管理。例如,SYSCALL(系统调用)、HALT(停止)等。

  8. 浮点指令(Floating-Point Instructions):这些指令用于执行浮点运算,如浮点加法、浮点乘法等。例如,ADD.S(单精度浮点加法)、MUL.D(双精度浮点乘法)等。

这些是MIPS指令集的主要类别,每个类别下又有许多具体的指令。

二、汇编编程

2.1 示例

MIPS汇编编程涉及使用MIPS汇编语言编写程序,该程序会在MIPS体系结构的计算机上执行。以下是一些关键的概念和示例,帮助你入门MIPS汇编编程:

1. 寄存器:

MIPS体系结构有32个通用寄存器,每个寄存器都用符号表示。例如,符号表示。例如,t0表示临时寄存器0,$s1表示保存寄存器1。

# 示例:将值存储到寄存器
LI $t0, 10   # 将立即数10加载到$t0

2. 内存访问:

MIPS使用Load(LW)和Store(SW)指令来读取和写入内存。

# 示例:从内存读取数据
LW $t1, 0($t0)   # 从地址($t0 + 0)读取数据到$t1

# 示例:将数据写入内存
SW $s0, 4($t2)   # 将$s0的值写入地址($t2 + 4)

3. 分支和跳转:

MIPS提供条件分支和无条件跳转指令,例如BEQ(Branch if Equal)和J(Jump)。

# 示例:条件分支
BEQ $s0, $t0, label_equal  # 如果$s0和$t0相等,则跳转到label_equal

# 示例:无条件跳转
J label_jump   # 无条件跳转到label_jump

4. 过程调用:

过程调用涉及将参数传递给函数、调用函数以及从函数中返回。在MIPS中,参数通常通过寄存器传递。

# 示例:过程调用
LI $a0, 5       # 将参数5传递给函数
JAL my_function # 调用函数my_function,JAL会保存返回地址到$ra寄存器

5. 伪指令:

前面已经提到了一些常见的MIPS伪指令,它们在汇编阶段被转换为真实的MIPS指令。

# 示例:使用伪指令
NOP             # 无操作
MOVE $t0, $s0   # 移动寄存器值
CLEAR $t1       # 清零寄存器值

6. 示例程序:

下面是一个简单的MIPS程序,演示了寄存器、内存访问、分支和过程调用:

.data
message: .asciiz "Hello, MIPS!\n"

.text
main:
    # 输出字符串
    LI $v0, 4            # 调用系统服务4,用于打印字符串
    LA $a0, message      # 将字符串地址传递给参数
    SYSCALL              # 执行系统调用

    # 退出程序
    LI $v0, 10           # 调用系统服务10,用于退出程序
    SYSCALL

# 示例函数
my_function:
    # 函数体...

    JR $ra               # 返回,使用$ra中保存的返回地址

以上是一个简单的示例,涵盖了一些基本的MIPS汇编编程概念。在实际编程中,你可能会遇到更复杂的任务,但这个起点可以帮助你理解和掌握MIPS汇编语言。

2.2 函数定义

MIPS汇编中的函数定义通常遵循一定的约定和结构。下面是一个简单的MIPS函数定义示例:

# 函数声明
my_function:
    # 函数体

    # 返回
    JR $ra               # 返回,使用$ra中保存的返回地址

让我们来解释一下:

  1. 函数声明:在MIPS汇编中,函数声明由标签表示,例如 my_function:。函数的开始由该标签标识。

  2. 函数体:在函数的标签之后,是函数的实际代码内容,包括各种指令、操作和逻辑。

  3. 返回指令:在函数体的结尾通常会有一个返回指令,用于将控制流返回到调用函数的地方。在MIPS中,使用JR $ra指令来实现返回操作,这里的$ra寄存器保存了函数调用前的返回地址。

在实际编程中,函数可能会有参数传递、局部变量分配和其他复杂的逻辑。参数通常通过寄存器传递,而局部变量通常被存储在堆栈上。这些方面会在更复杂的函数中涉及到,但基本的函数结构如上所示。

2.3 段定义

在MIPS汇编中,段(section)通常用来定义不同类型的数据和代码。常见的段包括.data段和.text段。

  1. .data 段.data段用于定义静态数据。在这个段中,你可以声明和初始化全局变量、字符串、数组等。这些数据在程序执行过程中通常是不变的。
.data
message: .asciiz "Hello, MIPS!\n"
array: .word 1, 2, 3, 4, 5

  1. .text 段.text段用于存放程序的指令部分,也就是代码段。在这个段中,你可以定义函数、指令序列等。程序执行时,控制流会从.text段开始执行指令。
.text
main:
    # 函数主体
    # 调用其他函数

这些段的划分有助于组织和管理程序的不同部分,使得程序的结构更加清晰明了。在实际编程中,你会在这些段中定义和实现程序的各种功能和逻辑。

2.4 伪指令

在MIPS汇编中,伪指令(pseudo-instruction)是一种不是真正的机器指令,而是由汇编器处理并转换为一系列真正的机器指令的指令。它们提供了一些方便的功能和语法糖,使得编写和理解汇编代码更加简单。以下是一些常见的MIPS伪指令:

  1. .data:定义数据段,用于声明和初始化全局变量、字符串等静态数据。

    .data
    message: .asciiz "Hello, MIPS!\n"
    array: .word 1, 2, 3, 4, 5
    
  2. .text:定义代码段,用于存放程序的指令。

    .text
    main:
        # 程序指令
    
  3. .word:用于在数据段中声明一个或多个字(32位数据)。

    .data
    my_var: .word 42
    
  4. .asciiz:在数据段中声明一个以空字符结尾的字符串。

    .data
    my_string: .asciiz "MIPS Assembly"
    
  5. .space:在数据段中为变量分配指定字节数的空间。

    .data
    buffer: .space 100
    
  6. .text:定义代码段,用于存放程序的指令。

    .text
    main:
        # 程序指令
    
  7. .globl或**.global**:声明一个全局符号,通常用于声明函数名或全局变量。

    .globl my_function
    
  8. .align:对齐指令,用于确保后续数据或指令在内存中按指定的边界对齐。

    .align 4
    
  9. .set:设置伪指令,用于设置汇编器选项。

    .set noat     # 禁用 $at 寄存器
    
  10. .end:标记程序的结束,有些汇编器可能需要此指令。

.end

    11. .type: 

在MIPS汇编中,.type伪指令用于为一个符号(symbol)指定类型信息。这对于链接器(linker)在链接过程中正确处理符号非常重要。一般情况下,.type伪指令的语法为:

.type symbol, type

其中,symbol是要指定类型信息的符号的名称,而type是该符号的类型。符号的类型通常可以是函数、对象或其他类型之一。

例来说,如果有一个名为my_function的函数,你可以使用.type指令为它指定类型信息,如下:

.type my_function, @function

这告诉链接器,my_function是一个函数。类似地,如果有一个全局变量my_variable,你可以使用以下指令:

.type my_variable, @object

这告诉链接器,my_variable是一个对象(全局变量)。

在实际应用中,.type伪指令通常与其他指令一起使用,以确保在链接时符号的类型得到正确识别和处理。这对于生成可执行文件或共享库时至关重要,因为链接器需要知道符号的类型以正确地连接不同的模块。

这些伪指令有助于提高汇编代码的可读性和编写效率,同时使代码更加模块化和易于维护。

三、常用指令详解

1、空操作:nop:相当于 sll zero,zero,o,

                   ssnop: equals sll zero,zero,1.
      这个指令不得与其它指令同时发送,这样就保证了其运行要花费至少一个时钟周期。这在简单的流水线的CPU上无关紧要,但在复杂些的实现上对于实现强制的延时很有用。

空操作指令在MIPS指令集中被称为NOP(No Operation),它是一种不执行任何操作的指令。在汇编语言中,NOP通常用于填充空闲位置或者在调试时插入延迟。

在MIPS汇编中,NOP指令的操作码通常是全0的二进制序列。在某些情况下,NOP指令可能会有特定的功能,比如在乱序执行的CPU中,NOP可能会有让处理器等待的作用,以确保指令执行的正确顺序。

示例:

NOP

这条指令执行时,处理器不执行任何操作,只是简单地将控制传递到下一条指令。


2、寄存器/寄存器传送:

      move: 通常用跟$zero寄存器的or来实现,或者用addu。
      movf, movt, movn, movz: 条件传送。

寄存器-寄存器传送指令是MIPS指令集中的一类指令,用于在寄存器之间传送数据。这些指令通常用于数据移动、数据加载和存储等操作。以下是几种常见的寄存器-寄存器传送指令:

  1. MOVE(Move):MOVE指令用于将一个寄存器的值复制到另一个寄存器中,没有任何运算或变换。例如:

    MOVE $t0, $s0
    

    这条指令将寄存器�0的值复制到寄存器s0的值复制到寄存器t0中。

  2. MFHI(Move From HI):MFHI指令用于将HI寄存器的值复制到一个通用寄存器中。HI寄存器用于保存乘法或除法指令的高位结果。例如:

    MFHI $t1
    

    这条指令将HI寄存器的值复制到寄存器$t1中。

  3. MFLO(Move From LO):MFLO指令用于将LO寄存器的值复制到一个通用寄存器中。LO寄存器用于保存乘法或除法指令的低位结果。例如:

    MFLO $t2
    

    这条指令将LO寄存器的值复制到寄存器$t2中。

  4. MTHI(Move To HI):MTHI指令用于将一个通用寄存器的值复制到HI寄存器中。例如:

    MTHI $s1
    

    这条指令将寄存器$s1的值复制到HI寄存器中。

  5. MTLO(Move To LO):MTLO指令用于将一个通用寄存器的值复制到LO寄存器中。例如:

    MTLO $s2
    

    这条指令将寄存器$s2的值复制到LO寄存器中。

这些寄存器-寄存器传送指令在MIPS汇编中被广泛使用,用于数据传送和操作。


3、常数加载:

      dla、la: 用来加载程序中某些带标号的位置或者变量的地址的宏指令;
      dli、li: 装入立即数常数,这是一个宏指令;
      lui: 把立即数加载到寄存器高位。
 

常数加载指令是MIPS指令集中的一类指令,用于将常数值加载到寄存器中。在程序中,常数值经常用于进行算术运算、逻辑运算或者作为地址偏移量。以下是几种常见的常数加载指令:

  1. LI(Load Immediate):LI指令用于将一个立即数(常数)加载到寄存器中。例如:

    LI $t3, 42
    

    这条指令将值42加载到寄存器$t3中。

  2. LUI(Load Upper Immediate):LUI指令用于将一个16位的立即数左移16位,并将结果加载到目标寄存器的高位。通常与其他指令组合使用,用于加载32位常数。例如:

    LUI $t4, 0x1234
    

    这条指令将16位的常数0x1234左移16位,并加载到寄存器$t4的高位,低位为0。

  3. ORI(OR Immediate):ORI指令用于将寄存器中的值与一个16位的立即数进行按位或运算,并将结果存放回寄存器。例如:

    ORI $t5, $t5, 0xFF
    

    这条指令将寄存器�5中的值与0���进行按位或运算,并将结果存放回t5中的值与0xFF进行按位或运算,并将结果存放回t5。

这些常数加载指令在MIPS汇编中允许程序员有效地将常数值加载到寄存器中,以便后续的运算或存储。

4、算术/逻辑运算:

      add、addi、dadd、daddi、addu、addiu、daddu、daddiu、dsub、sub、subu:加法指令和减法指令;
      abs,dabs:绝对值;
      dneg、neg、negu:取相反数;
      and、andi、or、ori、xor、nor:逐位逻辑操作指令;
      drol、rol、ror:循环移位指令;
      sll、srl、sra:移位。

算术和逻辑运算是计算机程序中常见的操作,MIPS指令集提供了一系列指令来执行这些操作。以下是几种常见的算术和逻辑运算指令:

  1. ADD(Addition):ADD指令用于将两个寄存器中的值相加,并将结果存放到目标寄存器中。例如:

    ADD $t0, $s0, $s1
    

    这条指令将寄存器�0和s0和s1中的值相加,并将结果存放到寄存器$t0中。

  2. SUB(Subtraction):SUB指令用于将一个寄存器中的值减去另一个寄存器中的值,并将结果存放到目标寄存器中。例如:

    SUB $t1, $s2, $s3
    

    这条指令将寄存器�2中的值减去s2中的值减去s3中的值,并将结果存放到寄存器$t1中。

  3. AND(Logical AND):AND指令用于将两个寄存器中的值进行按位与操作,并将结果存放到目标寄存器中。例如:

    AND $t2, $s4, $s5
    

    这条指令将寄存器�4和s4和s5中的值进行按位与操作,并将结果存放到寄存器$t2中。

  4. OR(Logical OR):OR指令用于将两个寄存器中的值进行按位或操作,并将结果存放到目标寄存器中。例如:

    OR $t3, $s6, $s7
    

    这条指令将寄存器�6和s6和s7中的值进行按位或操作,并将结果存放到寄存器$t3中。

  5. XOR(Exclusive OR):XOR指令用于将两个寄存器中的值进行按位异或操作,并将结果存放到目标寄存器中。例如:

    XOR $t4, $s8, $s9
    

    这条指令将寄存器�8和s8和s9中的值进行按位异或操作,并将结果存放到寄存器$t4中。

这些算术和逻辑运算指令在MIPS汇编中允许程序员对数据进行各种操作,从而实现复杂的计算和逻辑控制。

5、条件设置指令:

      slt、slti、sltiu、sltu、seq、sge、sle、sne:条件设置。

条件设置指令是MIPS指令集中的一类指令,用于在执行比较操作后设置条件码(例如零、正数、负数等),以便后续的条件分支或其他操作。以下是几种常见的条件设置指令:

  1. SLT(Set on Less Than):SLT指令用于比较两个寄存器中的值,如果第一个寄存器中的值小于第二个寄存器中的值,则将目标寄存器设置为1;否则设置为0。例如:

    SLT $t0, $s0, $s1
    

    这条指令比较寄存器�0和s0和s1中的值,如果�0的值小于s0的值小于s1的值,则将$t0设置为1,否则设置为0。

  2. SLTI(Set on Less Than Immediate):SLTI指令用于将一个寄存器中的值与一个立即数进行比较,如果寄存器中的值小于立即数,则将目标寄存器设置为1;否则设置为0。例如:

    SLTI $t1, $s2, 10
    

    这条指令比较寄存器�2中的值和立即数10,如果s2中的值和立即数10,如果s2的值小于10,则将$t1设置为1,否则设置为0。

  3. SLTU(Set on Less Than Unsigned):SLTU指令用于比较两个无符号整数寄存器中的值,如果第一个寄存器中的值小于第二个寄存器中的值,则将目标寄存器设置为1;否则设置为0。例如:

    SLTU $t2, $s3, $s4
    

    这条指令比较寄存器�3和s3和s4中的无符号整数值,如果�3的值小于s3的值小于s4的值,则将$t2设置为1,否则设置为0。

  4. SLTIU(Set on Less Than Immediate Unsigned):SLTIU指令用于将一个无符号整数寄存器中的值与一个立即数进行比较,如果寄存器中的值小于立即数,则将目标寄存器设置为1;否则设置为0。例如:

    SLTIU $t3, $s5, 20
    

    这条指令比较寄存器�5中的无符号整数值和立即数20,如果s5中的无符号整数值和立即数20,如果s5的值小于20,则将$t3设置为1,否则设置为0。

这些条件设置指令在MIPS汇编中常用于执行比较并根据比较结果设置条件码,以便进行条件分支或其他操作。


 

6、整数乘法、除法和求余数:

      div、mul、rem等等。

整数乘法、除法和求余数是在计算机程序中常见的操作,MIPS指令集提供了一些指令来执行这些操作。以下是几种常见的整数乘法、除法和求余数的指令:

  1. MULT(Multiply)和 MFHI/MFLO(Move From High/Low):MULT指令用于将两个寄存器中的有符号整数值相乘,并将结果存放在一对特殊寄存器中,即HI(高位)和LO(低位)。之后,可以使用MFHI和MFLO指令将相乘的结果的高位和低位移动到其他寄存器中。例如:

    MULT $s0, $s1      # 将$s0和$s1中的值相乘
    MFLO $t0           # 将乘积的低位存放到$t0中
    MFHI $t1           # 将乘积的高位存放到$t1中
    
  2. DIV(Divide)和 MFHI/MFLO:DIV指令用于将一个寄存器中的有符号整数值除以另一个寄存器中的值,并将商和余数存放在HI和LO寄存器中。之后,可以使用MFHI和MFLO指令将商和余数移动到其他寄存器中。例如:

    DIV $s2, $s3       # 将$s2中的值除以$s3中的值
    MFLO $t2           # 将商存放到$t2中
    MFHI $t3           # 将余数存放到$t3中
    
  3. MUL(Multiply Unsigned)和 MULU(Multiply Unsigned):MUL指令用于将两个寄存器中的无符号整数值相乘,结果存放在目标寄存器中。MULU执行类似的操作,但是用于无符号整数。例如:

    MUL $t4, $t5, $t6  # 将$t5和$t6中的值相乘,结果存放到$t4中
    
  4. DIVU(Divide Unsigned):DIVU指令用于将一个无符号整数寄存器中的值除以另一个无符号整数寄存器中的值,并将商存放在LO寄存器中,余数存放在HI寄存器中。例如:

    DIVU $t7, $t8      # 将$t7中的值除以$t8中的值
    MFLO $t9           # 将商存放到$t9中
    MFHI $s4           # 将余数存放到$s4中
    

这些指令允许程序员在MIPS汇编中执行整数乘法、除法和求余数的操作,适用于有符号和无符号整数。

7、整数乘加(累加):

      mad等。

整数乘加,也称为整数乘累加或累积乘法加法操作,是一种常见的操作,通常用于计算多个整数的乘积并将其与一个累加器相加。在MIPS指令集中,可以使用MADD(Multiply-Add)和MADDU(Multiply-Add Unsigned)指令执行整数乘加操作。

  1. MADD(Multiply-Add):MADD指令用于将两个寄存器中的有符号整数值相乘,然后将结果与第三个寄存器中的值相加,并将最终结果存储在累加器寄存器(通常是HI和LO寄存器)中。例如:

    MADD $s0, $s1, $s2  # 将$s1和$s2中的值相乘,然后与$s0中的值相加,结果存放在HI和LO寄存器中
    
  2. MADDU(Multiply-Add Unsigned):MADDU指令类似于MADD,但用于无符号整数的乘加操作。它将两个无符号整数寄存器中的值相乘,然后将结果与第三个寄存器中的值相加,并将最终结果存储在累加器寄存器中。例如:

    MADDU $t0, $t1, $t2  # 将$t1和$t2中的无符号整数值相乘,然后与$t0中的值相加,结果存放在HI和LO寄存器中
    

在执行这些指令后,可以使用MFHI和MFLO指令将累加器中的结果移动到其他寄存器中,以供后续使用。

整数乘加操作在许多计算任务中非常有用,特别是在信号处理和图形处理等应用中。这种操作允许高效地执行一系列的整数乘法和加法操作,减少了指令的数量和执行时间。

8、加载和存储:

      lb、ld、ldl、ldr、sdl、sdr、lh、lhu、ll、sc、pref、sb等操作。
 

加载和存储指令在计算机程序中用于将数据从内存加载到寄存器中或将数据从寄存器存储到内存中。MIPS指令集提供了一系列加载和存储指令,包括以下几种:

  1. LW(Load Word):LW指令用于从内存中加载一个字(32位数据)到寄存器中。例如:

    LW $t0, offset($s1)  # 将地址为$s1 + offset处的字加载到$t0中
    
  2. SW(Store Word):SW指令用于将一个字(32位数据)从寄存器存储到内存中。例如:

    SW $t0, offset($s1)  # 将$t0中的值存储到地址为$s1 + offset处
    
  3. LB(Load Byte):LB指令用于从内存中加载一个字节(8位数据)到寄存器中。加载的字节会进行符号扩展,即最高位(MSB)被复制到寄存器的其他位上。例如:

    LB $t0, offset($s1)  # 将地址为$s1 + offset处的字节加载到$t0中
    
  4. SB(Store Byte):SB指令用于将一个字节(8位数据)从寄存器存储到内存中。例如:

    SB $t0, offset($s1)  # 将$t0中的最低字节存储到地址为$s1 + offset处
    

这些加载和存储指令允许程序员在MIPS汇编中有效地进行数据的读取和存储操作,从而支持程序的正常执行。

网络搜索

9、浮点加载和存储:

      l.d、l.s、s.d、s.s等

浮点加载和存储指令在MIPS指令集中用于处理浮点数数据的加载和存储操作。MIPS架构支持单精度浮点数(32位)和双精度浮点数(64位)。以下是常见的浮点加载和存储指令:

  1. LWC1(Load Word to Coprocessor 1):LWC1指令用于将一个32位的单精度浮点数从内存加载到浮点寄存器(协处理器1)中。例如:

    LWC1 $f0, offset($s1)  # 将地址为$s1 + offset处的单精度浮点数加载到$f0中
    
  2. SWC1(Store Word from Coprocessor 1):SWC1指令用于将一个32位的单精度浮点数从浮点寄存器(协处理器1)存储到内存中。例如:

    SWC1 $f0, offset($s1)  # 将$f0中的单精度浮点数存储到地址为$s1 + offset处
    
  3. LDC1(Load Double to Coprocessor 1):LDC1指令用于将一个64位的双精度浮点数从内存加载到浮点寄存器对中(协处理器1)。因为双精度浮点数占用两个寄存器,所以加载到对中。例如:

    LDC1 $f0, offset($s1)  # 将地址为$s1 + offset处的双精度浮点数加载到$f0和$f1对中
    
  4. SDC1(Store Double from Coprocessor 1):SDC1指令用于将一个64位的双精度浮点数从浮点寄存器对中(协处理器1)存储到内存中。例如:

    SDC1 $f0, offset($s1)  # 将$f0和$f1对中的双精度浮点数存储到地址为$s1 + offset处
    

这些浮点加载和存储指令允许程序员在MIPS汇编中有效地进行浮点数数据的读取和存储操作,从而支持程序的正常执行。

网络搜索

四、常用MIPS指令集及格式:

MIPS 指令集(共31条)

助记符

指令格式

示例

示例含义

操作及其解释

Bit #

31..26

25..21

20..16

15..11

10..6

5..0

R-type

op

rs

rt

rd

shamt

func

add

000000

rs

rt

rd

00000

100000

 add $1,$2,$3

 $1=$2+$3

 rd <- rs + rt   ;其中rs=$2,rt=$3, rd=$1

addu

000000

rs

rt

rd

00000

100001

 addu $1,$2,$3

 $1=$2+$3

 rd <- rs + rt   ;其中rs=$2,rt=$3, rd=$1,无符号数

sub

000000

rs

rt

rd

00000

100010

 sub $1,$2,$3

 $1=$2-$3

 rd <- rs - rt   ;其中rs=$2,rt=$3, rd=$1

subu

000000

rs

rt

rd

00000

100011

 subu $1,$2,$3

 $1=$2-$3

 rd <- rs - rt   ;其中rs=$2,rt=$3, rd=$1,无符号数

and

000000

rs

rt

rd

00000

100100

 and $1,$2,$3

 $1=$2 & $3

 rd <- rs & rt   ;其中rs=$2,rt=$3, rd=$1

or

000000

rs

rt

rd

00000

100101

 or $1,$2,$3

 $1=$2 | $3

 rd <- rs | rt   ;其中rs=$2,rt=$3, rd=$1

xor

000000

rs

rt

rd

00000

100110

 xor $1,$2,$3

 $1=$2 ^ $3

 rd <- rs xor rt   ;其中rs=$2,rt=$3, rd=$1(异或)

nor

000000

rs

rt

rd

00000

100111

 nor $1,$2,$3

 $1=~($2 | $3)

 rd <- not(rs | rt)   ;其中rs=$2,rt=$3, rd=$1(或非)

slt

000000

rs

rt

rd

00000

101010

 slt $1,$2,$3

 if($2<$3) 
  $1=1 else
   $1=0

 if (rs < rt) rd=1 else rd=0 ;其中rs=$2,rt=$3, rd=$1

sltu

000000

rs

rt

rd

00000

101011

 sltu $1,$2,$3

 if($2<$3) 
  $1=1 else
   $1=0

 if (rs < rt) rd=1 else rd=0 ;其中rs=$2,rt=$3, rd=$1
  (无符号数)

sll

000000

00000

rt

rd

shamt

000000

 sll $1,$2,10

 $1=$2<<10

 rd <- rt << shamt  ;shamt存放移位的位数,
  也就是指令中的立即数,其中rt=$2, rd=$1

srl

000000

00000

rt

rd

shamt

000010

 srl $1,$2,10

 $1=$2>>10

 rd <- rt >> shamt ;(logical) ,其中rt=$2, rd=$1

sra

000000

00000

rt

rd

shamt

000011

 sra $1,$2,10

 $1=$2>>10

 rd <- rt >> shamt  ;(arithmetic) 注意符号位保留
 其中rt=$2, rd=$1

sllv

000000

rs

rt

rd

00000

000100

 sllv $1,$2,$3

 $1=$2<<$3

 rd <- rt << rs  ;其中rs=$3,rt=$2, rd=$1

srlv

000000

rs

rt

rd

00000

000110

 srlv $1,$2,$3

 $1=$2>>$3

 rd <- rt >> rs  ;(logical)其中rs=$3,rt=$2, rd=$1

srav

000000

rs

rt

rd

00000

000111

 srav $1,$2,$3

 $1=$2>>$3

 rd <- rt >> rs  ;(arithmetic) 注意符号位保留
 其中rs=$3,rt=$2, rd=$1

jr

000000

rs

00000

00000

00000

001000

 jr $31  

#寄存器跳转

 goto $31

 PC <- rs

I-type

op

rs

rt

immediate

addi

001000

rs

rt

immediate

 addi $1,$2,100

 $1=$2+100

 rt <- rs + (sign-extend)immediate ;其中rt=$1,rs=$2

addiu

001001

rs

rt

immediate

addiu $1,$2,100

 $1=$2+100

 rt <- rs + (zero-extend)immediate ;其中rt=$1,rs=$2

andi

001100

rs

rt

immediate

 andi $1,$2,10

 $1=$2 & 10

 rt <- rs & (zero-extend)immediate ;其中rt=$1,rs=$2

ori

001101

rs

rt

immediate

 andi $1,$2,10

 $1=$2 | 10

 rt <- rs | (zero-extend)immediate ;其中rt=$1,rs=$2

xori

001110

rs

rt

immediate

 andi $1,$2,10

 $1=$2 ^ 10

 rt <- rs xor (zero-extend)immediate ;其中rt=$1,rs=$2

lui

001111

00000

rt

immediate

 lui $1,100

 $1=100*65536

 rt <- immediate*65536 ;将16位立即数放到目标寄存器高16
         位,目标寄存器的低16位填0

lw

100011

rs

rt

immediate

 lw $1,10($2)

 $1=memory[$2
 +10]

 rt <- memory[rs + (sign-extend)immediate] ;rt=$1,rs=$2

sw

101011

rs

rt

immediate

 sw $1,10($2)

 memory[$2+10]
 =$1

 memory[rs + (sign-extend)immediate] <- rt ;rt=$1,rs=$2

beq

000100

rs

rt

immediate

 beq $1,$2,10

 if($1==$2) 
 goto PC+4+40

 if (rs == rt) PC <- PC+4 + (sign-extend)immediate<<2 

bne

000101

rs

rt

immediate

 bne $1,$2,10

 if($1!=$2)
 goto PC+4+40

 if (rs != rt) PC <- PC+4 + (sign-extend)immediate<<2 

slti

001010

rs

rt

immediate

 slti $1,$2,10

 if($2<10) 
  $1=1 else
   $1=0

 if (rs <(sign-extend)immediate) rt=1 else rt=0 ;
   其中rs=$2,rt=$1

sltiu

001011

rs

rt

immediate

 sltiu $1,$2,10

 if($2<10) 
  $1=1 else
   $1=0

 if (rs <(zero-extend)immediate) rt=1 else rt=0 ;
  其中rs=$2,rt=$1

J-type

op

address

j

000010

address

 j 10000

 goto 10000

 PC <- (PC+4)[31..28],address,0,0   ;address=10000/4

jal

000011

address 

 jal 10000

#目标地址长跳转

 $31<-PC+4;
 goto 10000

 $31<-PC+4;PC <- (PC+4)[31..28],address,0,0
   ;address=10000/4

五、CPU内部的32个寄存器:

寄存器号            符号名            用途

  •  0                 始终为0     看起来象浪费,其实很有用
  •  1                 at          保留给汇编器使用
  •  2-3               v0,v1       函数返回值
  •  4-7               a0-a3       前头几个函数参数
  •  8-15              t0-t7       临时寄存器,子过程可以不保存就使用
  •  24-25             t8,t9       同上
  •  16-23             s0-s7       寄存器变量,子过程要使用它必须先保存
  •                                然后在退出前恢复以保留调用者需要的值
  •  26,27             k0,k1       保留给异常处理函数使用
  •  28                gp          global pointer;用于方便存取全局或者静态变量
  •  29                sp          stack pointer
  •  30                s8/fp       第9个寄存器变量;子过程可以用它做frame pointer
  •  31                 ra         返回地址

硬件上这些寄存器并没有区别(除了0号),区分的目的是为了不同的编译器产生的代码可以通用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/442331.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在线部署ubuntu20.04服务器,安装jdk、mysql、redis、nginx、minio、开机自启微服务jar包

一、服务器 1、查看服务器版本 查看服务器版本为20.04 lsb_release -a2、服务器信息 服务器初始账号密码 sxd / 123456 首先,更改自身密码都输入123456 sudo passwd 创建最高权限root账号&#xff0c;密码为 123456 su root 3、更新服务器源 1、更新源列表 sudo apt-g…

【golang】Windows与Linux交叉编译保姆级教程

【golang】Windows与Linux交叉编译 大家好 我是寸铁&#x1f44a; 总结了一篇【golang】Windows与Linux交叉编译的文章✨ 喜欢的小伙伴可以点点关注 &#x1f49d; 问题背景 今天寸铁想将Windows中的程序部到Linux下跑&#xff0c;我们知道在从Windows与Linux下要进行交叉编译…

11、Linux-安装和配置Redis

目录 第一步&#xff0c;传输文件和解压 第二步&#xff0c;安装gcc编译器 第三步&#xff0c;编译Redis 第四步&#xff0c;安装Redis服务 第五步&#xff0c;配置Redis ①开启后台启动 ②关闭保护模式&#xff08;关闭之后才可以远程连接Redis&#xff09; ③设置远程…

Java基础 - 8 - 算法、正则表达式、异常

一. 算法 什么是算法&#xff1f; 解决某个实际问题的过程和方法 学习算法的技巧&#xff1f; 先搞清楚算法的流程&#xff0c;再直接去推敲如何写算法 1.1 排序算法 1.1.1 冒泡排序 每次从数组中找出最大值放在数组的后面去 public class demo {public static void main(S…

21 easy 1. 两数之和

//给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 // // 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。 // // 你可以…

java Spring boot简述jetcache 并叙述后续文章安排

我们之前 讲了 Spring boot 整合 cache 使用 simple(默认) redis Ehcache memcached的几种方式 但是 始终有人觉得不够完善 提出了一些问题 例如 觉得 当前spring boot 对缓存过期的控制过于松散 不严谨 比较明显的体现就是 memcached过期时间在逻辑代码中控制 Ehcache的过期时…

Tomcat的安装

下载Tomcat&#xff08;这里以Tomcat8.5为例&#xff09; 直接进入官网进行下载&#xff0c;Tomcat官网 选择需要下载的版本&#xff0c;点击下载这里一定要注意&#xff1a;下载路径一定要记住&#xff0c;并且路径中尽量不要有中文&#xff01;&#xff01;&#xff01;&…

Prompt Engineering、Finetune、RAG:OpenAI LLM 应用最佳实践

一、背景 本文介绍了 2023 年 11 月 OpenAI DevDay 中的一个演讲&#xff0c;演讲者为 John Allard 和 Colin Jarvis。演讲中&#xff0c;作者对 LLM 应用落地过程中遇到的问题和相关改进方案进行了总结。虽然其中用到的都是已知的技术&#xff0c;但是进行了很好的总结和串联…

神经网络的矢量化,训练与激活函数

我们现在再回到我们的神经元部分&#xff0c;来看我们如何用python进行正向传递。 单层的正向传递&#xff1a; 我们回到我们的线性回归的函数。我们每个神经元通过上述的方法&#xff0c;就可以得到我们的激发值&#xff0c;从而可以继续进行下一层。 我们用这个方法就可以得…

排序算法的对比

类别排序方法时间复杂度空间复杂度稳定性平均情况特殊情况 插入 排序 插入排序基本有序最优稳定希尔排序不稳定 选择 排序 选择排序不稳定堆排序不稳定 交换 排序 冒泡排序稳定快速排序基本有序最差不稳定归并排序稳定基数排序稳定

0环PEB断链实现

截止到昨天那里我们的思路就清晰了&#xff0c;通过EPROCESS找到我们要隐藏的进程的ActiveProcessLinks&#xff0c;将双向链表的值修改&#xff0c;就可以将我们想要隐藏的这个进程的ActiveProcessLinks从双向链表中抹去的效果&#xff0c;这里的话如果在windbg里面直接使用ed…

用Python实现一个简单的——人脸相似度对比

近几年来&#xff0c;兴起了一股人工智能热潮&#xff0c;让人们见到了AI的能力和强大&#xff0c;比如图像识别&#xff0c;语音识别&#xff0c;机器翻译&#xff0c;无人驾驶等等。总体来说&#xff0c;AI的门槛还是比较高&#xff0c;不仅要学会使用框架实现&#xff0c;更…

Day33|贪心算法part3

k次取反后最大的数组元素和 思路&#xff1a;贪心&#xff0c;局部最优&#xff0c;让绝对值大的负数变正数&#xff0c;当前数值达到最大&#xff0c;整体最优&#xff1b;整个数组和达到最大。如果把序列中所有负数都转换为正数了&#xff0c;k还没耗尽&#xff0c;就是k还大…

AWS的CISO:GenAI只是一个工具,不是万能钥匙

根据CrowdStrike的年度全球威胁报告,尽管研究人员预计人工智能将放大对防御者和攻击者的影响,但威胁参与者在其行动中使用人工智能的程度有限。该公司上个月在报告中表示:“在整个2023年,很少观察到GenAI支持恶意计算机网络运营的开发和/或执行。” 对于GenAI在网络安全中的…

Python:在 Ubuntu 上安装 pip的方法

目录 1、检测是否已安装pip 2、更新软件源 3、安装 4、检测是否安装成功 pip和pip3都是Python包管理工具&#xff0c;用于安装和管理Python包。 在Ubuntu上&#xff0c;pip和pip3是分别针对Python2和Python3版本的pip工具。 pip3作用&#xff1a;自动下载安装Python的库文…

2024年HW技术总结

我们都知道&#xff0c; 护网行动 是国家应对网络安全问题所做的重要布局之一。至今已经是8个年头了&#xff0c;很多公司在这时候人手不够&#xff0c;因此不得不招募一些网安人员来参加护网。 红队 扮演攻击的角色&#xff0c;蓝队 扮演防守、溯源的角色&#xff0c;紫队当然…

Java 的 System 类常用方法介绍

Java 中的 System 类是一个final类&#xff0c;它提供了与系统相关的属性和方法。它是一个内置的类&#xff0c;可以直接使用&#xff0c;不需要实例化。System 类提供了标准输入、标准输出和错误输出流&#xff0c;以及对外部定义的属性和系统环境的访问。下面是 System 类的一…

如何在Android 上查找恢复删除/隐藏的照片?5 个值得尝试的方法分享

Android 设备上的删除/隐藏图像有多种用途&#xff0c;无论是保护隐私还是优化存储空间。然而&#xff0c;在某些情况下&#xff0c;用户可能由于意外隐藏、删除或仅仅是出于好奇而需要取消删除/隐藏这些照片。在这种情况下&#xff0c;了解如何在 Android 上查找删除/隐藏的照…

Sora的新商业视角:从生态构建到未来产业协同

在科技飞速发展的当下&#xff0c;人工智能与机器学习不仅重塑了我们的生活方式&#xff0c;还深刻地改变了商业模式的构建方式。Sora&#xff0c;作为一款前沿的AI视频生成工具&#xff0c;其盈利路径和未来产业协同的可能性值得深入探讨。 Sora学习资料&#xff1a;使用方式…

LabVIEW智能Modbus监控系统

LabVIEW智能Modbus监控系统 在自动化和信息化迅速发展下&#xff0c;传统的监控系统已无法满足现代工业对于数据通讯和处理的高效率和高可靠性要求。为了解决这一问题&#xff0c;设计了一套基于LabVIEW的智能Modbus监控系统。该系统利用LabVIEW的图形化编程环境和Modbus协议的…