精华内容
下载资源
问答
  • MIPS指令集中LB和LW的区别

    千次阅读 2020-04-21 22:46:14
    文章目录LB 取字节LW ...指令如下 内存如下 LB和LW都是取0x7C位置的值,但LB取的是字节,也就是0x80, 然后按照符号扩展,LB得到的值是有符号的0xFF80. 而LW取的是32位的字,即下图中红框中的值: 故LW得到的是...

    LB 取字节

    在这里插入图片描述

    LW 取字

    在这里插入图片描述

    区别

    LB与LW的区别:LB加载字节,地址不一定是4的倍数。LW加载字(1字=4字节),地址必须是4的倍数。

    举例

    指令如下
    在这里插入图片描述
    内存如下
    在这里插入图片描述
    LB和LW都是取0x7C位置的值,但LB取的是字节,也就是0x80,
    在这里插入图片描述
    然后按照符号扩展,LB得到的值是有符号的0xFF80.
    而LW取的是32位的字,即下图中红框中的值:
    在这里插入图片描述
    故LW得到的是有符号的0x0080

    展开全文
  • 指令

    2021-05-13 15:09:51
    控制计算机需要使用计算机语言,语言的基本单词称为指令,一台计算机的全部指令称为计算机指令集。 所有计算机都是基于基本原理相似的硬件技术所构建的,另一面是因为所有计算机都必须提供一些基本操作。此外,...

    引言

    控制计算机需要使用计算机语言,语言的基本单词称为指令,一台计算机的全部指令称为计算机指令集

    所有计算机都是基于基本原理相似的硬件技术所构建的,另一面是因为所有计算机都必须提供一些基本操作。此外,计算机设计者都有一个共同的目标:找到一种语言,可方便硬件和编译器的设计,且性能最佳,同时使成本和功耗最低。

    指令集存在什么地方?

    CPU指令集是在CPU设计时固化在里面的"硬程序",整合在CPU的逻辑电路中。

    如果把CPU看成是一个人,那么指令集就是交流的语言。如果要和CPU交流则必须使用它会的语言。

    也可以这么理解:

    把CPU看做是日常生活中的工具,指令集就是使用这个工具方法。但这个方法不存在任何地方(方法不能存储的),方法只在工具说明书中"说明"了

    指令集架构的分类

    CISC(Complex Instruction Set Computer 复杂指令集计算机):CISC每个指令可执行若干低阶操作,从内存读取、存储和计算操作,全部集中于单一指令。简单理解就是一个指令能干很多事,RISC指令做相同的操作需要多条指令。

    RISC (Reduced Instruction Set Computer 精简指令集计算机): 起源于MIPS主机,具有设计更简单,设计周期更短等优点。

    复杂和精简

    这里的“复杂”和“精简”是指指令上的,即功能精简(一条指令只干极少的事),功能复杂(一条指令能做很多事)

    机器周期

    大多数计算机处理器都会不断地重复三个基本步骤。每个机器周期内会执行一条机器指令。一个现代的计算机处理器每秒钟运行数百万次机器周期。
    一条机器指令是由一串对应着处理器基本操作的二进制码组成的,在不同的处理器架构中,机器周期的组成也不相同,但他们的基本行为都包含下面三个主要步骤:

    • 从内存中读取指令:指令存放在内存中,PC (Program Counter) 存放了指令在内存中的地址
    • PC=PC+4:让PC指向下一条指令所在的地址
    • 执行所得到的指令

    时钟周期、机器周期和指令周期

    时钟周期: 也称为振荡周期,定义为时钟脉冲的倒数,是计算机中最基本的、最小的时间单位。

    机器周期: 常把一条指令的执行过程划分为若干个阶段,每完成一个阶段所需要的时间称为机器周期。

    指令周期: 执行一条指令所需要的时间,一般由若干个机器周期组成。指令不同,所需要的机器周期也不同。

    从时间上来分区分: 指令周期 > 机器周期 > 时钟周期

    硬件设计原则

    1. 简单源于规整: 比如加法指令,加法指令只有三个操作数,每个指令有且仅有三个操作数。操作个数的可变将给硬件设计带来更大的复杂性
    2. 越小越快: 比如寄存器非常小,但速度非常快
    3. 优秀的设计需要适应的折中方案: MIPS的所有指令长度相同,但指令的格式不一样(分为了R,I 类型),这是一种折中的体现(长度相同,指令格式相同,MIPS选择了前者)

    CPU工作原理

    在这里插入图片描述

    图片取自:CPU工作原理

    MIPS架构

    介绍

    英语:MIPS architecture,为Microprocessor without Interlocked Pipeline Stages的缩写,亦为Millions of Instructions Per Second的头字语

    MIPS 是一种采用精简指令集(RISC) 的处理器架构

    MIPS操作数

    名字 示例 注释
    32个寄存器 $0 $1 寄存器用于数据的快速存取。MIPS中只能对存放在寄存器中的数据只需算数操作
    $2^{30} $ 个存储字 Memory[0], Memory[4] … 存储器只能通过数据传输指令访问。MIPS使用字节编址,所以连续的字地址相差4.存储器用于保存数据结构、数组和溢出的寄存器

    寄存器

    • 总共有32个通用寄存器
    • 在汇编中,寄存器由$符开头
    • 寄存器有两种表示方法一个是使用REGISTER ($ 0) 一个是使用 NAME ($zero)
    REGISTER NAME USAGE
    $0 $zero 常量0(constant value 0)
    $1 $at 保留给汇编器(Reserved for assembler) 可以用于加载大常数
    $2-$3 $v0 - $v1 函数调用返回值(values for results and expression evaluation)
    $4-$7 $a0-$a3 函数调用参数(arguments)
    $8-$15 $t0-$t7 临时寄存器(temp)
    $16-$23 $s0-$s7 保存的(或如果用,需要SAVE/RESTORE的)(saved)
    $24-$25 $t8-$t9 临时寄存器(temp) 为操作系统/异常处理保留,至少要预留一个
    $28 $gp 全局指针(Global Pointer)
    $29 $sp 堆栈指针(Stack Pointer)
    $30 $fp 帧指针(Frame Pointer)
    $31 $ra 返回地址(return address)
    1. $1, 保留,可以用于拆散和重装大常数
    2. $31 , 使用jar address跳转到某个地址(比如过程地址)时把下一条指令地址放到$ra 中。当过程执行完毕使用jr $ra 返回

    指令类型

    R型指令: 操作寄存器

    指令格式

    在这里插入图片描述

    • op: (Operation Code ) 操作码
    • rs: (Source Register): 第一个来源寄存器
    • rt: ( Target Register): 第二个来源寄存器
    • rd: (Destination Register)目的地寄存器
    • sham: Shift amount (number of bits the operation is shifted) 偏移量
    • funct: function (function code) 功能,一般称为功能码,用于指明OP字段中操作的特定变式

    包含的指令:

    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型指令:操作常量

    指令格式:

    在这里插入图片描述

    • op: (Operation Code ) 操作码
    • rs: (Source Register): 第一个来源寄存器
    • rt: (Destination Register)目的地寄存器
    • imd: Immediate value 即时量

    包含的指令:

    指令 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型指令:跳跃寻址,非条件式分支指令

    指令格式
    在这里插入图片描述

    • op: (Operation Code ) 操作码
    • imd: Immediate value 即时量

    包含的指令:

    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

    算数与逻辑指令

    算数

    -----------R  type-------------
    add rd rs rt # 加法,rd = rs + rt
    addu rd rs rt # 加法 r类型 用于无符号
    sub rd rs rt # 减法 rd = rs - rt 
    subu rd rs rt # 减法 同上 , rd rs rt 无符号
    -----------I  type-------------
    addi rt rs imd # 加法 r
    addiu rt rs imd # imd 为常数 rs rt 无符号
    

    逻辑

    -----------R  type-------------
    and rd rs rt #与 rd = rs & rt
    or rd rs rt #或 rd = rs | rt
    xor rd rs rt #异或 rd = rs ^ rt  
    nor rd rs rt #或非 rd = ~(rs|rt)
    -----------I  type-------------
    adni rt rs imd  #与 rt = rs & imd
    ori rt rs imd  # 或 rt = rs | imd
    xori rt rs imd # 异或 rt = rs ^ imd
    

    数据传输

    指令 示例 含义 注释
    取字 lw $s1,20($s2) $s1 =Memory[ $s2 + 20] 将一个字从内存中 取到寄存器中
    存字 sw s1,20(s1,20(s2) Menory[ 8s2 +20]= $s1 将一个字从寄存器 中取到内存中
    取半字 lh $s1,20($s2) $sl =Memory[ $s2 +20] 将半个字从内存中 取到寄存器中
    取无符号半字 lhu $s1,20($s2) $s1 = Memory[ $s2 +20 ] 将半个字从内存中 取到寄存器中
    存半字 sh $81,20(8$82) Mermoy[$s2+20]= $s1 将半个字从寄存器 存到内存中
    取字节 lb $s1,20($s2) $sl =Memory( $s2 +20] 将一个字节从内存 取到寄存器中
    取无符号字节 lbu $31,20($s2) $sl = Memory[ $s2 +20] 将一个字节从内存 取到寄存器中
    存字节 sb $s1,201$s2) Memory[ $s2+20]= $s1 将一个字节从寄存 器存到内存中
    取链接学 11 $s1,20(Ss2) $sl = Memory[ $s2 +20] 取字作为原子交换 的前半部
    存条件字 SC $81,20($s2) Menny[ $s2+20] = $s1;
    $s1 =0 or 1
    存字作为原子交换 的后半部分
    取立即数的高位 lul $s1,20 $sl =20*216 取立即数并放到高 16位

    条件分支 /决策指令

    计算机根据输入数据和计算过程产生的值可以执行不同的指令

    b	target		    #  unconditional branch to program label target  target 需要跳转到的目的地址
    beq	$t0,$t1,target	#  branch to target if $t0 = $t1  (branch equal)
    blt	$t0,$t1,target	#  branch to target if $t0 < $t1  (branch less than)
    ble	$t0,$t1,target	#  branch to target if $t0 <= $t1 (branch less than equal)
    bgt	$t0,$t1,target	#  branch to target if $t0 > $t1  (branch greater than)
    bge	$t0,$t1,target	# branch to target if $t0 >= $t1 (branch greater than equal)
    bne	$t0,$t1,target	#  branch to target if $t0 <> $t1 (branch not equal)
    bgez $t0,target     #  branch to target if $t0 >= 0 (branch greater than equal zero)
    bgtz $t0,target     #  branch to target if $t0 > 0  (branch greater than zero)
    blez $t0,target     #  branch to target if $t0 <= 0 (branch less than equal zero)
    bltz $t0,target     #  branch to target if $t0 < 0  (branch less than zero)
    

    beq Demo

    # 如果 0 == 0 则输出 " hello world!"
    .data
    	string1: .asciiz "hello world!"
    .text
    	main:
    		beq $zero,$zero,sayHello
    	sayHello:
    		li $v0,4
    		la $a0,string1
    		syscall
    

    比较并设置

    -------------------------R type------------------------------------
    # rs < rt? rd = 1 : rd = 0
    slt rd rs rt # set on less than  
    sltu rd rs rt # set on less than unsigned  其中rs 和 rt 为无符号数
    -------------------------I type------------------------------------
    # 含义 rs < imd? rd = 1 : rd = 0
    slti rd rs imd # set on less than immediate 
    sltiu rd rs imd # set on less than immediate unsigned   
    

    slt和slti 用于处理有符号整数,sltu和sltiu用于处理无符号整数

    移位运算

    逻辑移位

    指令

    sll rd rs sham # shift left logical  向左位移,溢出的丢弃,最低位补0
    srl rd rs sham # shift right logical 向右位移 ~~~~~~~~~, 最高位补0
    sllv rd rt rs # 使用寄存器rs 的值让rt向左逻辑移动, rs的值不超过32 也就是5位
    srlv rd rt rs # 使用寄存器rs 的值让rt向右逻辑移动 ~~~~~同上
    

    sll demo:

    li $t1,1
    sll $t0,$t1,3 # 结果 $t0 = D(8)
    

    sllv demo:

    li $t0,1 # rt
    li $t1,33 # rs 由于不超过32 所以只向左移动一位
    sllv $a0,$t0,$t1 # $t0 >> $t1 
    

    sllv demo 结果:
    在这里插入图片描述

    算数移位

    指令:

    sra rd rt sham # rd shift right arithmetic 向右算数移位 ,最高位用原数字补上,比如最高位为0000 0001 则补0
    srav rd rt rs # rd shift left arithmetic  同上,用rs做算数位移
    

    常用于除法,目的可能是保留符号位

    比如:
    在这里插入图片描述

    如果是-1的话会出现问题:
    在这里插入图片描述

    -1 / 2 = -1 按理来说应该是0,可能-1 是一个特殊数,但如果是-2 能正常运算。

    原子操作

    MIPS中使用链接取数(load linked)和条件存数(store conditional)两个指令执行原子操作

    操作数

    存储器操作数

    处理器只处理寄存器中的数据,但数据都存储在存储器中。MIPS必须包含在存储器和寄存器之间传送数据的指令,这种指令叫做数据传输指令

    从存储器中复制数据的指令称为取数(load) ,写入数据称为存数(store)

    MIPS 是按字节编址的,字的起始地址必须是4的倍数。这个称为对其限制(alignment restriction)

    如下图:

    在这里插入图片描述

    如果要访问数组中第三个Arr[2],则必须在基地址上加上偏移量—3*4(12) 才能读取到Arr[2]

    寄存器会不会不够用?

    存储器与寄存器大小相差是巨大的,寄存器会不会不够用?

    硬件设计原则2: 存储器一定比寄存器慢

    通过不断load和store,不用担心空间不够用的问题。为了提高效率,编译器会将最常用的变量保存在寄存器中,而其他的变量放在存储器中。将不常用的变量存回到存储器中的过程称为寄存器溢出(spilling)

    常数或立即数操作数

    程序中经常会在某个操作中用到常数——例如,将数组的下标加一,用以指向下一个操作数

    使用常数必须要从存储器取出到寄存器中才能够使用, 根据加速大概率事件思想,提供其中一个操作数是常数的指令。

    比如 $s3 需要加20:

    lw $t0,Constant($s1) # t0 = constant
    add $s3,$s3,$t0  # s3 = s3+t0  
    

    改善后:

    addi $s3,$s3,20  # s3 = s3+20 只需要一个指令,而且效率提高了,不需要从存储器中取出
    

    有符号和无符号

    用来表示符号数的方法是二进制补码(tow’s complement),无符号的是二进制

    在这里插入图片描述

    最左边为最高有效位 , 最右边为最低有效位

    有符号

    • 最高有效位为1表示负数
    • 最高有效位为0表示正数

    无符号

    • 无符号都为正数

    指令格式

    三种指令类型:
    请添加图片描述
    在这里插入图片描述

    当某条指令比上述字段更长,问题就会发生。比如一条指令op长度为5那么某个指令个数就被限制在25 ( 32个) 之内。
    并且指令长度相等更利于硬件的设计。

    因此,即希望所有指令长度相同,有希望具有统一的格式。两者产生了冲突。
    根据设计原则3: 优秀的设计需要折中的方案。

    MIPS选择保持所有指令长度相同,但不同类型的指令采用不同的指令格式

    多种指令格式使硬件变得更复杂,保持指令格式类似可降低复杂度。

    比如R、I、J 第一个字段都是OP,R、I 前三个字段相同。

    寻址方式

    立即数寻址

    在这里插入图片描述

    操作数是位于指令自身的常数

    寄存器寻址

    在这里插入图片描述

    操作数是寄存器

    基址寻址

    在这里插入图片描述

    操作数在内存中,地址是指令中基址和常数的和

    PC相对寻址

    在这里插入图片描述

    地址是PC和指令中常数的和

    伪直接寻址

    在这里插入图片描述

    J类型指令中26位字段和PC高位字段相连而成

    对过程的支持

    先进后出的队列,可以看成往一个桶里面放东西,先放下去的最后才能拿出来。

    栈指针: 指向栈中最新分配的地址的值,在MIPS中为$sp寄存器

    往栈中添加元素称为压栈 ,从栈中取出元素为出栈

    访问静态变量

    MIPS 通过$gp 全局变量访问静态数据区。
    在这里插入图片描述

    帧指针

    如果参数多余4个怎么办?
    由于MIPS只提供了4个寄存器存储参数,一旦超过4个就只能将额外的参数放在栈中帧指针的上方。

    什么是帧指针?
    帧指针是存储函数活动记录中固定地址的寄存器。其实就是CPU中的一个寄存器,该寄存器始终指向函数活动记录的一个固定位置,不会随这个函数的执行而变化(注意,并不是指向活动记录的最底部位置)。

    函数调用过程

    MIPS 代码

    	addiu	$sp,$sp,-48   # sp所需要用到的最大栈空间
    	sw	$31,44($sp)  # 返回地址
    	sw	$fp,40($sp)  # 
    	move	$fp,$sp
    	li	$2,9			# 0x9
    	sw	$2,32($sp)
    	li	$2,8			# 0x8
    	sw	$2,28($sp)
    	li	$2,7			# 0x7
    	sw	$2,24($sp)
    	li	$2,6			# 0x6
    	sw	$2,20($sp)
    	li	$2,5			# 0x5
    	sw	$2,16($sp)
    	li	$7,4			# 0x4
    	li	$6,3			# 0x3
    	li	$5,2			# 0x2
    	li	$4,1			# 0x1
    	balc	func
    	move	$2,$0
    	move	$sp,$fp
    	lw	$31,44($sp)
    	lw	$fp,40($sp)
    	addiu	$sp,$sp,48
    	jrc	$31
    

    对应的C代码

    #include<stdio.h>
    void func(int a,int b,int c,int d,int e,int f,int g,int h,int i){
      int x = a+b+c+d+e+f+g+h+i;
      printf("_%d_",x);
    }
    int main(){
      func(1,2,3,4,5,6,7,8,9);
    }
    

    大概思路:

    先开辟sp需要用到的最大栈空间,然后将其余5个参数压入栈中,其他4个就放在$4 - $7 中,之后调用函数

    翻译并执行程序

    描述将C程序转换成可执行程序的几个步骤
    在这里插入图片描述

    编译器

    将C程序代码转换为汇编程序的工具

    汇编器

    将汇编语言程序转换成目标文件。

    大概功能: 支持将伪指令转换成MIPS支持的汇编,将不同进制的数字转换成二进制。将符号放入符号表中。

    伪指令: 汇编语言指令的一个变种,是一种语言方言。


    目标文件中通常包含6个不同部分:

    • 目标文件头:描述目标文件其他部分的大小和位置
    • 代码段: 包含机器语言代码
    • 静态数据段: 包含在程序生命周期内分配的数据
    • 重定位信息: 标记了一些在程序加载进内存时依赖于其他绝对地址的指令和数据
    • 符号表: 包含未定义的剩余标记,如外部引用
    • 调试信息,包含一份说明目标模块如何编译的简明描述,这样,调试器能够将机器指令关联到C源文件,并使数据结构也变得可读

    链接器

    将多个目标文件拼接成一个文件,最后生成可执行文件的一个工具。

    为什么需要链接器?

    这是为了解决修改一段代码会导致整个文件都需要重新编译和汇编。所以,就把一个文件拆分成多个文件,修改一段只需要编译和汇编一小段。

    链接器的工作分为三个步骤:

    1. 将代码和数据模块象征性放入内存
    2. 决定数据和指令标签的地址
    3. 修补内部和外部引用

    加载器

    将目标程序装载到内存中以准备运行的系统程序

    参考

    MIPS 汇编入门

    操作系统与CPU的指令集的关系是怎样的?

    CPU 指令集存在什么地方?

    计算机组成与设计—硬件软件接口

    展开全文
  • MIPS指令

    2021-02-03 10:56:40
    MIPS常用指令lb/lh/lw: 从存储器中读取一个byte/half word/word的数据到寄存器中.如lb $1, 0($2) sb/sh/sw: 把一个byte/half word/word的数据从寄存器存储到存储器中.如 sb $1, 0($2) add/addu:把两个定点寄存器...

    MIPS常用指令集

    lb/lh/lw: 从存储器中读取一个byte/half word/word的数据到寄存器中.如lb $1, 0($2)
    sb/sh/sw: 把一个byte/half word/word的数据从寄存器存储到存储器中.如 sb $1, 0($2)
    add/addu:把两个定点寄存器的内容相加add $1,$2,$3($1=$2+$3);u为不带符号加。

    addi/addiu:把一个寄存器的内容加上一个立即数add $1,$2,#3($1=$2+3);u为不带符号加。
    sub/subu:把两个定点寄存器的内容相减。
    div/divu:两个定点寄存器的内容相除。
    mul/mulu:两个定点寄存器的内容相乘。
    and/andi:与运算,两个寄存器中的内容相与and $1,$2,$3($1=$2 & $3);i为立即数。
    or/ori:或运算。
    xor/xori:异或运算。
    beq/beqz/benz/bne:条件转移eq相等,z零,ne不等。
    j/jr/jal/jalr:j直接跳转;jr使用寄存器跳转;
    lui:把一个16位的立即数填入到寄存器的高16位,低16位补零。
    sll/srl:逻辑左移/右移sll $1,$2,#2。
    slt/slti/sltui:如果$2的值小于$3,那么设置$1的值为1,否则设置$1的值为0。slt $1,$2,$3。
    mov/movz/movn:复制,n为负,z为零。mov $1,$2; movz $1,$2,$3($3为零则复制$2到$1)。
    trap:根据地址向量转入管态。
    eret:从异常中返回到用户态。

    32个通用寄存器

    0(zero):01(zero): 永远返回值为0 1(at): 用做汇编器的暂时变量
    2-3(v0v0-v1): 子函数调用返回结果
    4-7(a0a0-a3): 子函数调用的参数
    8-15(t0t0-t7): 暂时变量,子函数使用时不需要保存与恢复
    16-23(s0s0-s7): 子函数寄存器变量。子函数必须保存和恢复使用过的变量在函数返回之前,从而调用函数知道这些寄存器的值没有变化。
    24-25(t8t8-t9): 暂时变量,子函数使用时不需要保存与恢复
    26-27(k0k0-k1): 通常被中断或异常处理程序使用作为保存一些系统参数
    28(gp)便staticextern29(gp): 全局指针。一些运行系统维护这个指针来更方便的存取“static“和”extern”变量。 29(sp): 堆栈指针
    30(s8/s8/fp): 第9个寄存器变量。子函数可以用来做桢指针
    31($ra): 子函数的返回地
    cp0:协处理器0,MIPS对CPU的控制用cp0完成

    展开全文
  • MIPS 指令

    万次阅读 2017-05-10 14:53:27
    MIPS 指令   指令 功能 应用实例 LB 从存储器中读取一个字节的数据到寄存器中 LB R1, 0(R2) LH 从存储器中读取半个字的数据到寄存器中 ...

    MIPS 指令

     

    指令

    功能

    应用实例

    LB

    从存储器中读取一个字节的数据到寄存器中

    LB R1, 0(R2)

    LH

    从存储器中读取半个字的数据到寄存器中

    LH R1, 0(R2)

    LW

    从存储器中读取一个字的数据到寄存器中

    LW R1, 0(R2)

    LD

    从存储器中读取双字的数据到寄存器中

    LD R1, 0(R2)

    L.S

    从存储器中读取单精度浮点数到寄存器中

    L.S R1, 0(R2)

    L.D

    从存储器中读取双精度浮点数到寄存器中

    L.D R1, 0(R2)

    LBU

    功能与LB指令相同,但读出的是不带符号的数据

    LBU R1, 0(R2)

    LHU

    功能与LH指令相同,但读出的是不带符号的数据

    LHU R1, 0(R2)

    LWU

    功能与LW指令相同,但读出的是不带符号的数据

    LWU R1, 0(R2)

    SB

    把一个字节的数据从寄存器存储到存储器中

    SB R1, 0(R2)

    SH

    把半个字节的数据从寄存器存储到存储器中

    SH R1,0(R2)

    SW

    把一个字的数据从寄存器存储到存储器中

    SW R1, 0(R2)

    SD

    把两个字节的数据从寄存器存储到存储器中

    SD R1, 0(R2)

    S.S

    把单精度浮点数从寄存器存储到存储器中

    S.S R1, 0(R2)

    S.D

    把双精度数据从存储器存储到存储器中

    S.D R1, 0(R2)

    DADD

    把两个定点寄存器的内容相加,也就是定点加

    DADD R1,R2,R3

    DADDI

    把一个寄存器的内容加上一个立即数

    DADDI R1,R2,#3

    DADDU

    不带符号的加

    DADDU R1,R2,R3

    DADDIU

    把一个寄存器的内容加上一个无符号的立即数

    DADDIU R1,R2,#3

    ADD.S

    把一个单精度浮点数加上一个双精度浮点数,结果是单精度浮点数

    ADD.S F0,F1,F2

    ADD.D

    把一个双精度浮点数加上一个单精度浮点数,结果是双精度浮点数

    ADD.D F0,F1,F2

    ADD.PS

    两个单精度浮点数相加,结果是单精度浮点数

    ADD.PS F0,F1,F2

    DSUB

    两个寄存器的内容相减,也就是定点数的减

    DSUB R1,R2,R3

    DSUBU

    不带符号的减

    DSUBU R1,R2,R3

    SUB.S

    一个双精度浮点数减去一个单精度浮点数,结果为单精度

    SUB.S F1,F2,F3

    SUB.D

    一个双精度浮点数减去一个单精度浮点数,结果为双精度浮点数

    SUB.D F1,F2,F3

    SUB.PS

    两个单精度浮点数相减

    SUB.SP F1,F2,F3

    DDIV

    两个定点寄存器的内容相除,也就是定点除

    DDIV R1,R2,R3

    DDIVU

    不带符号的除法运算

    DDIVU R1,R2,R3

    DIV.S

    一个双精度浮点数除以一个单精度浮点数,结果为单精度浮点数

    DIV.S F1,F2,F3

    DIV.D

    一个双精度浮点数除以一个单精度浮点数,结果为双精度浮点数

    DIV.D F1,F2,F3

    DIV.PS

    两个单精度浮点数相除,结果为单精度

    DIV.PS F1,F2,F3

    DMUL

    两个定点寄存器的内容相乘,也就是定点乘

    DMUL R1,R2,R3

    DMULU

    不带符号的乘法运算

    DMULU R1,R2,R3

    MUL.S

    一个双精度浮点数乘以一个单精度浮点数,结果为单精度浮点数

    DMUL.S F1,F2,F3

    MUL.D

    一个双精度浮点数乘以一个单精度浮点数,结果为双精度浮点数

    DMUL.D F1,F2,F3

    MUL.PS

    两个单精度浮点数相乘,结果为单精度浮点数

    DMUL.PS F1,F2,F3

    AND

    与运算,两个寄存器中的内容相与

    ANDR1,R2,R3

    ANDI

    一个寄存器中的内容与一个立即数相与

    ANDIR1,R2,#3

    OR

    或运算,两个寄存器中的内容相或

    ORR1,R2,R3

    ORI

    一个寄存器中的内容与一个立即数相或

    ORIR1,R2,#3

    XOR

    异或运算,两个寄存器中的内容相异或

    XORR1,R2,R3

    XORI

    一个寄存器中的内容与一个立即数异或

    XORIR1,R2,#3

    BEQZ

    条件转移指令,当寄存器中内容为0时转移发生

    BEQZ R1,0

    BENZ

    条件转移指令,当寄存器中内容不为0时转移发生

    BNEZ R1,0

    BEQ

    条件转移指令,当两个寄存器内容相等时转移发生

    BEQ R1,R2

    BNE

    条件转移指令,当两个寄存器中内容不等时转移发生

    BNE R1,R2

    J

    直接跳转指令,跳转的地址在指令中

    J name

    JR

    使用寄存器的跳转指令,跳转地址在寄存器中

    JR R1

    JAL

    直接跳转指令,并带有链接功能,指令的跳转地址在指令中,跳转发生时要把返回地址存放到R31这个寄存器中

    JAL R1 name

    JALR

    使用寄存器的跳转指令,并且带有链接功能,指令的跳转地址在寄存器中,跳转发生时指令的放回地址放在R31这个寄存器中

    JALR R1

    MOV.S

    把一个单精度浮点数从一个浮点寄存器复制到另一个浮点寄存器

    MOV.S F0,F1

    MOV.D

    把一个双精度浮点数从一个浮点寄存器复制到另一个浮点寄存器

    MOV.D F0,F1

    MFC0

    把一个数据从通用寄存器复制到特殊寄存器

    MFC0 R1,R2

    MTC0

    把一个数据从特殊寄存器复制到通用寄存器

    MTC0 R1,R2

    MFC1

    把一个数据从定点寄存器复制到浮点寄存器

    MFC1 R1,F1

    MTC1

    把一个数据从浮点寄存器复制到定点寄存器

    MTC1 R1,F1

    LUI

    把一个16位的立即数填入到寄存器的高16位,低16位补零

    LUI R1,#42

    DSLL

    双字逻辑左移

    DSLL R1,R2,#2

    DSRL

    双字逻辑右移

    DSRL R1,R2,#2

    DSRA

    双字算术右移

    DSRA R1,R2,#2

    DSLLV

    可变的双字逻辑左移

    DSLLV R1,R2,#2

    DSRLV

    可变的双字罗伊右移

    DSRLV R1,R2,#2

    DSRAV

    可变的双字算术右移

    DSRAV R1,R2,#2

    SLT

    如果R2的值小于R3,那么设置R1的值为1,否则设置R1的值为0

    SLT R1,R2,R3

    SLTI

    如果寄存器R2的值小于立即数,那么设置R1的值为1,否则设置寄存器R1的值为0

    SLTI R1,R2,#23

    SLTU

    功能与SLT一致,但是带符号的

    SLTU R1,R2,R3

    SLTUI

    功能与SLT一致,但不带符号

    SLTUI R1,R2,R3

    MOVN

    如果第三个寄存器的内容为负,那么复制一个寄存器的内容到另外一个寄存器

    MOVN R1,R2,R3

    MOVZ

    如果第三个寄存器的内容为0,那么复制一个寄存器的内容到另外一个寄存器

    MOVZ R1,R2,R3

    TRAP

    根据地址向量转入管态

    ERET

    从异常中返回到用户态

    MADD.S

    一个双精度浮点数与单精度浮点数相乘加,结果为单精度

    MADD.D

    一个双精度浮点数与单精度浮点数相乘加,结果为双精度

    MADD.PS

    两个单精度浮点数相乘加,结果为单精度





    MIPS构架简介

        MIPS全称为icroprocessor without interlocked piped stages,意思是“无内部互锁流水级的微处理器”(M,其机制是尽量利用软件办法避免流水线中的数据相关问题。它最早是在80年代初期由斯坦福(Stanford)大学Hennessy教授领导的研究小组研制出来的。MIPS公司的R系列就是在此基础上开发的RISC工业产品的微处理器。这些系列产品为很多计算机公司采用构成各种工作站和计算机系统。 MIPS是出现最早的商业RISC架构芯片之一,新的架构集成了所有原来MIPS指令集,并增加了许多更强大的功能。

        MIPS是高效精简指令集计算机(RISC)体系结构中最优雅的一种;即使连MIPS的竞争对手也这样认为,这可以从MIPS对于后来研制的新型体系结构比如DEC的Alpha和HP的Precision产生的强烈影响看出来。虽然自身的优雅设计并不能保证在充满竞争的市场上长盛不衰,但是MIPS微处理器却经常能在处理器的每个技术发展阶段保持速度最快的同时保持设计的简洁。 

       MIPS的指令系统经过通用处理器指令体系MIPS I、MIPS II、MIPS III、MIPS IV到MIPS V,嵌入式指令体系MIPS16、MIPS32到MIPS64的发展已经十分成熟。在设计理念上MIPS强调软硬件协同提高性能,同时简化硬件设计。


    MIPS体系结构首先是一种RISC架构

    1 MIPS32架构中有32个通用寄存器,其中$0(无论你怎么设置,这个寄存器中保存的数据都是0)和$31(保存函数调用jal的返回地址)有着特殊的用途,其它的寄存器可作为通用寄存器用于任何一条指令中。

        虽然硬件没有强制性的指定寄存器使用规则,在实际使用中,这些寄存器的用法都遵循一系列约定。这些约定与硬件确实无关,但如果你想使用别人的代码,编译器和操作系统,你最好是遵循这些约定。

    [plain] view plain copy
     print?在CODE上查看代码片派生到我的代码片
    1. ;REGISTER            NAME             USAGE  
    2. $0                   $zero            常量0(constantvalue 0)         永远返回值为0  
    3. $2-$3                $v0-$v1          子函数调用返回值(values for results and expressionevaluation)  
    4. $4-$7                $a0-$a3          子函数调用参数(arguments)  
    5. $8-$15               $t0-$t7          暂时的(或随便用的)  
    6. $16-$23              $s0-$s7          保存的(或如果用,需要SAVE/RESTORE的)(saved)  
    7.                                       子函数寄存器变量。子函数必须保存和恢复使用过的变量在函数 返回之前,从而调用函数知道这些寄存器的值没有变化。    
    8. $24-$25              $t8-$t9          暂时的(或随便用的)  
    9. $26-$27              $k0-$k1          通常被中断或异常处理程序使用作为保存一些系统参数  
    10. $28                  $gp              全局指针(GlobalPointer) 一些运行系统维护这个指针来更方便的存取“static“和”extern" 变量。  
    11. $29                  $sp              堆栈指针(StackPointer)  
    12. $30                  $fp              帧指针(FramePointer) 第9个寄存器变量。子函数可以用来做桢指针  
    13. $31                  $ra              子函数的返回地址(returnaddress)  


    2 MIPS32中如果有FPA
        将会有32个浮点寄存器,按汇编语言的约定为$f0~$f31,MIPS32中只能使用偶数号的浮点寄存器,奇数号的用途是:在做双精度的浮点运算时,存放该奇数号之前的偶数号浮点寄存器的剩余无法放下的32位。比如在做双精度的浮点运算时,$1存放$0的剩余的部分,所以在MIPS32中可以通过加载偶数号的浮点寄存器而把64位的双精度数据加载到两个浮点寄存器中,每个寄存器存放32位。

    比如:
    l.d $02, 24(t1)
    被扩充为两个连续的寄存器加载:
    lwc1 $f0, 24(t1)
    lwc1 $f1, 28(t1)



    3 MIPS架构中没有X86中的PC(程序计数)寄存器
       它的程序计数器不是一个寄存器。因为在MIPS这样具有流水线结构的CPU中,程序计数器在同一时刻可以有多个给定的值,如 jal 指令的返回地址跟随其后的第二条指令。
    ...
    jal printf
    move $4, $6
    xxx                          #return here after call
    MIPS32中也没有条件码,比如在X86中常见的状态寄存器中的Z、C标志位在MIPS32中是没有的,但是MIPS32中有状态寄存器


    4 MIPS32中不同于其它的RISC架构的地方是其有整数乘法部件
    这个部件使用两个特殊的寄存器HI、LO,并且提供相应的指令 mfhi/mthi,mthi/mtlo来实现整数乘法结果--hi/lo寄存器与通用寄存器之间的数据交换


    5 数据加载与存储.
      MIPS CPU可以在一个单一操作中存储1到8个字节。文档中和用来组成指令助记符的 命名约定如下:

    [plain] view plain copy
     print?在CODE上查看代码片派生到我的代码片
    1. C名字            MIPS名字          大小(字节)                    汇编助记符  
    2. long long        dword                8                        "d"代表ld  
    3. int/long          word                4                        "w"代表lw  
    4. short            half word            2                        "h"代表lh  
    5. char              byte                1                         "b"代表lb  

    5.1数据加载.包括这样几条记载指令  LB/LBU、LH/LHU、LW
        byte和short的加载有两种方式。带符号扩展的lb和lh指令将数据值存放在32位寄存器的低位中,剩下的高位用符号位的值来扩充(位7如果是一个byte,位15如果是一个short)。这样就正确地将一个带符号整数放入一个32位的带符号的寄存器中。
       不带符号指令lbu和lhu用0来扩充数据,将数据存放在32位寄存器的低位中,并将高位用零来填充。例如,如果一个byte字节宽度的存储器地址为t1,其值为0xFE(-2或254如果是非符号数),那么将会在t2中放入0xFFFFFFFE(-2作为一个符号数)。t3的值会是0x000000FE(254作为一个非符号数)
    [plain] view plain copy
     print?在CODE上查看代码片派生到我的代码片
    1. lb   t2, 0(t1)  
    2. lbu  t3, 0(t1)  

    5.2数据存储.包括这样几条指令SB、SH、SW
    由于加载就是把寄存器中的数据加载到内存中,所以不存在位扩展的问题。


    6 CP0 (协处理器0)--MIPS处理器控制.

    用于控制和设置MIPS CPU,里面包含了一些寄存器,通过对这些寄存器的不同的位的操作可以实现对处理器的设置
    CP0类似于X 86只能由内核 (高优先级权限)访问的一些处理器资源
    而前面提到的通用寄存器GPR和FPR则可以有由所有的优先级权限访问
    CP0提供了中断异常处理、内存管理(包括CACHE、TLB)、外设管理等途径(而这些只能由高优先级的内核才能访问到)。

    MIPS体系结构中集成了一个叫做 System Control Coprocessor (CP0)的部件。CP0就是我们常说的MMU控制器。在CP0中,除了TLB entry(例如,对RM5200,有48pair,96个TLB entry),一些控制寄存器提供给OSKERNEL来控制MMU的行为。每个CP0控制寄存器都对应一个唯一的寄存器号。MIPS提供特殊的指令来对CP0进行操作。

    [plain] view plain copy
     print?在CODE上查看代码片派生到我的代码片
    1. mfc0 reg. CP0_REG                把一个数据从特殊寄存器复制到通用寄存器                
    2. mtc0 reg. CP0_REG                把一个数据从通用寄存器复制到特殊寄存器      

    我们通过上述的两条指令来把一个GPR寄存器的值assign给一个CP0寄存器,从而达到控制MMU的目的。

    面简单介绍几个与TLB相关的CP0控制寄存器。
    Index Register
    这个寄存器是用来指定TLB entry的,当你进行TLB读写的时候。我们已经知道,例如,MIPS R5提供48个TLBpair,所以index寄存器的值是从0到47。换句话说,每次TLB写的行为是对一个pair发生的。这一点是与其他的CPU MMUTLB 读写不同的。 EntryLo0, EntryLo1 这两个寄存器是用来specify 一个TLBpair的偶(even)和奇(odd)物理(Physical)页面地址。


    6.1常见的MIPS CPU控制寄存器包括:

    SR( 状态寄存器) 12
    Config (CPU参数设置寄存器)-16
    EPC (例外程序寄存器)13、 

    CAUSE(导致中断和异常的原因寄存器) 14、

    BadVaddr(地址错误时存放地址的寄存器)8
    Index-0、Random-1、EntryLo0-2、EntryLo1-3、EntryHi-10、PageMask
    Count-9、Compare-11共同组成了高精度的时钟


    6.2CP0寄存器的访问指令

    mtc0 ts,                 #把通用寄存器 ts中的数据送到协处理器0中的寄存器nn
    mfc0 ts,                 #把送到协处理器0中寄存器 nn 的值送到通用寄存器ts
    dmtc0 ts,              #把通用寄存器 ts中的数据送到协处理器0中的寄存器nn
    dmfc0 ts,              #把送到协处理器0中寄存器 nn 的值送到通用寄存器ts



    6.3起作用的寄存器及其作用时机
    加电后:你需要设置SR和Config寄存器,以确保CPU进入正确的引导状态,并且SR寄存器还设置了中断码。以决定系统响应哪些中断。
    进入任何异常:处理任何例外都会调用一个“通用异常处理程序”。MIPS体系并没有为进入异常作任何的寄存器保存,也没有关于堆栈方面的任何支持,进入异常时唯一保存的就是                              异 常返回地址保存在EPC中。所以这些都需要操作系统的软件实现。操作系统可以使用K0或者K1寄存器作为堆栈指针,指向某个位置,并且在需要保存的寄存器

                             保存到这个栈上。然后通过Cause寄存器找到发生异常的原因,这样才能跳转到对应的中断处理程序中。
    从异常返回:  从异常返回到EPC制定的地址之前要把CPU的状态回复到异常之前,好象什么事情都没有发生一样。在R3000中使用rfe指令作这样的事情,但是着条指令仅仅恢复了                         一些寄存器中的内容,但是并没有转移控制指令,你需要把EPC内容保存到一个通用寄存器中,然后调用jr指令返回到EPC指向的地址处,


    7 MIPS的存储管理模型.MIPS32中的存储器模型被划分为四个大块,其中:
    0x0000,0000~0x7fff,ffff(0~2G-1) USEG
    must be mapped (set page table and TLB)and set cache before use
    0x8000,0000~0x9fff,ffff(2G~2.5G-1) KSEG0
    directly mapped(no need to set page table and TLB) but need to set cache before use
    0xa000,0000~0xbfff,ffff(2.5G~3G-1) KSEG1
    directly mapped(no need to set page table and TLB) and never use cache
    0xc000,0000~0xffff,ffff(3G~4G-1) KSEG2
    muse be mapped(set page table and TLB) and set cache before use


    这样的存储器管理模型和X86差距比较大,X86有一个实模式,内核在启动保护模式之前,运行在实模式之下,直到设定了保护模式之后才能运行在保护模式下。在MIPS32中没有保护模式那么系统是如何启动的呢?

    可以直观的看到只有kseg1是不需要映射(物理虚拟转换),没有被缓存的,也就是说只有kseg1的内存区域可以做引导的存储区(在这里放置引导用flash 存储器).被cached区域必须等到MMU 的TLB被初始化后才可以使用的。

    MIPS32中的系统启动向量位于KSEG1中0xbf10,0000,由于KSEG1是directly mapped的,所以直接对应了物理地址0x1fc0,0000,你可以在内核中一直使用0xa000,0000~0xbfff,ffff之间的虚拟地址来访问物理地址0~512M-1,在设置了KSEG0的cache之后,也可一使用0x8000,0000~0x9fff,ffff之间的虚拟地址来访问0~512M-1之间的物理地址。对于512M以上的物理地址只能由KSEG2和USEG通过页表访问。


    8 MIPS32中的状态寄存器SR.状态寄存器来设置处理器的一些功能集合,包括设置

    设置协处理器0~3的可用性的位 CU0~CU3(28~31)
    复位向量  BEV
    中断屏蔽位8~15
    KUc、IEc0~1,基本的CPU保护单位
    KUc为1时表示运行在内核态,为0时运行在用户模式。在内核态下,可以访问所有的地址空间和协处理器0,运行在用户态下值只能访问0x0000,0000~0x7fff,ffff之间的地址空间。
    KUp、IEp2~3
    当异常发生时,硬件把KUc、IEc的值保存到KUp、IEp中,并且将KUc、IEc设置为[1,0]--内核态、关中断。异常返回时rfe指令可以把KUp、IEp的内容复制到KUc、IEc中
    KUo、IEo
    当异常发生时,硬件把KUp、IEp的值保存到KUo、IEo中;返回时把KUo、IEo的内容复制到KUp、IEp中。
    上面三对KU/IE位构成了深度2的栈,异常发生时,硬件自动压栈,rfe指令从异常返回时,从栈中恢复数值
    还有一些其它的功能和状态位,可以参考相应的文档


    9 MIPS32中的Cause寄存器 

    BD位:EPC中正常情况下存放了发生异常的指令,但是当着条指令存放在调转指令的延迟槽中时,那么EPC中存放的是这个跳转指令,否则这条跳转指令将得不到执行。
    IP位:告诉用户来临的中断
    ExcCode:这是一个5位的代码,告诉你哪一条异常发生了,可以根据这个从通用异常处理程序跳装到特定异常处理程序中。

    10 MIPS32的C语言中参数传递和返回值的约定 

    caller至少使用16bytes 堆栈空间存放参数,然后把这16 bytes存放到通用寄存器a0~a3中, called subroutine 直接使用寄存器中的参数,同时caller 堆栈中的16bytes的数据可以不去理会了。
    需要理解的是带有浮点参数和结构体的参数传递,对于带有浮点参数的传递需要看第一个参数是否是浮点,如果是浮点则将参数放到 $f12和$f14这两个浮点寄存器中,如果第一个参数不是浮点数,则不用浮点寄存器存放参数。对于结构体的参数传递和x86类似
    对于整数和指针类型的参数返回值一般通过通用寄存器v0($2)返回,对于浮点返回类型,一般存放在$f0中返回。



    参考文章:

    http://mips.eefocus.com/article/10-04/261271061334.html

    http://www.52solution.com/basic/1678?page=1



    指令

    功能

    应用实例

    LB

    从存储器中读取一个字节的数据到寄存器中

    LB R1, 0(R2)

    LH

    从存储器中读取半个字的数据到寄存器中

    LH R1, 0(R2)

    LW

    从存储器中读取一个字的数据到寄存器中

    LW R1, 0(R2)

    LD

    从存储器中读取双字的数据到寄存器中

    LD R1, 0(R2)

    L.S

    从存储器中读取单精度浮点数到寄存器中

    L.S R1, 0(R2)

    L.D

    从存储器中读取双精度浮点数到寄存器中

    L.D R1, 0(R2)

    LBU

    功能与LB指令相同,但读出的是不带符号的数据

    LBU R1, 0(R2)

    LHU

    功能与LH指令相同,但读出的是不带符号的数据

    LHU R1, 0(R2)

    LWU

    功能与LW指令相同,但读出的是不带符号的数据

    LWU R1, 0(R2)

    SB

    把一个字节的数据从寄存器存储到存储器中

    SB R1, 0(R2)

    SH

    把半个字节的数据从寄存器存储到存储器中

    SH R1,0(R2)

    SW

    把一个字的数据从寄存器存储到存储器中

    SW R1, 0(R2)

    SD

    把两个字节的数据从寄存器存储到存储器中

    SD R1, 0(R2)

    S.S

    把单精度浮点数从寄存器存储到存储器中

    S.S R1, 0(R2)

    S.D

    把双精度数据从存储器存储到存储器中

    S.D R1, 0(R2)

    DADD

    把两个定点寄存器的内容相加,也就是定点加

    DADD R1,R2,R3

    DADDI

    把一个寄存器的内容加上一个立即数

    DADDI R1,R2,#3

    DADDU

    不带符号的加

    DADDU R1,R2,R3

    DADDIU

    把一个寄存器的内容加上一个无符号的立即数

    DADDIU R1,R2,#3

    ADD.S

    把一个单精度浮点数加上一个双精度浮点数,结果是单精度浮点数

    ADD.S F0,F1,F2

    ADD.D

    把一个双精度浮点数加上一个单精度浮点数,结果是双精度浮点数

    ADD.D F0,F1,F2

    ADD.PS

    两个单精度浮点数相加,结果是单精度浮点数

    ADD.PS F0,F1,F2

    DSUB

    两个寄存器的内容相减,也就是定点数的减

    DSUB R1,R2,R3

    DSUBU

    不带符号的减

    DSUBU R1,R2,R3

    SUB.S

    一个双精度浮点数减去一个单精度浮点数,结果为单精度

    SUB.S F1,F2,F3

    SUB.D

    一个双精度浮点数减去一个单精度浮点数,结果为双精度浮点数

    SUB.D F1,F2,F3

    SUB.PS

    两个单精度浮点数相减

    SUB.SP F1,F2,F3

    DDIV

    两个定点寄存器的内容相除,也就是定点除

    DDIV R1,R2,R3

    DDIVU

    不带符号的除法运算

    DDIVU R1,R2,R3

    DIV.S

    一个双精度浮点数除以一个单精度浮点数,结果为单精度浮点数

    DIV.S F1,F2,F3

    DIV.D

    一个双精度浮点数除以一个单精度浮点数,结果为双精度浮点数

    DIV.D F1,F2,F3

    DIV.PS

    两个单精度浮点数相除,结果为单精度

    DIV.PS F1,F2,F3

    DMUL

    两个定点寄存器的内容相乘,也就是定点乘

    DMUL R1,R2,R3

    DMULU

    不带符号的乘法运算

    DMULU R1,R2,R3

    MUL.S

    一个双精度浮点数乘以一个单精度浮点数,结果为单精度浮点数

    DMUL.S F1,F2,F3

    MUL.D

    一个双精度浮点数乘以一个单精度浮点数,结果为双精度浮点数

    DMUL.D F1,F2,F3

    MUL.PS

    两个单精度浮点数相乘,结果为单精度浮点数

    DMUL.PS F1,F2,F3

    AND

    与运算,两个寄存器中的内容相与

    ANDR1,R2,R3

    ANDI

    一个寄存器中的内容与一个立即数相与

    ANDIR1,R2,#3

    OR

    或运算,两个寄存器中的内容相或

    ORR1,R2,R3

    ORI

    一个寄存器中的内容与一个立即数相或

    ORIR1,R2,#3

    XOR

    异或运算,两个寄存器中的内容相异或

    XORR1,R2,R3

    XORI

    一个寄存器中的内容与一个立即数异或

    XORIR1,R2,#3

    BEQZ

    条件转移指令,当寄存器中内容为0时转移发生

    BEQZ R1,0

    BENZ

    条件转移指令,当寄存器中内容不为0时转移发生

    BNEZ R1,0

    BEQ

    条件转移指令,当两个寄存器内容相等时转移发生

    BEQ R1,R2

    BNE

    条件转移指令,当两个寄存器中内容不等时转移发生

    BNE R1,R2

    J

    直接跳转指令,跳转的地址在指令中

    J name

    JR

    使用寄存器的跳转指令,跳转地址在寄存器中

    JR R1

    JAL

    直接跳转指令,并带有链接功能,指令的跳转地址在指令中,跳转发生时要把返回地址存放到R31这个寄存器中

    JAL R1 name

    JALR

    使用寄存器的跳转指令,并且带有链接功能,指令的跳转地址在寄存器中,跳转发生时指令的放回地址放在R31这个寄存器中

    JALR R1

    MOV.S

    把一个单精度浮点数从一个浮点寄存器复制到另一个浮点寄存器

    MOV.S F0,F1

    MOV.D

    把一个双精度浮点数从一个浮点寄存器复制到另一个浮点寄存器

    MOV.D F0,F1

    MFC0

    把一个数据从通用寄存器复制到特殊寄存器

    MFC0 R1,R2

    MTC0

    把一个数据从特殊寄存器复制到通用寄存器

    MTC0 R1,R2

    MFC1

    把一个数据从定点寄存器复制到浮点寄存器

    MFC1 R1,F1

    MTC1

    把一个数据从浮点寄存器复制到定点寄存器

    MTC1 R1,F1

    LUI

    把一个16位的立即数填入到寄存器的高16位,低16位补零

    LUI R1,#42

    DSLL

    双字逻辑左移

    DSLL R1,R2,#2

    DSRL

    双字逻辑右移

    DSRL R1,R2,#2

    DSRA

    双字算术右移

    DSRA R1,R2,#2

    DSLLV

    可变的双字逻辑左移

    DSLLV R1,R2,#2

    DSRLV

    可变的双字罗伊右移

    DSRLV R1,R2,#2

    DSRAV

    可变的双字算术右移

    DSRAV R1,R2,#2

    SLT

    如果R2的值小于R3,那么设置R1的值为1,否则设置R1的值为0

    SLT R1,R2,R3

    SLTI

    如果寄存器R2的值小于立即数,那么设置R1的值为1,否则设置寄存器R1的值为0

    SLTI R1,R2,#23

    SLTU

    功能与SLT一致,但是带符号的

    SLTU R1,R2,R3

    SLTUI

    功能与SLT一致,但不带符号

    SLTUI R1,R2,R3

    MOVN

    如果第三个寄存器的内容为负,那么复制一个寄存器的内容到另外一个寄存器

    MOVN R1,R2,R3

    MOVZ

    如果第三个寄存器的内容为0,那么复制一个寄存器的内容到另外一个寄存器

    MOVZ R1,R2,R3

    TRAP

    根据地址向量转入管态

    ERET

    从异常中返回到用户态

    MADD.S

    一个双精度浮点数与单精度浮点数相乘加,结果为单精度

    MADD.D

    一个双精度浮点数与单精度浮点数相乘加,结果为双精度

    MADD.PS

    两个单精度浮点数相乘加,结果为单精度





    展开全文
  • MBUS_MSG指令

    2021-01-20 16:54:31
    MBUS_MSG指令输入/输出操作数数据类型首次布尔I,Q,M,S,SM,T,C,V,L(以上升沿检测元素为条件的功率流)从站字节VB,IB,QB,MB,SB,SMB,LB,AC,Constant*V
  • 递增、递减指令递增、递减指令用于对输入无符号数字节、符号数字、符号数双字进行加1或减1的操作。指令格式如表5-19所示。1.递增字节(INC-B)/递减字节(DEC-B)指令递增字节和递减字节指令在输入字节(IN)上加1或减1,...
  • MIPS指令

    千次阅读 2017-02-05 12:26:39
    MIPS指令集 MIPS指令集属于精简指令集 MIPS的所有指令都是32位,指令格式简单,而X86的指令长度不是固定的。 简单的指令和格式易于译码和流水线操作,但是代码密度不高,导致二进制文件大 MIPS有32个通用...
  • mips指令

    2013-01-22 16:45:14
    MIPS 指令   指令 功能 应用实例 LB 从存储器中读取一个字节的数据到寄存器中 LB R1, 0(R2) LH 从存储器中读取半个字的数据到寄存器中 ...
  • 32位mips指令说明

    万次阅读 多人点赞 2019-04-27 21:45:32
    指令(1条) nop指令 逻辑运算指令(8条) and、or、xor、nor指令 当功能码是6b100100时,表示是and指令,逻辑“与”运算。 指令用法为:and rd,rs,rt。 指令作用为:rd ← rs AND rt,将地址为rs的...
  • 指令入门

    2020-09-17 12:05:09
    计算机指令_汇编指令入门助记符寻址模式(Addressing Model)寄存器寻址立即寻址偏移量寻址PC相对寻址指令类型内存读写数学运算浮点数浮点小数![在这里插入图片描述]...
  • 计算机指令就是指挥机器工作的指示和命令,程序就是一系列按一定顺序排列的指令,执行程序的过程就是计算机的工作过程。通常一条指令包括两方面的内容: [1]操作码和操作数,操作码决定要完成的操作,操作数指参加...
  • mips指令

    2016-11-06 09:50:51
    mips 指令集小结
  • MIPS 指令 系统中常用指令

    千次阅读 2011-11-14 20:07:21
    指令 功能 应用实例 LB 从存储器中读取一个字节的数据到寄存器中 LB R1, 0(R2) LH 从存储器中读取半个字的数据到寄存器中 LH R1, 0(R2) LW 从存储器...
  • MIPS汇编指令

    万次阅读 多人点赞 2016-03-30 16:55:37
    MIPS汇编MIPS指令集 MIPS指令集属于精简指令集 MIPS的所有指令都是32位,指令格式简单,而X86的指令长度不是固定的。 简单的指令和格式易于译码和流水线操作,但是代码密度不高,导致二进制文件大 ...
  • 加载存储指令说明加载指令(7) lb、lbu、lh、lhu、lw、lwl、lwr存储指令(5) sb、sh、sw、swl、swr补充 加载指令(7) lb、lbu、lh、lhu、lw、lwl、lwr op[31:26] base[25:21] rt[20:16] offset[15:0] ...
  • mips指令简单入门

    万次阅读 多人点赞 2016-06-30 23:59:15
    MIPS Architecture and Assembly Language Overview MIPS架构及其汇编初步 ... 2: 算术及寻址指令  3: 程序结构  4: 系统调用  Data Types and Literals 数据类型(及字符) Data
  • 9.1.1 加载指令lb、lbu、lh、lhu、lw说明 9.1.2 存储指令sb、sh、sw说明 9.1.3 加载存储指令用法示例 OpenMIPS处理器是按照字节寻址,并且是大端模式,在这种模式下,数据的高位保存在存储器的低地址中,而数据的...
  • SLT/SLTU/ADDI/ADDIU/ANDI/ORI/XORI/LUI/SLTI/SLTIU/LB/LBU/LH/LH U/LW/SB/SH/SW/BEQ/BNE/BGEZ/BGTZ/BLEZ/BLTZ/J/JAL/JR/JALR} 42条 • ISA2 = {add, sub, addu, subu, addi, ori, lui, and, andi, or, nor,slt, ...
  • ARM指令系统

    万次阅读 2017-08-19 22:22:24
    第3章 ARM指令系统 3.1 ARM处理器的指令格式 ...ARM内核属于RISC结构,所以其指令集有着一些独特的特点:指令长度固定,指令格式的种类少,寻址方式简单。由于ARM处理器采用固定长度的32位指令,因此处理器内部
  • (1)RISC-V指令集介绍 RISCV指令集是UC Berkley 大学设计的第五代开源 RISC ISA, V 暗示了支持变种(Variations)和向量(Vector),其中数据的并型加速功能也是设计的明确目标,这是当今专用硬件的一个重要发展方向...
  • 精简指令集(MIPS为例)常用指令特点及其格式 一、指令指令集是指一台计算机的全部指令;不同的计算机有不同的指令集,但是在许多方面都有共同之处。早期的计算机有非常简单的指令集:实现简单,许多现代计算机也...
  • MIPS32指令

    千次阅读 2015-01-06 18:29:41
    MIPS指令可以分成以下各类:  空操作no-op;  寄存器/寄存器传输:用得很广,包括条件传输在内;  常数加载:作为数值和地址的整型立即数;  算术/逻辑指令;  整数乘法、除法和求余数;  整数乘加;...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 597
精华内容 238
关键字:

lbsb指令