收藏 分享(赏)

MIPS 指令系统和汇编语言.pdf

上传人:精品资料 文档编号:9677331 上传时间:2019-08-23 格式:PDF 页数:29 大小:1.06MB
下载 相关 举报
MIPS 指令系统和汇编语言.pdf_第1页
第1页 / 共29页
MIPS 指令系统和汇编语言.pdf_第2页
第2页 / 共29页
MIPS 指令系统和汇编语言.pdf_第3页
第3页 / 共29页
MIPS 指令系统和汇编语言.pdf_第4页
第4页 / 共29页
MIPS 指令系统和汇编语言.pdf_第5页
第5页 / 共29页
点击查看更多>>
资源描述

1、 第四章 MIPS 指令系统和汇编语言 1. 考研预测:出题特点总结 本章 是对 统考 408 内容 来说, 本章是新增的章节。此外北航 961 大纲中制定了要考 MIPS指令集,从 15 年 961 真题来看 MIPS 是重中之重。但是今年计组并没有指定具体的教材,但大纲明确要求掌握 MIPS 指令集,所以还是建议考生将 计算机组成与设计:硬件 /软件接口 中文版(原版第三版或第四版)作为本章的参考书籍。 本章大致内容是 MIPS 的基础知识,难度并不大。考生应该将重点放 在 MIPS 指令集的基础上,考察 C 语言中的语句转换为对应的 MIPS 指令,所以需要熟练掌握 C 语言中一些语句对

2、应的 MIPS 指令实现。本章出题很大可能就是 C 语言和 MIPS 汇编语言之间的转换,也可能涉及到第五章 CPU 指令流水线等内容。 2. 考研知识点系统整理:梳理考点,各个击破 3.1 指令系统概述 机器指令要素 操作码 :指明进行的何种操作 源操作数地址 :参加操作的操作数的地址,可能有多个。 目的操作数地址 :保存操作结果的地址。 下条指令的地址 :指明下一条要运行的指令的位置,一般指令是按顺序依次执行的,所以绝大多数指令中并不显式的指明下一条指令的地址,也就是说,指令格式中并不包含这部分信息。只有少数指令需要显示指明下一条指令的地址。 指令执行周期 操作数区别 操作数的位置 :存储

3、器、 寄存器 和 输入输出端口 操作数的类型 : 数值 类型、 逻辑型数、字符 和 地址 操作数的存储方式 大端( big-endian )次序:最高有效字节存储在地址最小位置 小端( little-endian )次序:最低有效字节存储在地址最小 举例: int a = 0x12345678; 地址 数值 地址 数值 A + 0 12 A + 0 78 A + 1 34 A + 1 56 A + 2 56 A + 2 34 A + 3 78 A + 3 12 大端存储 小端存储 3.2 指令 格式 一台计算机指令格式的选择和确定要涉及多方面的因素,如指令长度、地址码结构以及操作码结构等,是一

4、个很复杂的问题,它与计算机系统结构、数据表示方法、指令功能设计等都密切相关。 指令的基本格式 一条指令就是机器语言的一个语句,它是一组有意义的二进制代码,指令的基本格式如下: 操作码字段 地址码字段 其中操作码指明了指令的操作性质及功能,地址码则给出了操作数的地址。 指令的长度是指一条指令中所包含的二进制代码的位数,指令长度与机器字长没有固定 的关系,它可以等于机器字长,也可以大于或小于机器字长。通常,把指令长度等于机器字长的指令称为单字长指令;指令长度等于半个机器字长的指令称为半字长指令;指令长度等于两个机器字长的指令称为双字长指令。 在一个指令系统中,若所有指令的长度都是相等的,称为定长指

5、令字结 构。定长结构指令系统控制简单,但不够灵活。若各种指令的长度随指令功能而异,就称为变长指令字结构。现代计算机广泛采用变长指令字结构,变长结构指令系统灵活,但指令的控制较复杂。 计算机执行一条指令所需要的全部信息都必须包含在指令中。对于一般的双操作数运算类指令来说,除去操作码之外,地址码字段中应包含以下信息: 第一操作数地址。 第二操作数地址。 操作结果存放地址。 这些信息可以在指令中明显的给出,称为显地址;也可以依照某种事先的约定,用隐含的方式给出,称为隐 地址。所以,从地址结构的角度可以分为三地址指令、二地址指令、一地址指令和零地址指令。 ( 1)三地址指令 三地址指令格式为: OP

6、A1 A2 A3 其中 A1 为第一操作数地址, A2 为第二操作数地址, A3 为操作结果存放地址。 这条指令的含义: (A1)OP(A2)A 3 式中 OP 表示双操作数运算指令的运算符号,如 “+”或 “”等。 ( 2)二地址指令 如果让第一操作数地址同时兼作存放结果的地址(目的地址),这样即得到了二地址指令,其格式为: OP A1 A2 其中 A1 为目的操作数地址, A2 为源操作数地址。 指令的含义: (A1)OP(A2)A 1。 ( 3)一地址指令 一地址指令顾名思义只有一个显地址,它的指令格式为: OP A1 一地址指令只有一个地址,那么另一个操作数来自何方呢?指令中虽未明显给

7、出,但按事先约定,这个隐含的操作数就放在一个专门的寄存器中。因为这个寄存器在连续性运算时,保存着多条指令连续操作的累计结果,故称为累加寄存器( AC)。 指令的含义: (AC)OP(A1)AC ( 4)零地址指令 零地址指令格式中只有操作码字段,没有地址码字段,其格式为: OP 零地址的运算类指令仅 用在堆栈计算机中的。堆栈计算机没有一般计算机中必备的通用寄存器,因此堆栈就成为提供操作数和保存运算结果的唯一场所。通常,参加运算的两个操作数隐含地从堆栈顶部(栈顶和次栈顶单元)弹出,送到运算器中进行运算,运算的结果再 隐含地压入堆栈中。对于同一个问题,用三地址指令编写的程序最短,但指令长度(程序存

8、储量)最长;而用二、一、零地址指令来编写程序,程序的长度一个比一个长,但指令的长度一个比一个短。 定长操作码指令格式 如果某个计算机全部指令的操作码字段的位数和位置都是固定的,就称为定长操作码指令。这是一种最简单的编 码方法,为了能表示整个指令系统中的全部指令,指令的操作码字段应当具有足够的位数。假定指令系统共有 m 条指令,指令中操作码字段的位数为 N 位,则有如下关系式: m2N, 所以 Nlog2m 定长操作码对于简化硬件设计,减少指令译码的时间是非常有利的,在字长较长的大、中型计算机及超级小型计算机上广泛采用。例如, IBM 370 机中不论指令的长度为多少位,其操作码字段一律都是 8

9、 位。 8 位操作码允许容纳 256 条指令,而实际上在 IBM 370 机中仅有 183条指令,存在着极大的信息冗余,这种信息冗余的编码也称为非法操作码。 扩展操作码指令格式 如果某个计算机全部指令的操作码字段的位数不固定,且分散地放在指令字的不同位置上,就称为变长操作码指令。这种方式能够有效地压缩指令中操作码字段的平均长度,在字长较短的小、微型计算机上广泛采用。显然,操作码字段的位数和位置不固定将增加指令译码和分析的难度,使控制器的设计复杂化。 最常见的变长操作码指令采用扩展操作码法。因为如果指令长度一定,则地址码与操作码字段的长度是相互制约的。为了解决这一矛盾,让操作数地址个数多的指令(

10、三地址指令)的操作码字段短些,操作数地址个数少的指令(一或零地址指令) 的操作码字段长些,这样既能充分地利用指令的各个字段,又能在不增加指令长度的情况下扩展操作码的位数,使它能表示更多的指令。 3.3 指令的寻址方式 所谓寻址,指的是寻找操作数的地址或下一条将要执行的指令地址。讨论寻址方式首先要搞清楚编址的概念。通常,指令中的地址码字段将指出操作数的来源和去向,而操作数则存放在相应的存储设备中。在计算机中需要编址的设备主要有 CPU 中的通用寄存器、主存储器和输入输出设备等 3 种。要对寄存器、主存储器和输入输出设备等进行访问,首先必须对它们进行编址。就像一个大楼有许多房间,首先必须给每一个房

11、间编上一个唯一的号码,人们才能据此找到需要的房间一样。 指令格式中每个地址码的位数是与主存容量和最小寻址单位(即编址单位)有关联的。主存容量越大,所需的地址码位数就越长。对于相同容量来说,如果以字节为最小寻址单位,地址码的位数就需要长些,但是可以方便地对每一个字符进行处理;如果以字为最小寻址单位(假定字长为 16 位或更长),地址码的位数可以减少,但对字符操作比较困难。例如:某机主存容量为 220 个字节,机器字长 32 位,若最小寻址单位为字节(按字节编址),其地址码 应为 20位;若最小寻址单位为字(按字编址),其地址码只需 18 位。 有效地址的概念 寻址方式是根据指令中给出的地址码字段

12、寻找有效地址的方式。我们把指令中地址码字段给出的地址称为形式地址(用字母 A 表示),这个地址有可能不能直接用来访问主存。例如,IBM PC/XT 机的主存容量可达 1MB,而指令中的地址码字段最长仅 16 位,仅能直接访问主存的一小部分,而无法访问到整个主存空间。就是在字长很长的大型机中,即使指令中能够拿出足够的位数来作为访问整个主存空间的地址,为了灵活方便地编制程序,也需要对地址进行必要的变换。 有效地址是指能够直接访问主存的地址(用字母 EA 表示),形式地址经过某种寻址方式的转换才能变为有效地址。 数据寻址和指令寻址 寻址可以分为指令寻址和数据寻址。寻找下一条将要执行的指令地址称为指令

13、寻址,寻找操作数的地址称为数据寻址。指令寻址比较简单,它又可以细分为顺序寻址和跳跃寻址。而数据寻址方式种类较多,其最终目的都是寻找所需要的操作数。 顺序寻址可通过程序计数器加 1,自动形成下一条指令的地址;跳跃寻址则需要通过程序转移类指令实现。 跳跃寻址的转移地址形成方式有 3 种:直接(绝对)、相对和间接寻址,它与数据寻址 方式中的直接、相对和间接寻址是相同的,只不过寻找到的不是操作数的有效地址而是转移的有效地址而已。 常见寻址方式 每台计算机的指令系统都有自己的一套寻址方式,不同计算机的寻址方式的名称和含义并不统一,下面介绍大多数计算机常用的几种基本寻址方式。 ( 1)立即寻址 立即寻址是

14、一种特殊的寻址方式,指令中在操作码字段后面的部分不是通常意义上的操作数地址,而是操作数本身,也就是说数据就包含在指令中,只要取出指令,也就取出了可以立即使用的操作数,这样的数称为立即数,其指令格式为: OP 立即数 这种方式的特点是:在取指令时,操作码和操作数被同时取出,不必再次访问主存,从而提高了指令的执行速度。但是,因为操作数是指令的一部分,不能被修改,而且立即数的大小受到指令长度的限制,所以这种寻址方式灵活性最差。 ( 2) 寄存器寻址 寄存器寻址指令的地址码部分给出某一个通用寄存器的编号 Ri,这个指定的寄存器中存放着操作数。其寻址过程如图所示,图中的 IR 表示指令寄存器,它的内容是

15、从主存中取出的指令。操作数 S 与寄存器 Ri 的关系为: S=(Ri)。 这种寻址方式具有两个明显的优点: 从寄存器中存取数据比从主存中快得多; 由于寄存器的数量较少,其地址码字段比主存单元地址字段短得多。 ( 3) 直接寻址 指令中地址码字段给出的地址 A就是操作数的有效地址,即形式地址等于有效地址: EA=A。由于这样给出的操作数地址是不能修改的,与程序本身所在的位置无关,所以又叫做绝对寻址方式。 下 图为直接寻址的示意图。操作数 S 与地址码 A 的关系为: S=(A)。 这种寻址方式不需作任何寻址运算,简单直观,也便于硬件实现,但地址空间受到指令中地址码字段位数的限制。 ( 4) 间

16、接寻址 间接寻址意味着指令中给出的地址 A 不是操作数的地址,而是存放操作数地址的主存单元的地址,简称操作数地址的地址。通常在指令格式中划出一位作为直接或间接寻址的标志位,间接寻址时标志位 =1。 间接寻址中又有一级间接寻址和多级间接寻址之分。在一级间接寻址中,首先按指令的地址码字段先从主存中取出操作数的有效地址,即 EA=(A),然后再按此有效地址从主存中读 出操作数,如 图 (a)所示。操作数 S 与地址码 A 的关系为: S=(A)。 多级间接寻址为取得操作数需要多次访问主存,即使在找到操作数有效地址后,还需再访问一次主存才可得到真正的操作数,如图 (b)所示。对于多级间接寻址来说,在寻

17、址过程中所访问到的每个主存单元的内容中都应设有一个间址标志位。通常将这个标志放在主存单元的最高位。当该位为“ 1”,表示这一主存单元中仍然是间接地址,需要继续间接寻址;当该位为“ 0”,表示已经找到了有效地址,根据这个地址可以读出真正的操作数。 间接寻址要比直接寻址灵活得多,它的主要优点如下: 扩大了寻址范围,可用指令中的短地址访问大的主存空间; 可将主存单元作为程序的地址指针,用以指示操作数在主存中的位置。当操作数的地址需要改变时,不必修改指令,只需修改存放有效地址的那个主存单 元的内容就可以了。 但是,间接寻址在取指之后至少需要两次访问主存才能取出操作数,降低了取操作数的速度。尤其是在多级

18、间接寻址时,寻找操作数要花费相当多的时间,甚至可能发生间址循环。 ( 5) 寄存器间接寻址 为了克服间接寻址中访存次数多的缺点,可采用寄存器间接寻址,即指令中的地址码给出某一通用寄存器的编号,在被指定的寄存器中存放操作数的有效地址,而操作数则存放在主存单元中,其寻址过程如图所示。操作数 S 与寄存器号 Ri 的关系为: S=(Ri)。 这种寻址方式的指令较短,并且在取指后 只需一次访存便可得到操作数,因此指令执行速度较间接寻址方式快。 ( 6) 变址寻址 变址寻址就是把变址寄存器 Rx 的内容与指令中给出的形式地址 A 相加,形成操作数有效地址,即 EA=(Rx)+A。 Rx 的内容称为变址值

19、,其寻址过程如图所示。操作数 S 与地址码和变址寄存器的关系为: S=(Rx)+A)。 变址寻址最典型的用法是将指令中的形式地址作为基准地址,而变址寄存器的内容作为修改量。在遇到需要频繁修改地址时,无须修改指令,只要修改变址值就可以了,这对于数组运算、字符串操作等成批数据处理是很有用的。 在具有变址寻址的指令中,除去操作码和形式地址外,还应具有变址寻址标志,当有多个变址寄存器时,还必须指明具体寻找哪一个变址寄存器。 ( 7) 相对寻址 相对寻址是将程序计数器( PC)的内容与位移量 D 相加,即 EA=(PC)+D。 PC 的内容是指令的地址,指令的地址码字段作为位移量 D,位移量可正、可负,

20、两者相加后得到操作数的有 效地址,位移量指出的是操作数和现行指令之间的相对位置。 这种寻址方式有如下两个特点:操作数的地址不是固定的,它随着 PC 值的变化而变化,并且与指令地址之间总是相差一个固定值。当指令地址变换时,由于其位移量不变,使得操作数与指令在可用的存储区内一起移动,所以仍能保证程序的正确执行。采用 PC 相对寻址方式编写的程序可在主存中任意 浮动,它放在主存的任何地方,所执行的效果都是一样的;其次 对于指令地址而言,操作数地址可能在指令地址之前或之后,因此,指令中给出的位移量可负、可正,通常用补码表示。如果位移量为 n 位,则相对寻址的寻址范围为: (PC) 2(n-1) (PC

21、)+2(n-1) 1。 ( 8) 页面寻址 页面寻址相当于将整个主存空间分成若干个大小相同的区,每个区称为一页,每页有若 干个主存单元。例如:一个 64KB 的存储器被划分为 256 个页面,每个页面中有 256 个字节,如图 (a)所示。每页都有自己的编号,称为页面地址;页面内的每个主存单元也有自己的编号,称为页内地址。这样,存储器的有效地址就被分为两部分:前部为页面地址(在此例中占 8 位),后部为页内地址(也占 8 位)。页内地址由指令的地址码部分自动直接提供,它与页面地址通过简单的拼装连接就可得到有效地址,无须进行计算,因此寻址迅速。根据页面地址的来源不同,页面寻 址又可以分成 3 种

22、不同的方式。 基页寻址,又称零页寻址。由于页面地址全等于 0,所以有效地址 EA=0 A(在这里表示简单拼接),操作数 S 在零页面中,如图 2-4-7(b)所示。基页寻址实际上就是直接寻址。 当前页寻址。页面地址就等于程序计数器 PC 的高位部分的内容,所以有效地址 EA=(PC)H A,操作数 S 与指令本身处于同一页面中,如图 (c)所示。 页寄存器寻址。页面地址取自页寄存器,与形式地址相拼接形成有效地址,如图 (d)所示。 ( 9) 堆栈寻址 堆栈是一种按特定顺序进行存取的存储区,这种特定顺序可归结为“后进先出( LIFO)”或“先进后出( FILO)”。堆栈区通常是主存储器中指定的一

23、个区域,在堆栈容量很小的情况下,也可以用一组寄存器来构成堆栈。 寄存器堆栈又称为硬堆栈。这种堆栈的栈顶是固定的,寄存器组中各寄存器是相互连接的,它们之间具有对应位自动推移的功能,即可将一个寄存器的内容推移到相邻的另一个寄存器中去。寄存器堆栈的成本比较高,不适于作大容量的堆栈,而从主存中划出一段区域来作堆栈是最合算且最常用的方法。这种堆栈又称为软堆栈,堆栈的大小可变,栈底 固定,栈顶浮动,故需要一个专门的硬件寄存器作为堆栈栈顶指针,简称栈指针( SP)。栈指针所指定的存储单元,就是堆栈的栈顶。 最常见的软堆栈是自底向上生成(向低地址方向生成)堆栈,这种堆栈的栈底地址大于栈顶地址,通常栈指针始终指

24、向栈顶的满单元。因此,进栈时,堆栈指针 SP 的内容需要先自动减 1,然后再将数据压入堆栈;出栈时,需要先将堆栈中的数据弹出,然后 SP 的内容再自动加 1。 3.4 MIPS 汇编语言 MIPS 汇编语言是本章的重点内容,也是必考内容。在 15 年 961 真题中 MIPS 汇编语言所占分数很大, MIPS 汇编 语言的考点有: MIPS 寄存器结构、 MIPS 指令格式、运算指令、分支指令、寻址指令、函数调用以及与 C 语言之间的转换等知识点。 总体来说 MIPS 汇编语言难度不大,但知识点比较杂,需要考生仔细复习。在 计算机组成与设计:硬件 /软件接口 教材 MIPS 章节中也有相应的习

25、题,考生可以多加练习。 MIPS 寄存器结构 目前最常用的 MIPS 是 32 位虚拟地址空间 : 32 个 32 位的 GPRs(通用寄存器) ,编号从 $zero($0), $1 $31 32 个 32 位的 FPRs(浮点数寄存器) PC, 32 位 HI, LO(乘除寄存器) ,都是 32 位 MIPS 指令格式 操作码 RS RT RD SHAMT 功能码 R 型 31 26 25 0 21 20 16 15 11 10 6 5 考生 只需要掌握这三种 MIPS 指令格式就行,其他的指令格式由于本书本没有涉及,故推想应该不会作为考察目标。 MIPS 算数运算指令 add rd, rs

26、, rt rd rs + rd ;其中 shamt=0。扩展:如果发生溢出,那么目的寄存器不会被修改,同时引发整数溢出异常 addi rt, rs, immediate rt rs + immediate ; 该指令会将 immediate 部分作为有符号数来看待。 如果发生溢出,目的寄存器不会修改,同时引发整数溢出异常 addiu rt, rs, immediate rt rs + immediate ;该指令会将 immediate 数据作为有符号来看待。 但是在任何情况下都不会产生异常。 addu rd, rs, rt rd rs + rd ;任何情况下都不会产生异常 sub rd, r

27、s, rt rd rs rd,其他同 add subu rd, rs, rt 类似于 addu,仅仅不同的是这里执行减法操作 sll rd, rt, sa 属于 R 型指令,其中 shamt=sa rd rt = b) goto L slt $t0, $s0, $s1 beq $t0, $zero, L if(a b) while statement loop: slt $t0, $s1, $s0 beq $t0, $zero, exit: while statement j loop exit: b) for 语句 for(a = b; a 设机器字长为 32 位,一个容量为 16MB 的存

28、储器, CPU 按半字寻址,其寻址单元数是( )。 A 224 B 223 C 222 D 221 解答 : B。 16MB = 224,由于字长为 32 位,现在按半字( 16 位)寻址,相当于有 8M 个 存储单元,每个存储单元中存放 16 位。 某机器字长 16 位,主存按字节编址,转移指令采用相对寻址,由两个字节组成,第一字节为操作码字段,第二字节为相对位移量字段。假定取指令时,每取一个字节 PC 自动加 1。若某转移指令所在主存地址为 2000H,相对位移量字段的内容为 06H,则该转移指令成功转移后的目标地址是( )。 A 2006H B 2007H C 2008H D 2009H

29、 解答 : C。主存按字节编址,取指令时,每取一个字节 PC 自动加 1。由于转移指令由两个字节组成,取出这条转移指令之后的 PC 值等于 2002H,所以转移指令成功转移后的目标地址 PC = 2000H + 2 + 06H = 2008H。 将下面 C 代码转换成对应的 MIPS 汇编指令。 解答 : 本题中没有给定参数存放的寄存器,此时就需要根据 寄存器使用约定 ! g 存放在 a0 中, h 存放在 a1 中, i 存放在 a2 上, j 存放在 a3 上。 对应的 MIPS 汇编代码如下: leaf_example: addi $sp, $sp, -4 add $t0, $a0, $

30、a1 add $t1, $a2, $a3 sub $t2, $t0, $t1 sw $t2, 0($sp) addi $v0, $t2, $zero addi $sp, $sp, 4 jr $ra 经过优化之后: leaf_example: add $t0, $a0, $a1 add $t1, $a2, $a3 sub $v0, $t0, $t1 jr $ra 假设这样: leaf_example: addi $sp, $sp, -12 sw $s0, 8($sp) sw $s1, 4($sp) sw $s2, 0($sp) add $s0, $a0, $a1 add $s1, $a2, $a

31、3 sub $s2, $s0, $s1 sw $s2, 0($sp) addi $v0, $s2, $zero lw $s0, 8($sp) lw $s1, 4($sp) lw $s2, 0($sp) addi $sp, $sp, 12 jr $ra 将下面一段递归程序翻译成 MIPS 汇编代码。 解答 :根据寄存器使用规则, n 存放在 a0 寄存器中。 两种方式实现: 1. 调用者负责恢复堆栈 fact: slti $t0, $a0, 1 beq $t0, $zero, Label1 addi $v0, $zero, 1 jr $ra Label1: addi $sp, $sp, -8 s

32、w $ra, 4($sp) sw $a0, 0($sp) addi $a0, $a0, -1 jal fact lw $a0, 0($sp) lw $ra, 4($sp) addi $sp, $sp, 8 mul $v0, $a0, $v0 jr $ra 2. 被调用者负责恢复堆栈 fact: slti $t0, $a0, 1 beq $t0, $zero, Label1 addi $v0, $zero, 1 lw $a0, 0($sp) lw $ra, 4($sp) addi $sp, $sp, 8 jr $ra Label1: addi $sp, $sp, -8 sw $ra, 4($sp

33、) sw $a0, 0($sp) addi $a0, $a0, -1 jal fact mul $v0, $a0, $v0 lw $a0, 0($sp) lw $ra, 4($sp) addi $sp, $sp, 8 jr $ra 稍加修改: fact: slti $t0, $a0, 1 beq $t0, $zero, Label1 addi $v0, $zero, 1 j exit Label1: addi $sp, $sp, -8 sw $ra, 4($sp) sw $a0, 0($sp) addi $a0, $a0, -1 jal fact mul $v0, $a0, $v0 exit:

34、 lw $a0, 0($sp) lw $ra, 4($sp) addi $sp, $sp, 8 jr $ra 用 MIPS 汇编实现 strcpy 函数,已知 strcpy 函数实现如下: void strcpy(char x, char y) int i = 0; while(xi = yi) != 0) i +; 解答 : 根据规则, x 保存在 a0, y 保存在 a1 中,代码如下: strcpy: addi $t0, $zero, 0 addi $t4, $zero, 0 loop: add $t1, $t0, $a0 add $t2, $t0, $a1 lb $t3, 0($t2)

35、 sb $t3, 0($t3) addi $t0, $t0, 1 bne $t3, $t4, loop addi $sp, $sp, 8 jr $ra 一些电脑有显示的指令从 32 位寄存器中取出任意字段并放到寄存器中的最低有效位中,下图显示了需要的操作: 找出最短的 MIPS 指令序列 能够完成上述操作,给定实现该功能的函数原型如下: int pickuppart(int value, int i, int j); 其中返回值就是所要得到的部分。 解答 : 注意参数保存的位置。 pickuppart: addi $t0, $zero, 31 sub $t1, $t0, $a2 sllv $a

36、0, $a0, $t1 addi $a1, $a1, 1 srlv $v0, $a0, $a1 addi $sp, $sp, 12 jr $ra 用 MIPS 汇编实现 memcpy 函数,该函数原型如下: void* memcpy(void* dest, void* source, size_t nBytes); 大致功能:将从 source 指向的一段内存区域拷贝 nBytes 所 指定 长度的数据到 dest 所指向的一段内存中。 解答 : 最简单的方式,实现跟 strcpy 类似。 memcpy: add $v0, $zero, $a0 addi $t1, $zero, 0 loop

37、beq $t1, $a2, exit lb $t2, 0($a1) sb $t2, 0($a0) addi $t1, $t1, 1 addi $a0, $a0, 1 addi $a1, $a1, 1 j loop exit: jr $ra 对于上题有没有更快的方法? 解答 : 一般系统会这么去实现 。 memcpy: srl $t0, $a2, 2 add $v0, $zero, $a0 addi $t1, $zero, 0 loop: beq $t1, $t0, next lw $t3, 0($a1) sw $t3, 0($a0) addi $t1, $t1, 1 addi $a1, $a1

38、, 4 addi $a0, $a0, 4 j loop next: sll $t1, $t1, 2 loop1 beq $t1, $a2, exit lb $t2, 0($a1) sb $t2, 0($a0) addi $t1, $t1, 1 addi $a0, $a0, 1 addi $a1, $a1, 1 j loop1 exit: jr $ra 按照寄存器 $s0 等于 Ss1 给出下面一个分支, beq $s0, $s1, L1;不过这个指令有些缺陷,请通过一对提供大的多的分支转移距离的指令来取代它。 解答 : beq 指令限制了跳转的长度。 L1 只能是 16 位,导致 跳转的长度是

39、 0, 64K * 4,也就是向上向下跳转的最大距离是 128K。在大型的软件中可能会超过这个距离 。 可通过下面指令解决: bne $s0, $s1, L2 j L1 L2: 这样只要保证 L1 和 j L1 这条指令处于 同 一个 256M 的空间即可。 如果这样还不能够满足,亦可以通过 jr 指令来实现跳转。跳转空间是整个执行空间。 一般要借助 lui 和 addi 指令来完成 跳转 地址的加载。 用 MIPS 指令实现下面的 MIPS 伪指令,其中 big 的对应一个指定需要 32 位来表示的数字, small 对应一个 16 位数。 伪指令 完成功能 Move $t1, $t2 $t

40、1= $t2 Clear $t0 $t0 = 0 Beq $t1, small, L If($t1 = small) goto L Beq $t2, big, L If($t2=big) goto L Li $t1, small $t1 = small Li $t2, big $t2 = big Ble $t3, $t5, L If($t3 $t5) goto L Bge $t5, $t3, L If($t5 = $t3) goto L Addi $t0, $t2, big $t0 = $t2 + big Lw $t5, big($t2) $t5 = Memory$t2+big 解答 : 伪指

41、令是为了方便程序员编程,编译器提供的,一旦程序员在编写程序的过程中使用了伪指令,由编译器负责将这些伪指令映射为实实在在能够在 机器上执行的机器指令。 1. move $t1, $t2 功能:实现了 $t1 $t2 映射: addi $t1, $t2, 0 或者 add $t1, $t2, $zero 2. clear $t0 功能: $t0 0 映射: addi $t0, $zero, 0 或者 add $t0, $zero, $zero 3. beq $t1, small, L 功能: If($t1 = small) goto L 映射: addi $t2, $zero, small beq

42、 $t1, $t2, L 或者 li $at, small beq $t1, $at, L 4. beq $t2, big, L 功能: If($t1 = big) goto L 映射: lui $at, upper(big) addi $at, $at, lower(big) beq $t2, $at, L 或者 li $at, big beq $t2, $at, L 5. li $t1, small 功能: $t1 = small 映射: addi $t1, $zero, small 6. li $t2, big 功能: $t2 = big 映射: lui $t2, upper(big)

43、ori $t2, $t2, lower(big) 7. ble $t3, $t5, L 功能: if($t3 $5) goto L 映射: slt $at, $5, $4 bne $at, $zero, L 9. bge $t5, $t3, L 功能: slt $at, $5, $3 beq $at, $zero, L 10. addi $t0, $t2, big 功能: $t0 = $t2 + big 映射: li $at, big add $0, $t2, $at 11. lw $t5, big($t2) 功能: $5 = Memory$t2 + big 映射: li $at, big a

44、dd $at, $at, $t2 lw $t5, 0($at) 就你对 PC 相对寻址的理解,解释为何汇编器在下面代码序列中直接实现分支指令时可能会有问题。 here: beq $s0, $s2, there there: add $s0, $s0, $s0 说明汇编器可能如何重写该代码序列来解决这个问题。 解答 : 弄清楚 beq 指令转移的长度。修改可参看前面的例题 7. C(或 Java)程序段 while(savei = k) i += 1; MIPS 转换在每次循环时使用了一个条件分支和无条件跳转。只有优化功能弱的编译器生成的代码才会导致这样的循环开销。假设该代码采用的是 Java(

45、不是 C),重写汇编 代码 使其每次循环时最多使用一个分支或跳转。另外,加上执行 Java 下标越界检查的代码并保证每次循环最多使用一个分支或跳转。如果循环的迭代次数为 10,且 i 始终不越界的话,那优化前后运行的指令条数各是多少? 解答 :由于需要考虑对数组下标的检查,故重写上面的循环是: while(i = 0 为了下面表示方便,不妨假设数组基地址存放到 $6 中,变量 i 存放在 $s3 中, array_size存放在 $2 中, k 存放在 $5 中。 那么优化性能较差的编译器会生成如下代码: loop: stl $t0, $s3,$zero bne $t0, $zero, ind

46、exOutOfBounds slt $t0, $s3, $s2 beq $t0, $zero, indexOutOfBounds sll $t1, $s3, 2 add $t1, $t1, $s6 lw $t0, 0($s6) bne $t0, $s5, exit addi $s3, $s3, 1 j loop exit: 执行代码条数: 10 * 10 + 8 = 108 优化之后代码 : slt $t0, $s3, $zero slt $t1, $s3, $s2 slti $t1, $t1, 1 or $t1, $t1, $t0 bne $t1, $zero, indexOutOfBounds sll $t1, $t3, 2 add $t1, $t1, $s6 lw $t0, 0($t1) bne $t0, $s5, exit loop: addi $s3, $s3, 1 slt $t0, $s3, $zero slt $t2, $s3, $s2 slti $t2, $t2, 1 or $t2, $t2, $t0 bne $t2, $zero, indexOutOfBounds addi $t1, $t1, 4 lw $t0, 0($t1) beq $t0, $s5, loop exit: 执行代码条数: 9 + 9 * 9 + 9 = 99

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报