MIPS Architecture and Assembly Language Overview

MIPS架构及其汇编初步

(开始之前稍微再提下,整体分为4个结构:)

  1: 寄存器种类;

  2: 算术及寻址指令

  3: 程序结构

  4: 系统调用 

Data Types and Literals

数据类型(及字符)

Data types:

  • Instructions are all 32 bits
  • 所有MIPS指令都是32位长的
  • byte(8 bits), halfword (2 bytes), word (4 bytes)
  • 各单位:1字节=8位,半字长=2个字节,1字长=4个字节
  • a character requires 1 byte of storage
  • 一个字符空间=1个字节
  • an integer requires 1 word (4 bytes) of storage
  • 一个整型=一个字长=4个字节

    Literals:

  • numbers entered as is. e.g. 4
  • 数字就是数字,例如:4
  • characters enclosed in single quotes. e.g. 'b'
  • 单个字符用单引号,例如:'b'
  • strings enclosed in double quotes. e.g. "A string"
  • 字符串用双引号,例如:"A string"

    Registers

    寄存器

  • 32 general-purpose registers
  • MIPS下一共有32个通用寄存器
  • register preceded by $ in assembly language instruction
  • 在汇编中,寄存器标志由$符开头
    two formats for addressing:
  • 寄存器表示可以有两种方式:
  • using register number e.g. $0 through $31
  • 直接使用该寄存器对应的编号,例如:从$0到$31
  • using equivalent names e.g. $t1, $sp
  • 使用对应的寄存器名称,例如:$t1, $sp(详细含义,下文有表格special registers Lo and Hi used to store result of multiplication and division 对于乘法和除法分别有对应的两个寄存器$lo, $hi
  • not directly addressable; contents accessed with special instruction mfhi ("move from Hi") and mflo ("move from Lo")
  • 对于以上二者,不存在直接寻址;必须要通过mfhi("move from hi")以及mflo("move from lo")分别来进行访问对应的内容
  • stack grows from high memory to low memory
  • 栈的走向是从高地址到低地址
    This is from Figure 9.9 in the Goodman&Miller text
    MIPS下各个寄存器编号及描述:

    Register
    Number

    寄存器编号

    Alternative 
    Name

    寄存器名

    Description

    寄存器用途

    0
    zero

    the value 0

    永远返回零

    1
    $at

    (assembler temporary) reserved by the assembler

    汇编保留寄存器(不可做其他用途)

    2-3
    $v0 - $v1

    (values) from expression evaluation and function results

    Value简写)存储表达式或者是函数的返回值

    4-7
    $a0 - $a3

    (arguments) First four parameters for subroutine.
    Not preserved across procedure calls

    Argument简写)存储子程序的前4个参数,在子程序调用过程中释放

    8-15
    $t0 - $t7

    (temporaries) Caller saved if needed. Subroutines can use w/out saving.
    Not preserved across procedure calls

    Temp简写)临时变量,同上调用时不保存

    16-23
    $s0 - $s7

    (saved values) - Callee saved. 
    A subroutine using one of these must save original and restore it before exiting.
    Preserved across procedure calls

    Saved or Static简写?)静态变量?调用时保存

    24-25
    $t8 - $t9

    (temporaries) Caller saved if needed. Subroutines can use w/out saving.
    These are in addition to $t0 - $t7 above.
    Not preserved across procedure calls.

    Temp简写)算是前面$0~$7的一个继续,属性同$t0~$t7

    26-27
    $k0 - $k1

    reserved for use by the interrupt/trap handler

    (breaK off简写?)中断函数返回值,不可做其他用途

    28
    $gp

    global pointer. 
    Points to the middle of the 64K block of memory in the static data segment.

    Global Pointer简写)指向64k(2^16)大小的静态数据块的中间地址(字面上好像就是这个意思,块的中间)

    29
    $sp

    stack pointer 
    Points to last location on the stack.

    (Stack Pointer简写)栈指针,指向的是栈顶

    30
    $s8/$fp

    saved value / frame pointer
    Preserved across procedure calls

    (Saved/Frame Pointer简写)帧指针

    31
    $ra

    return address

    返回地址,目测也是不可做其他用途

    Program Structure

    程序结构

  • just plain text file with data declarations, program code (name of file should end in suffix .s to be used with SPIM simulator)
  • 其实就只是数据声明+普通文本+程序编码(文件后缀为.s,或者.asm也行)
  • data declaration section followed by program code section
  • 数据声明在代码段之后(其实在其之前也没啥问题,也更符合高级程序设计的习惯)

    Data Declarations

    数据声明

  • placed in section of program identified with assembler directive .data
  • 数据段以 .data为开始标志
  • declares variable names used in program; storage allocated in main memory (RAM)
  • 声明变量后,即在主存中分配空间。

    Code

    代码

  • placed in section of text identified with assembler directive .text
  • 代码段以 .text为开始标志
  • contains program code (instructions)
  • 其实就是各项指令操作
  • starting point for code e.g.ecution given label main:
  • 程序入口为main:标志(这个都一样啦)
  • ending point of main code should use exit system call (see below under System Calls)
  • 程序结束标志(详见下文)

    Comments

  • anything following # on a line
  • 同C系语言
    # This stuff would be considered a comment
  • Template for a MIPS assembly language program:
  • MIPS程序的基本模板如下:
    # Comment giving name of program and description of function# 说明下程序的目的和作用(其实和高级语言都差不多了)
    # Template.s
    # Bare-bones outline of MIPS assembly language program.data       # variable declarations follow this line                    # 数据变量声明# ....text       # instructions follow this line  # 代码段部分
    main:                  # indicates start of code (first instruction to execute)                       # 主程序# ...# End of program, leave a blank line afterwards to make SPIM happy# 必须多给你一行,你才欢?

      

    Data Declarations

    数据声明

    format for declarations:

    声明的格式:

    name:                   storage_type    value(s)    变量名:(冒号别少了)     数据类型         变量值     
  • create storage for variable of specified type with given name and specified value
  • value(s) usually gives initial value(s); for storage type .space, gives number of spaces to be allocated
  • 通常给变量赋一个初始值;对于.space,需要指明需要多少大小空间(bytes)

    Note: labels always followed by colon ( : )

    examplevar1:      .word   3   # create a single integer variable with initial value 3                   # 声明一个 word 类型的变量 var1, 同时给其赋值为 3
    array1:     .byte   'a','b' # create a 2-element character array with elements initialized#   to  a  and  b                   # 声明一个存储2个字符的数组 array1,并赋值 'a', 'b'
    array2:     .space  40  # allocate 40 consecutive bytes, with storage uninitialized#   could be used as a 40-element character array, or a#   10-element integer array; a comment should indicate which!                       # 为变量 array2 分配 40字节(bytes)未使用的连续空间,当然,对于这个变量                   # 到底要存放什么类型的值, 最好事先声明注释下!

    Load / Store Instructions

    加载/保存(也许这里写成读取/写入 可能更易理解一点) 指令集

  • RAM access only allowed with load and store instructions
  • 如果要访问内存,不好意思,你只能用 load 或者 store 指令
  • all other instructions use register operands
  • 其他的只能都一律是寄存器操作

    load:

     lw  register_destination, RAM_source

    #copy word (4 bytes) at source RAM location to destination register.

    从内存中 复制 RAM_source 的内容到 对应的寄存器中

    (lw中的'w'意为'word',即该数据大小为4个字节)

      lb  register_destination, RAM_source

    #copy byte at source RAM location to low-order byte of destination register,
    # and sign-e.g.tend to higher-order bytes

    同上, lb 意为 load byte

    store word:

       sw  register_source, RAM_destination

    #store word in source register into RAM destination

    #将指定寄存器中的数据 写入 到指定的内存中

        sb  register_source, RAM_destination

    #store byte (low-order) in source register into RAM destination

    load immediate:

       li  register_destination, value

    #load immediate value into destination register

    顾名思义,这里的 li 意为 load immediate

    example:.data
    var1:   .word   23      # declare storage for var1; initial value is 23# 先声明一个 word 型的变量 var1 = 3;.text
    __start:lw  $t0, var1   # load contents of RAM location into register $t0:  $t0 = var1                   # 令寄存器 $t0 = var1 = 3;li    $t1, 5      # $t1 = 5   ("load immediate")                   # 令寄存器 $t1 = 5;sw  $t1, var1   # store contents of register $t1 into RAM:  var1 = $t1                   # 将var1的值修改为$t1中的值: var1 = $t1 = 5;done

    Indirect and Based Addressing

    立即与间接寻址

  • Used only with load and store instructions

    load address:

    直接给地址

      la  $t0, var1
  • copy RAM address of var1 (presumably a label defined in the program) into register $t0

    indirect addressing:

    地址是寄存器的内容(可以理解为指针)

       lw  $t2, ($t0)
  • load word at RAM address contained in $t0 into $t2
        sw  $t2, ($t0)
  • store word in register $t2 into RAM at address contained in $t0

    based or indexed addressing:

    +偏移量

     lw  $t2, 4($t0)
  • load word at RAM address ($t0+4) into register $t2
  • "4" gives offset from address in register $t0
     sw  $t2, -12($t0)
  • store word in register $t2 into RAM at address ($t0 - 12)
  • negative offsets are fine

    Note: based addressing is especially useful for:

    不必多说,要用到偏移量的寻址,基本上使用最多的场景无非两种:数组,栈。

  • arrays; access elements as offset from base address
  • stacks; easy to access elements at offset from stack pointer or frame pointer
    example:栗子:.data
    array1:     .space  12      #  declare 12 bytes of storage to hold array of 3 integers                        #  定义一个 12字节 长度的数组 array1, 容纳 3个整型.text
    __start:    la  $t0, array1 #  load base address of array into register $t0                        #  让 $t0 = 数组首地址li  $t1, 5      #  $t1 = 5   ("load immediate")sw $t1, ($t0)     #  first array element set to 5; indirect addressing                        # 对于 数组第一个元素赋值 array[0] = $1 = 5li $t1, 13        #   $t1 = 13sw $t1, 4($t0)     #  second array element set to 13                        # 对于 数组第二个元素赋值 array[1] = $1 = 13                         # (该数组中每个元素地址相距长度就是自身数据类型长度,即4字节, 所以对于array+4就是array[1])li $t1, -7      #   $t1 = -7sw $t1, 8($t0)     #  third array element set to -7                        # 同上, array+8 = (address[array[0])+4)+ 4 = address(array[1]) + 4 = address(array[2])done
    

    Arithmetic Instructions

    算术指令集

  • most use 3 operands
  • 最多3个操作数
  • all operands are registers; no RAM or indirect addressing
  • 再说一遍,在这里,操作数只能是寄存器,绝对不允许出现地址
  • operand size is word (4 bytes)
  • 所有指令统一是32位 = 4 * 8 bit = 4bytes = 1 word

    add $t0,$t1,$t2 # $t0 = $t1 + $t2; add as signed (2's complement) integers

           sub $t2,$t3,$t4 #  $t2 = $t3 Ð $t4addi $t2,$t3, 5  #  $t2 = $t3 + 5;   "add immediate" (no sub immediate)addu  $t1,$t6,$t7 #  $t1 = $t6 + $t7;   add as unsigned integerssubu    $t1,$t6,$t7 #  $t1 = $t6 + $t7;   subtract as unsigned integersmult   $t3,$t4     #  multiply 32-bit quantities in $t3 and $t4, and store 64-bit#  result in special registers Lo and Hi:  (Hi,Lo) = $t3 * $t4                         运算结果存储在hi,lo(hi高位数据, lo地位数据)div  $t5,$t6     #  Lo = $t5 / $t6   (integer quotient)#  Hi = $t5 mod $t6   (remainder)                         商数存放在 lo, 余数存放在 himfhi    $t0     #  move quantity in special register Hi to $t0:   $t0 = Hi                          不能直接获取 hi 或 lo中的值, 需要mfhi, mflo指令传值给寄存器mflo $t1     #  move quantity in special register Lo to $t1:   $t1 = Lo#  used to get at result of product or quotientmove  $t2,$t3 #  $t2 = $t3

    Control Structures

    控制流

    Branches

    分支(if else系列)

  • comparison for conditional branches is built into instruction
          b   target      #  unconditional branch to program label targetbeq  $t0,$t1,target  #  branch to target if  $t0 = $t1blt   $t0,$t1,target  #  branch to target if  $t0 < $t1ble $t0,$t1,target  #  branch to target if  $t0 <= $t1bgt   $t0,$t1,target  #  branch to target if  $t0 > $t1bge $t0,$t1,target  #  branch to target if  $t0 >= $t1bne   $t0,$t1,target  #  branch to target if  $t0 <> $t1
    

    Jumps

    跳转(while, for, goto系列)

            j   target       #  unconditional jump to program label target                           看到就跳, 不用考虑任何条件      jr  $t3     #  jump to address contained in $t3 ("jump register")                          类似相对寻址,跳到该寄存器给出的地址处

    Subroutine Calls

    子程序调用

    subroutine call: "jump and link" instruction

      jal sub_label   #  "jump and link"
  • copy program counter (return address) to register $ra (return address register)
  • 将当前的程序计数器保存到 $ra 中
  • jump to program statement at sub_label

    subroutine return: "jump register" instruction

        jr  $ra #  "jump register"
  • jump to return address in $ra (stored by jal instruction)
  • 通过上面保存在  $ra 中的计数器返回调用前

    Note: return address stored in register $ra; if subroutine will call other subroutines, or is recursive, return address should be copied from $ra onto stack to preserve it, since jal always places return address in this register and hence will overwrite previous value

    如果说调用的子程序中有调用了其他子程序,如此往复, 则返回地址的标记就用 栈(stack) 来存储, 毕竟 $ra 只有一个, (哥哥我分身乏术啊~~)。

    System Calls and I/O (SPIM Simulator)

    系统调用 与 输入/输出(主要针对SPIM模拟器)

    (本人使用的是Mars 4.4,也通用--!)

  • used to read or print values or strings from input/output window, and indicate program end
  • 通过系统调用实现终端的输入输出,以及声明程序结束
  • use syscall operating system routine call
  • 学会使用 syscall
  • first supply appropriate values in registers $v0 and $a0-$a1
  • 参数所使用的寄存器:$v0, $a0,  $a1
  • result value (if any) returned in register $v0
  • 返回值使用: $v0

    The following table lists the possible syscall services.

    下表给出了系统调用中对应功能,代码,参数机返回值

    Code
    in $v0

    对应功能的调用码

    Arguments

    所需参数

    Results

    返回值

    Service

    print_int

    打印一个整型

    $v0 = 1

    $a0 = integer to be printed

    将要打印的整型赋值给 $a0

     

    print_float

    打印一个浮点

    $v0 = 2

    $f12 = float to be printed

    将要打印的浮点赋值给 $f12

     

    print_double

    打印双精度

    $v0 = 3

    $f12 = double to be printed

    将要打印的双精度赋值给 $f12

     
    print_string
    $v0 = 4

    $a0 = address of string in memory

    将要打印的字符串的地址赋值给 $a0

     
    read_int
    $v0 = 5
     

    integer returned in $v0

    将读取的整型赋值给 $v0

    read_float

    读取浮点

    $v0 = 6
     

    float returned in $v0

    将读取的浮点赋值给 $v0

    read_double

    读取双精度

    $v0 = 7
     

    double returned in $v0

    将读取的双精度赋值给 $v0

    read_string

    读取字符串

    $v0 = 8

    $a0 = memory address of string input buffer

    将读取的字符串地址赋值给 $a0
    $a1 = length of string buffer (n)

    将读取的字符串长度赋值给 $a1

     

    sbrk

    应该同C中的sbrk()函数

    动态分配内存

    $v0 = 9

    $a0 = amount

    需要分配的空间大小(单位目测是字节 bytes)

    address in $v0

    将分配好的空间首地址给 $v0

    exit

    退出

    $v0 =10
     你懂得  
  • The print_string service expects the address to start a null-terminated character string. The directive .asciiz creates a null-terminated character string.
  • 大概意思是要打印的字符串应该有一个终止符,估计类似C中的'\0', 在这里我们只要声明字符串为 .asciiz 类型即可。下面给个我用Mars4.4的提示:
  • .ascii 与 .asciiz唯一区别就是 后者会在字符串最后自动加上一个终止符, 仅此而已
  • The read_int, read_float and read_double services read an entire line of input up to and including the newline character.
  • 对于读取整型, 浮点型,双精度的数据操作, 系统会读取一整行,(也就是说以换行符为标志 '\n')
  • The read_string service has the same semantices as the UNIX library routine fgets.
  • It reads up to n-1 characters into a buffer and terminates the string with a null character.
  • If fewer than n-1 characters are in the current line, it reads up to and including the newline and terminates the string with a null character.
  • 这个不多说了,反正就是输入过长就截取,过短就这样,最后都要加一个终止符。
  • The sbrk service returns the address to a block of memory containing n additional bytes. This would be used for dynamic memory allocation.
  • 上边的表里已经说得很清楚了。
  • The exit service stops a program from running.
  • 你懂得。。。
    e.g. Print out integer value contained in register $t2栗子:  打印一个存储在寄存器 $2 里的整型li $v0, 1 # load appropriate system call code into register $v0;                             声明需要调用的操作代码为 1 (print_int) 并赋值给 $v0# code for printing integer is 1move $a0, $t2 # move integer to be printed into $a0: $a0 = $t2                             将要打印的整型赋值给 $a0 syscall # call operating system to perform operatione.g. Read integer value, store in RAM location with label int_value (presumably declared in data section)栗子:  读取一个数,并且存储到内存中的 int_value 变量中li $v0, 5 # load appropriate system call code into register $v0; # code for reading integer is 5                             声明需要调用的操作代码为 5 (read_int) 并赋值给 $v0  syscall # call operating system to perform operation、                             经过读取操作后, $v0 的值已经变成了 输入的 5 sw $v0, int_value # value read from keyboard returned in register $v0; # store this in desired location                             通过写入(store_word)指令 将 $v0的值(5) 存入 内存中         e.g. Print out string (useful for prompts)栗子:  打印一个字符串(这是完整的,其实上面栗子都可以直接替换main: 部分,都能直接运行) .data string1 .asciiz "Print this.\n" # declaration for string variable, # .asciiz directive makes string null terminated .text main: li $v0, 4 # load appropriate system call code into register $v0; # code for printing string is 4                              打印字符串, 赋值对应的操作代码 $v0 = 4 la $a0, string1 # load address of string to be printed into $a0                             将要打印的字符串地址赋值  $a0 = address(string1) syscall # call operating system to perform print operation  e.g. To indicate end of program, use exit system call; thus last lines of program should be:执行到这里, 程序结束, 立马走人, 管他后边洪水滔天~~ li $v0, 10      # system call code for exit = 10 syscall # call operating sys-------------------------------------------------我是那个分呀分呀分割线--------------------------------------------------------------------------
    OK, 十分轻松又愉快的MIPS入门之旅到此告一段落, 下面我把用到的一些软件和这篇文章的原文链接贴到下边,有需要的, 各位客官自取哈~~~1.Mars4.42.PCSpim Simulator3.《MIPS Qucik Tutorial》

mips指令简单入门相关推荐

  1. 《Linux指令从入门到精通》——4.2 Linux下的简单文字模式文本编辑器

    本节书摘来自异步社区<Linux指令从入门到精通>一书中的第4章,第4.2节,作者:宋磊 , 宋馥莉 , 雷文利著,更多章节内容可以访问云栖社区"异步社区"公众号查看 ...

  2. 简单的MIPS指令编译程序

    在做计算机组成原理的设计的时候,需要将MIPS指令转化为十六进制数和二进制数,来进行仿真.于是使用了python设计了一个简单的编译程序,其中包含了MIPS指令集中的61条指令. 代码如下: # MI ...

  3. ARM NEON 编程简单入门1

    原文:http://blog.csdn.net/silentob/article/details/72954618  ARM NEON 编程简单入门1 NEON简介 NEON是适用于ARM Corte ...

  4. 基于vue-cli、elementUI的Vue超简单入门小例子

    基于vue-cli.elementUI的Vue超简单入门小例子 这个例子还是比较简单的,独立完成后,能大概知道vue是干嘛的,可以写个todoList的小例子. 开始写例子之前,先对环境的部署做点简单 ...

  5. DartWeb基础—简单入门

    DartWeb基础-简单入门 DartWeb的前面是Dart,所以需要先搭建好Dart开发环境,再进行下面的工作 下载Dartium浏览器 Dartium是Chromium的一个特殊的版本,里面包含D ...

  6. 【Computer Organization笔记10】单周期CPU设计:基于7条MIPS指令的数据通路

    本次笔记内容: P19 计算机组成原理(19) P20 计算机组成原理(20) 本节课对应幻灯片: 组成原理24 singlecycle.pptx 基于上节课的7条MIPS指令的数据通路,分别针对7条 ...

  7. Git快速入门篇—— Windows版本淘宝镜像快速下载安装详细步骤及简单入门教程(附带图文教程)

    Git快速入门篇-- Windows版本淘宝镜像快速下载安装详细步骤及简单入门教程(附带图文教程) 前言:我们平时在整理代码的时候,尤其是与别人一起开发项目的时候,常常涉及到代码的更新,因此代码版本问 ...

  8. [WinForm]Windows程序(非网页) #2 -- 跨平台的 ADO.NET程序(简单入门)

    这是我的文章备份,有空请到我的网站走走, http://www.dotblogs.com.tw/mis2000lab/ 才能掌握我提供的第一手信息,谢谢您. http://www.dotblogs.c ...

  9. AutoHotKey简单入门

    简单入门 快捷键 ^j::Send, Hello world! Return ^j::代表Ctrl+J,其中^代表Ctrl键 Send命令:在光标处输入Hello world! 也就是说,你按下Ctr ...

  10. 实验2:MIPS指令系统和MIPS体系结构

    实验2:MIPS指令系统和MIPS体系结构 一.实验目的 (1)了解和熟悉指令级模拟器 (2)熟悉掌握MIPSsim模拟器的操作和使用方法 (3)熟悉MIPS指令系统及其特点,加深对MIPS指令操作语 ...

最新文章

  1. Android App优化之延长电池续航时间
  2. 网络数据包分析软件Wireshark简介
  3. 【源资讯 第24期】有人总想搞大新闻:“Windows 11”爆猛料;微信放出“小程序码”...
  4. HighNewTech:18.11.07—第五届世界互联网大会—互联网届的奥斯卡大奖—15张PPT见证15项世界互联网领先科技成果
  5. SQL基础【十九、触发器】(不建议使用触发器的原因)
  6. node --- 使用node连接mysql
  7. TypeScript 中类型 any,void,unknown,never之间的区别
  8. Mac中安装NetBeans方法
  9. 华为向emui输入鸿蒙,新颜值/新功能/新体验!EMUI 11上手:手机鸿蒙OS的提前预演...
  10. 基于私有云的数据库高可用架构实践
  11. paip.提升性能------服务器环境及编程语言架构选择
  12. ibatis 分页(转)
  13. 流媒体RTMP协议解析
  14. java截取视频的帧
  15. Adobe Premiere Pro (PR) 视频剪辑相关应用
  16. 苹果退款_销售和退款政策 - Apple (中国大陆)
  17. 水溶性Ag2S量子点表面修饰PEG-SH,发射1100-1500之间可根据需求定制-齐岳生物
  18. Animation动画学习
  19. 技术干货丨《大天使之剑H5》主程与项目总监:H5游戏的压缩与优化经验
  20. git 将本地项目关联到远程仓库

热门文章

  1. b和kb的换算_KB换算
  2. linux 硬盘分区,分区,删除分区,格式化,挂载,卸载笔记
  3. oracle多次发运,EBS 发运管理操作实例11——延迟交货(Backorder)
  4. Unity——射线检测
  5. android 菜鸟面单打印_Android开发的菜鸟小记
  6. 云服务器重装系统步骤,腾讯云服务器如何更换操作系统?更换系统镜像重装系统方法...
  7. 什么是反馈电路?反馈有什么作用?
  8. onvif开发踩坑【二】鉴权失败
  9. 第一章 十天干,十二地支
  10. win10下微软office2010卸载