好文档就是一把金锄头!
欢迎来到金锄头文库![会员中心]
电子文档交易市场
安卓APP | ios版本
电子文档交易市场
安卓APP | ios版本

MIPS系统指令系统超详细.pdf

98页
  • 卖家[上传人]:汽***
  • 文档编号:575924913
  • 上传时间:2024-08-19
  • 文档格式:PDF
  • 文档大小:1.33MB
  • / 98 举报 版权申诉
  • 文本预览
  • 下载提示
  • 常见问题
    • 3.1 概述3.2 计算机硬件的操作3.3 计算机硬件的操作数3.4 指令的计算机内部表示3.5 决策指令3.6 计算机硬件对过程的支持3.7 计算机对字符的处理(略去)3.8 MIPS的其他寻址方式第三章指令系统 3.1 概述概述要给计算机硬件直接下命令,就必须使用机器的语言机器语言中的“单词”称为指令指令,其“词汇表”称为指令集指令集本章将介绍现实中计算机所使用的指令集系统通过学习机器指令,你会了解到计算机中的一个重要概念:存储程序(存储程序(storedstored- -rogramrogram))着重介绍的是MIPS指令集 ,涉及到MIPS指令的操作数、指令格式及指令类别 1、、CISC---复杂指令系统计算机复杂指令系统计算机Complex Instruction Set Computer,20世纪60年代后期,随着IC、LSI、VLSI的出现和发展,计算机硬件成本不断下降,人们热衷于在指令系统真增加更多的指令和复杂的指令,来提高操作系统的效率,促使指令系统越来越复杂,这一时期的计算机称为CISC。

      2、、RISC---精简指令系统计算机精简指令系统计算机Reduced Instruction Set Computer ,1975年IBM公司开始研究指令系统的合理性问题,IBM的John Cocke提出精简指令的想法,本书作者David A. Patterson创造了RISC一词,并定义了其含义,后来John L. Hennessy带领他在斯坦福的研究小组研制成功MIPS机,精简指令系统计算机从此诞生并发展起来一、指令系统的发展 二、二、RISC的特点的特点1、优先选取一些使用频率最高的简单指令,以及一些很有用但不复杂的指令,避免复杂指令2、指令长度固定,指令格式种类少,寻址方式种类少,指令各字段的划分比较一致,各字段功能较规整3、只有存数、取数指令访问存储器,其余指令的操作都在寄存器之间进行4、CPU中通用寄存器数量较多三、三、MIPS简介简介1、处理器的缩写、处理器的缩写① Million Instruction Per Second,泛指每秒能执行百万条指令的处理器② Microprocessor without Interlocking Pipeline Stage,一种无内锁的流水线微处理器2、、MIPS公司公司 3.2 计算机硬件的操作指令计算机硬件的操作指令一、指令的基本格式一、指令的基本格式指令格式,是指令用二进制代码表示的结构形式,通常有操作码字段和地址码字段组成。

      操作码表示指令的操作特性和功能,而地址码通常指定参与操作的操作数的地址,故指令基本格式如下:OPA1、操作码、操作码操作码字段的位数取决于指令系统的规模,例如,只有8条指令的指令系统,OP字段有3位就够了,如果系统包含32条指令,则OP字段需要5位操作码一般来说一个包含n位的操作码能够表示2n条指令 2、地址码、地址码根据一条指令中有几个操作数地址,可将该指令称为几地址指令,一般有三地址指令、二地址指令、一地址指令和零地址指令格式:OPAOPA2A1OPA2A1A3OP 1、加法指令add rd, rs, rt #add rd, rs, rt #注释注释①每条指令只执行一个操作,并且有且只有三个变量②书写时,每一行只有一条指令,注释放在行尾,由#号引出③该指令执行rd=rs+rt的操作例如:add a, b, c # b + c的和存放在a中其中 add称操作符, 表示加运算;紧跟add的a是目的操作数, 即为结果,其余b、c表示源操作数每条指令中由 “#”号领头的部分是注释三、三、MIPS算术运算指令算术运算指令 例如:计算 a=b+c+d+e;add a,b,c # b + c的和存放在a中add a,a,d # b + c + d的和已存放在a中add a,a,e # b + c + d + e的和已存放在a中2、减法指令sub rd, rs, rt #注释例例3.1把两个把两个C语言赋值语句编译成语言赋值语句编译成MIPS汇编指令汇编指令下面这段C语言代码包含5个变量a, b, c, d, e:a = b + c;d = a – e; 【【解答解答】】add a, b, c # a=b+csub d, a, e # d = a – e例例3 3. .2 2把一个复杂的把一个复杂的C C语言赋值语句编译成语言赋值语句编译成MIPSMIPS汇汇编指令编指令f f = = (g(g + + h)h) – (i(i + + j)j); ; 【【解答解答】】addaddt t0 0, , g,g, h h# 临时变量t0=g + h的和addaddt t1 1, , i,i, j j# 临时变量t1=i + j的和最后做减法,把差放在f中:subsubf,f, t t0 0, , t t1 1# f=t0 - t1的值完成一个类似于加法的操作需要3个操作数:2个数参与运算,1个数存放结果。

      每条指令刚好包含3个操作数,不多也不少,这是遵循简化硬件的原则,因为操作数的个数不定的硬件实现比个数固定的硬件实现复杂得多这就是硬件设计要考虑的第一条原则:设计原则设计原则1:简单性来自规则性简单性来自规则性Simplicity favors regularity. )) 3.3计算机硬件的操作数计算机硬件的操作数cpu的的寄存器(寄存器(register)) 中中---寄存器操作数寄存器操作数寄存器是建造计算机的基石,因为它们是硬件设计中用到的基本单元,对于程序员也是可见的,但其数量有限计算机硬件的操作数放在什么地方?存储器中存储器中---存储器操作数存储器操作数复杂数据结构,如数组、结构体等包含大量数据元素,不可能映射到数量有限的寄存器上,只能存储到存储器中指令中指令中---立即数立即数有些操作数直接与指令存放在一起,称为立即数,而MIPS中专门设置有一些立即数指令,如addi,slti等 一、一、MIPS的寄存器的寄存器在MIPS体系结构中,一个寄存器的长度是32位;又称32位为字长MIPS体系中的数据字、指令字都是32位MIPS寄存器汇编符号记为$s0、$s1、 $s2、$s3 …$s7,对应编码为:16、17、… 23; 以及$t0、$t1、 $t2、$t3 …$t7,对应编码为:8、9、… 15。

      寄存器和编程语言的变量的一个主要区别是,寄存器数量有限,现在的计算机中一般是32个MIPS也只有32个寄存器为什么限于32个寄存器?原因可以从硬件设计的第二条原则找到:设计原则设计原则2 2::越小越快越小越快Smaller is faster. ))寄存器的数量如果很大,则电信号需要传输的距离更长,因而时钟周期也会变得很长 例例3.3 3.3 使用寄存器编译使用寄存器编译C C语言赋值语句语言赋值语句以上例C语言赋值语句为例:f = (g + h) – (i + j);为变量f, g, h, i, j分别指定寄存器$s0, $s1, $s2,$s3, $s4 而临时变量指定寄存器$t0,$t1,则MIPS 汇编符号指令:addadd$ $t t0 0, , $ $s s1 1, , $ $s s2 2# 寄存器$t0中包含g + h的和addadd$ $t t1 1, , $ $s s3 3, , $ $s s4 4# 寄存器$t1中包含i + j的和subsub$ $s s0 0, , $ $t t0 0, , $ $t t1 1# $t0 - $t1的差放入f中硬件硬件/软件接口软件接口 编译器不仅把变量同寄存器联系起来,还为数组和结构这样的数据结构分配内存空间。

      这样,编译器就能把恰当的基地址放入数据传送指令中 二、操作数在内存单元中二、操作数在内存单元中计算机如何表示和存取数组这样的复杂数据结构呢?处理器只能在寄存器中保存很少的数据,而内存则可以存放数以百万计的数据单元因此,数组这样的数据结构存放在数组这样的数据结构存放在内存中内存中内存单元用地址编号表示内存单元用地址编号表示, ,叫内存地址叫内存地址 ,例例: 实际MIPS内存地址:一个字=4字节表示,按字节编址:字节寻址还影响数组的索引要得到正确的地址,加到基址上的偏移量应该乘以4 三、数据传送指令三、数据传送指令 : LW与与 SW1 1、取字指令(、取字指令(Load Word))LW指令格式: Lw rt, offset(rs)Lw rt, offset(rs)#注释① offset为偏移量,是数组首地址到数组中某元素存储位置的字节偏移量,是一个常数② rs是存储数组首地址的寄存器,称为基址寄存器③ rt为目的操作数寄存器,存放取自【(rs)+offset】的数据注意:offset(rt)表示存放数据的内存单元地址,即内存地址即内存地址例例3.4 3.4 编译有一个操作数在内存中的编译有一个操作数在内存中的C C语言赋值语句语言赋值语句: :g = h + A[8];g = h + A[8]; 设数组A[100] 【【解答解答】】操作数A[8]在内存中,首先得把它转移到寄存器中。

      它的地址是数组A的基地址加上8*4的和 假设$s3存放数组A的基地址,g对应$s1寄存器,h对应$s2寄存器lwlw$ $t t0 0, , 3232( ($ $s s3 3) )# 临时寄存器$t0存放A[8]的值addadd$ $s s1 1, , $ $s s2 2, , $ $t t0 0# g = h + A[8]数据传送指令中的常量称为偏移量偏移量((offsetoffset)),用来计算地址的寄存器称为基地址寄存器基地址寄存器((basebase registerregister))内存有效地址内存有效地址EA=offset(EA=offset(偏移量偏移量)+ + rs(基地址寄存器基地址寄存器) 2 2、存字指令(、存字指令(Store Word))SWSW例例3.53.5使用取指令和存储指令进行编译使用取指令和存储指令进行编译 :C语句: A[12] = h + A[8];指令格式: sw rt, offset(rs) #注释指令功能:将rt寄存器中的数据存入【(rs)+offset】内存单元注意事项:同lw指令 【【解答解答】】首先应该使用lw指令将A[8]取到寄存器中,再做加法运算,最后利用sw指令将和存入A[12]。

      假设变量h在$s2寄存器中,数组A的基址在$s3中,则该C语句的MIPS汇编指令代码如下:lw w$ $t t0 0, , 3232( ($ $s s3 3) )# 临时寄存器$t0存放A[8]的值addadd$ $t t0 0, , $ $s s2 2, , $ $t t0 0# 临时寄存器$t0存放h+A[8]的值swsw$ $t t0 0, , 4848( ($ $s s3 3) )# 把h+A[8]的值存储到A[12]中 例例3.6 使用可变数组下标进行编译使用可变数组下标进行编译假设A是100个元素的数组,基地址在寄存器$s3中,变量g, h, i分别和寄存器$s1,$s2,$s4相联系写出下面的C语句的MIPS汇编代码:g g = = h h + + A[i]A[i]【【解答解答】】为了能从A[i]中取出数据,首先要得到A[i]的内存地址,且必须以offset(rs)的形式体现通过计算A+4*i可得A[i]的内存地址,将其放入基址寄存器,这样只要令偏移量offset为0,即可以offset(rs)的形式实现取数指令: add $t1, $s4, $s4# 临时寄存器$t1 = 2 * iadd $t1, $t1, $t1# 临时寄存器$t1 = 4 * iadd $t1, $t1, $s3# 临时寄存器$t1 = A[i]的地址(4*i+$s3)然后把A[i]取到临时寄存器中:lw $t0, 0($t1)# 临时寄存器$t0 = A[i]最后把A[i]和h加起来,放到变量g中:add $s1, $s2, $t0# g = h + A[i] 四、软硬件接口:溢出(四、软硬件接口:溢出(spilling)寄存器)寄存器很多程序中变量的数量比寄存器的数量多。

      因此,编译器尽量把使用最频繁的变量保持在寄存器中,而把其余的放在内存中,并用取数和存储指令在寄存器和内存之间传送数据将不常用或是以后才用到的变量存入内存的过程称为溢出溢出((spilling))寄存器寄存器五、小结五、小结P83 图3—4,指令与操作数小结 3.4 指令的计算机内部表示指令的计算机内部表示在计算机内部,指令体现为二进制数,由连续的0,1串组成,计算机为了识别指令,会将这个32位的二进制数分成几个字段,用来表示不同的信息,如表示操作码、寄存器号等机器指令格式以二进制表示:000000100011001001000000001000006位5位5位5位5位6位计算机如何识别和解释指令呢?首先要了解机器指令的表示MIPS汇编指令如下所示: add $t0, $s1, $s2二进制表示为:00000010001100100100000000100000 一、一、 R型指令格式型指令格式这些字段的意义是:opop:指令的操作码,传统上称为opcodeopcode,此处为0rsrs:表示第1个源操作数的寄存器rtrt:表示第2个源操作数的寄存器rdrd:表示目的操作数的寄存器,用来保存操作的结果。

      shamtshamt:移位位数,移位指令用作移位次数控制functfunct:功能域,用来选择opop域的一个特定的操作有时称为函数码((functionfunction codecode))R R型(型(R R- -type or Rtype or R- -formatformat)指令)指令,其中其中R R代表寄存器代表寄存器(Register(Register),),意为意为操作数都在寄存器中操作数都在寄存器中oprsrtrdshamtshamtfunctfunct6位5位5位5位5位6位31…….26 25……….21 20………..16 15……..11 10………6 5………….0 以上的R型指令非常适合运算类的指令,但当用于存、取数指令时,如果偏移地址使用5位字段,则偏移的范围就表达的太小了,并不适用因此,一方面要使所有指令长度都相同,另一方面又要让每条指令的格式都合适,产生了矛盾,因而提出了硬件设计的第三个原则:好的设计需要合适的折衷好的设计需要合适的折衷Good design demands good compromises. 由此进行折衷,设计出适合数据传送类指令的I型指令格式。

      例题:写出指令例题:写出指令add $t0, $s1, $s2 的机器代码的机器代码0171880 03232 二、二、I I型指令格式型指令格式 (Immadiate(Immadiate----Type)Type)各字段含义如下:op字段:操作码字段,35表示取数指令lw,43表示存数指令swrs字段:基址字段,存放基址寄存器号rt 字段:取指令的目的操作数寄存器号或存指令的源寄存器号offset字段:偏移量字段,指定相对于基址rs的字节偏移量16位的偏移量意味着存、取数指令可以装入的字的地址范围是,以位的偏移量意味着存、取数指令可以装入的字的地址范围是,以rs中的基地址为中心,中的基地址为中心,±±215(即(即32,768)个字节的范围,也即)个字节的范围,也即±±213(即(即8192)个字的范围个字的范围oprsrtoffset6位5位5位16位31…….26 25……….21 20……….16 15…………………………………….0 分析下列取数指令的机器代码:lw$t0, 32($s3)# 临时寄存器$t0存放A[8]的值Op=4319832注意:在取指令lw中,rt字段指定的是目的操作数寄存器。

      这里,$s3(寄存器号19)放在rs域中,$t0(寄存器号8)放在rt域中,偏移量32放在offset域中 该指令用十进制数表示的格式为: MIPS指令的编码注意:n.a.即not applicable,表示在这条指令中无此字段 例例3.7 将将MIPS汇编语言翻译成机器语言汇编语言翻译成机器语言写出写出C语句:语句:A[A[300300] ] = = h h + + A[A[300300] ]的机器语言代码的机器语言代码解答解答】】假设数组A的基地址在$t1中,变量h对应于寄存器$s2,则C赋值语句编译后的MIPS汇编代码如下:lw $t0, 1200($t1)# 临时寄存器$t0存放A[300]的值add $t0, $s2, $t0# 临时寄存器$t0存放h+A[300]的值sw $t0, 1200($t1)# 将h+A[300]的值存回A[300]中然后再写出这3条指令的MIPS机器语言代码为了方便起见,先用十进制数来表示机器指令根据前页表3.1,可得出下面的机器指令: A[300]=h+A[300];lw $t0, 1200($t1)add $t0, $s2, $t0sw $t0, 1200($t1) 四、存储程序(四、存储程序(storedstored- -programprogram))的概念。

      计算机的两个重要原理:1.指令是以数的形式表示的指令是以数的形式表示的2.程序可以存放在内存中程序可以存放在内存中,,像数字一样被读写像数字一样被读写三、小结:三、小结: P87 图图3—6 3.5 决策指令决策指令计算机区别于简单的计算器之处就在于它的决策能力基于输入数据和计算中产生的值的各种情况,执行的指令也可能不同在高级语言中一般用if语句代替决策,有时用带go to的if语句实现决策,MIPS中有类似功能的两种决策指令:一、分支指令(条件跳转指令)一、分支指令(条件跳转指令)1、beq指令指令格式:beq register1,register2,Label #注释指令功能:若register1=register2 则跳转到标号为Label的语句 例3.8 将if语句编译成条件分支语句if (i==j) go to L1;f=g+h;L1: f=f-i;【解答】首先为变量f、g、h、i、j分配寄存器$s0---$s4第一条语句比较i、j是否相等,然后根据结果决定是否跳转到L1语句,这恰好可以编译成一条beq语句:beq $s3,$s4,L1 #如果i等于j则跳转到L1add $s0, $s1, $s2 #f = g + h (如果i等于j则该 指令被跳过)L1: sub $s0, $s0, $s3 #f = f - i (该指令总是要执行) 2、bne指令指令格式:bne register1,register2,Label #注释指令功能:若register1≠register2 则跳转到标号为Label的语句例3.9 将if-then-else语句编译成条件转移指令if (i==j) f=g+h;else f=g-h;【解答解答】bne $s3, $s4, Else#如果i ≠ j则跳转到Elseadd $s0, $s1, $s2#f = g + h(如果i ≠ j则该指令被跳过)j Exit#跳转到ExitElse: sub $s0, $s1, $s2#f = g - h (如果i = j 则跳过该指令)Exit: 3、beq与bne指令的机器指令格式由于beq与bne指令中包含了跳转位置与当前指令的字偏移量,故采用I型指令格式更为合适:4/5rsrtLabel6位5位5位16位31…….26 25……….21 20……….16 15…………………………………….0其中,beq指令的op值为4,bne指令的op值为5,rs、rt两寄存器指定进行比较的两个数据,Label表示当前指令的下一条指令地址与跳转目标地址之间的字偏移量字偏移量,可正可负。

      需要注意的是,本来程序顺序执行,遇到beq/bne指令后,一旦发生跳转,则PC寄存器的内容会被修改,由原来的PC+4修改为PC+4+Label*4,即:需要将标号左移2位 二、无条件跳转指令二、无条件跳转指令指令格式:j Label #注释指令功能: 无条件跳转到标号为Label的语句机器格式:2Label6位26位31…….26 25………..……………………..…………………………………….0其中,Label表示跳转目标地址的26位字地址,但内存地址均为32位,故此26为字地址需要左移2位后形成28位字节地址,所以用当前PC寄存器的高4位与这个28位字节地址拼接形成一个32位内存地址,写入PC,以实现跳转 三、循环结构的实现三、循环结构的实现决策指令在if语句和循环结构的实现中都起着重要的作用,在分支结构中用于二者选一;在循环结构中用于重复执行在这两种情况下,关于决策的汇编指令是相同的,即高级语言中的if语句和while语句都是由决策指令beq和bne来实现的例3.10 编译一个带有可变数组下标的循环Loop: g=g+A[i];i=i+j;if(i!=h) go to Loop写出该循环的MIPS汇编代码 【解答解答】假设A是100个元素的数组,数组A的基地址在$s5中,变量g, h, i, j分别对应于寄存器$s1, $s2, $s3, $s4。

      首先将A[i]取出放入临时寄存器$t0Loop: add $t1, $s3, $s3 # 临时寄存器$t1 = 2 * iadd $t1, $t1, $t1 # 临时寄存器$t1 = 4 * iadd $t1, $t1, $s5 # $t1 = address of A[i]lw $t0, 0($t1) # 临时寄存器$t0 = A[i] 下面两条指令把A[i]加到g中,j加到i中:add $s1, $s1, $t0 # g = g + A[i]add $s3, $s3, $s4 # i = i + jbne $s3, $s2, Loop # 如果i ≠ h则跳转到Loop 例例3.11 3.11 编译编译whilewhile循环循环while ( save[i] = = k )i = i + j;写出这段C程序的MIPS汇编代码解答解答】假设i, j, k分别对应于寄存器$s3, $s4, $s5,数组save的基地址在$s6中写出该循环的MIPS汇编代码程序员一般不使用go to语句实现循环,传统的循环结构是用while语句来实现的,可通过编译器来翻译。

      Loop: add $t1, $s3, $s3 # 临时寄存器$t1 = 2 * iadd $t1, $t1, $t1 # 临时寄存器$t1 = 4 * iadd $t1, $t1, $s6 # $t1 = address of save[i]lw $t0, 0($t1) # 临时寄存器$t0 = save[i]bne $t0, $s5, Exit # 如果save[i]≠k则结束循环add $s3, $s3, $s4 # i = i + j j Loop # 跳转到LoopExit: ……作业:P150 习题3.9 优化此程序段 四、小于时置四、小于时置1 1 指令指令: sltslt指令格式:slt rd, rs, rt #注释,R型指令指令功能:对rs、rt两个寄存器进行比较,若rs

      例3.12 编译小于判断比较变量a(对应于寄存器$s0)是否小于变量b(对应于寄存器$s1),如果小于则跳转到标号Less,写出其MIPS汇编代码 slt $t0, $s0, $s1#如果$s0 < $s1 (a < b),则$t0的值为1bne $t0, $zero, Less#如果$t0≠0(也即,a < b)则跳转到Less ; $zero是mips 计算机cpu中的0号寄存器, 其值=0这样这样,,sltslt和和bnebne指令一起指令一起,,就实现了就实现了branchbranch onon lesslessthanthan((小于时跳转小于时跳转)) 五、高级语言五、高级语言case/switchcase/switch语句语句 的实现的实现在汇编语言程序中,多分支结构最常用的实现方法是跳转地址表法,即在内存中开辟一个空间(数组)用来存放所有分支程序段的入口地址,通过查询该表获得转移地址,从而跳转到相应的分支程序段为了支持这种情况,MIPS之类的计算机包含了一个跳转寄存器(jump register)指令jr,意思是无条件转移到寄存器中指定的地址执行下一条指令而编译器在编译switch语句时, 会建立一张跳转地址表(jump address table) 而该表中对应单元里的值是转移地址:L0L1L2L3L4A[0]A[1]A[2]A[3]A[4] 跳转寄存器指令跳转寄存器指令jr ((jump registerjump register))指令格式:jr rs #注释,R型指令指令功能:无条件跳转到rs指定的地址处执行机器格式:0rs000 08 8例3.13 使用跳转地址表法来编译switch语句switch ( k ) {case 0: f = i + j; break; /* k = 0 */case 1: f = g + h;break; /* k = 1 */case 2: f = g – h;break; /* k = 2 */case 3: f = i – j; break; /* k = 3 */} 【解答】假设从f到k的6个变量对应于从$s0到$s5的6个寄存器,寄存器$t2中的值为4,跳转表首地址在$t4中。

      L0=100L1=2000L3=4000L2=3000K=0K=1K=2K=3表头地址$t4 首先测试首先测试( (0 0 ≤≤ k k ≤≤ 3 3))slt$t3, $s5, $zero# 测试k是否小于0bne$t3, $zero, Exit# 如果k < 0,则退出程序slt$t3, $s5, $t2# 测试k是否小于4beq$t3, $zero, Exit# 如果k >= 4,则退出程序K K值合法(值合法( 0 ≤ k ≤ 30 ≤ k ≤ 3 ),将跳转地址),将跳转地址A[K]A[K]取到取到$t0$t0中:中:add $t1, $s5, $s5 # 临时寄存器$t1 = 2 * kadd $t1, $t1, $t1 # 临时寄存器$t1 = 4 * kadd $t1, $t1, $t4 # $t1 = address of JumpTable[k]lw $t0, 0($t1) # 临时寄存器$t0 = JumpTable[k]jr $t0 # 基于寄存器$t0进行跳转 各分支程序段:L0: add $s0, $s3, $s4 # k = 0时,f = i + jj Exit # 该case语句结束了,退出L1: add $s0, $s1, $s2 # k = 1时,f = g + hj Exit # 该case语句结束了,退出L2: sub $s0, $s1, $s2 # k = 2时,f = g - h j Exit # 该case语句结束了,退出L3: sub $s0, $s3, $s4 # k = 3时,f = i - jExit: # switch语句的出口swith语句中的前3种情况的汇编代码是类似的,都是由一个标号,一个执行case语句的指令,一个退出switch语句的跳转指令所组成,最后一种情况,直接进入switch语句的出口。

      六、小结P95 图3—9总结MIPS汇编语言的各个组成部分,在MIPS指令中增加了分支指令和跳转指令,并在一个寄存器中永久地固定了一个很有价值的值:0 3.6 计算机硬件对过程的支持计算机硬件对过程的支持子程序(子程序(subroutinesubroutine),),或称作过程(过程( procedureprocedure)),是程序员使程序结构化的手段,它使程序易懂,代码可以重复使用在过程的执行中,程序必须遵循以下6个步骤:1.把参数放在子程序能够存取的地方:参数传递参数传递2.把控制权转交给子程序: 调用子程序调用子程序3.获取子程序所需的存储资源:保护寄存器等保护寄存器等4.执行所需的任务:执行子程序体执行子程序体5.把结果的值放在子程序的主调程序能够存取的地方:返回结果返回结果6.把控制权返回给主调程序:返回主程序返回主程序MIPS为子程序调用提供一些专用寄存器 一、过程专用寄存器一、过程专用寄存器1、$a0-$a3:4个用来传递参数的寄存器,a代表argument2、$v0-$v1:2个用来返回值的寄存器,v代表value3、$ra:一个用来返回到主调程序调用点的返回地址寄存器,ra代表return address。

      4、$sp: 一个堆栈指针寄存器,用于指向栈顶位置,Sp代表stack pointer各寄存器编号见:各寄存器编号见:P102 图图3-13 二、与过程调用相关的指令二、与过程调用相关的指令1、跳转并链接指令jal (jump-and-link),也称过程调用指令指令格式:jal子程序入口标号指令功能:1)把该指令的下一条指令地址PC+4保存在$ra中;2)跳转到子程序所在的地址,子程序入口地址送给PC机器格式:3Label6位26位指令中的link表示一个地址或链接,指向调用点以便子过程能正确返回,该链接保存在$ra中,称为返回地址存储程序概念隐含这样一种思想:需要有一个寄存器来保存当前执行的指令的地址由于历史上的原因,在MIPS体系结构中,这个寄存器通常称为程序计数器(程序计数器(program counter,, PC))尽管“指令地址寄存器”这个名称可能更合理些 ,如IBM-PC计算机称作IP 2、过程返回指令jr指令格式:jr $ra #功能类似ret指令,过程的最后一条指令子程序参数传递方法:1) 通过寄存器寄存器:主调程序(caller)把参数值放在$a0-$a3中,并用指令jal X 跳转到子程序X,X是被调程序(callee)。

      X接着执行其指令,把结果放在$v0-$v1中,然后把控制权返回给主调程序2) 通过堆栈:堆栈:数据进入堆栈称为“压入”(push),数据离开堆栈称为“弹出”(pop)堆栈指针(堆栈指针(stack pointerstack pointer)),其符号为$sp,堆栈的栈顶地址比栈底地址低 ,把值压入栈中时,$sp的值就减小增加$sp的值则使堆栈收缩,从而把值从堆栈中弹出 例3-14 编译一个非嵌套过程intint leaf_exampleleaf_example ( ( intint g,g, intint h,h, intint i,i, intint j j ) ){ {intintf f; ;f f = = ( ( g g + + h h ) ) - - ( ( i i + + j)j); ;returnreturnf f; ;} }【解答】参数变量g, h, i, j分别对应于参数寄存器$a0, $a1, $a2, $a3变量f对应于$s0编译后的程序以该过程的标号为开头: leaf_example:#子程序名, 标号将寄存器入堆栈进行保护:sub $sp, $sp, 12# 调整堆栈,腾出空间保护寄存器sw$s0, 8($sp)# 保存寄存器$s0以防破坏sw$t0,4($sp)# 保存寄存器$t0以防破坏sw$t1,0($sp)# 保存寄存器$t1以防破坏下面3条指令对应于赋值语句f = (g+h ) f = (g+h ) - - (i+j)(i+j) :add $t0, $a0, $a1 # $t0 = g + h add $t1, $a2, $a3 # $t1 = i + jsub $s0, $t0, $t1 # f = $t0 - $t1将计算结果放入返回寄存器$v0:add $v0, $s0, $zero # 返回f,($v0=$s0+0) 寄存器出栈恢复,并恢复堆栈指针:lw $t1, 0($sp) # 恢复寄存器$t1lw $t0, 4($sp) # 恢复寄存器$t0lw $s0, 8($sp) # 恢复寄存器$s0以备主调程序使用add $sp, $sp,12 # 调整堆栈,收回堆栈空间jr $ra # 返回调用程序作业:作业:P148 3.1 3.2 3.3 3.4 $t1, $t0, $s0保护进堆栈的堆栈变化状况 MIPS使用寄存器的约定使用寄存器的约定: :MIPS提供了两类寄存器:$t0-$t9:10个临时临时((temporarytemporary))寄存器寄存器,在子程序的调用中不要保护。

      s0-$s7:8个需要保存的需要保存的(saved)(saved)寄存器寄存器,在子程序的调用中必须加以保护 leaf_example: #子程序名, 标号sub $sp, $sp, 4 # 调整堆栈,腾出空间保护寄存器sw $s0, 0($sp) # 保存寄存器$s0以防破坏add $t0, $a0, $a1 # $t0 = g + h add $t1, $a2, $a3 # $t1 = i + jsub $s0, $t0, $t1 # f = $t0 - $t1add $v0, $s0, $zero # 返回f,($v0=$s0+0)lw $s0, 0($sp) # 恢复寄存器$s0以备主调程序使用add $sp, $sp, 4 # 调整堆栈,收回堆栈空间jr $ra # 返回调用程序这样,例这样,例3 3- -1414就可以简化如下:就可以简化如下: 三、为新数据分配空间三、为新数据分配空间过程中的一些大型数据结构如数组、结构体等通常保存在堆栈中,除此之外,如果有超过四个参数需要传递到过程中,则前4个参数放入$a0----$a3寄存器,后面的参数压入堆栈,用$fp框架指针寻址。

      P101 图3-12 硬件硬件/ /软件接口软件接口((P102 P102 图图3 3- -1313))C语言中的变量是一个存储单元 , C语言有自动(自动(automatic))和静态静态((static))两种存储类别 ,为了简化对静态存储变量的存取,MIPS提供了一个寄存器,称为全局指针(全局指针(global pointer),),其符号为$gp 3.8 MIPS3.8 MIPS的其它寻址方式的其它寻址方式很多时候,程序中需要对常数进行操作,而如果采用目前所学过的指令,则需要先从内存中读取常数,然后才能使用,而程序中有大量使用常数的指令,这样太复杂了,为了提高效率,根据硬件设计的最后一个原则:设计原则设计原则4 4:加快对常见情况的处理:加快对常见情况的处理Make the common case fastMake the common case fast引入能对常数直接进行操作的指令,即在算术指令中加入常数字段,这样就比从存储器中读取要快得多 一、立即数指令一、立即数指令1、加立即数指令addi指令格式: addirt,rs,imm#注释,I型指令指令功能:rt=rs+imm机器格式:8rsrtimm31.… 26 25…….21 20…...16 15…………………………….0例:addi $sp, $sp, 4addi $sp, $sp, -4 2、小于立即数则置1指令slti指令格式: slti rt, rs, imm #注释指令功能:若rs<立即数imm,则rt寄存器置为1机器格式:10rsrtimm31.… 26 25…….21 20…...16 15…………………………….03、装入高位立即数指令lui指令格式: lui rt, imm #注释指令功能:将16位立即数imm送入rt寄存器的高16位,而rt寄存器的低16位清零机器格式:150rtimm31.… 26 25…….21 20…...16 15…………………………….0 lui 把16位立即数装入寄存器高16位,而低16位清零.硬件硬件/ /软件接口:软件接口: 不管是编译器还是汇编器都必须把大常数分割成小常数,然后重新汇集到寄存器中。

      I型指令中immediate域的大小限制,对于内存地址以及I型指令中常量的使用可能会有影响如果这一问题由汇编器来解决,那么汇编器需要一个临时寄存器来创建大常量这就是为汇编器保留寄存器这就是为汇编器保留寄存器$ $atat的原因的原因 例3-15 加载一个32位的常数怎样用MIPS指令把下面的32位常数装入$s0寄存器中?0000 0000 0011 1101 0000 1001 0000 0000【解答1】首先用lui指令装入高16位:lui $s0, 61然后用加法指令把低16位加到$s0中:addi $s0, $s0, 2304 【解答2】addi指令会将16位立即数的最高位符号扩展到高16位中,因此应使用ori指令配合生成32位常数lui $s0, 61ori $s0, $s0, 2304 二、分支和跳转指令的寻址二、分支和跳转指令的寻址1、跳转指令的寻址:伪直接寻址(pseudodirect addresssing)j label其跳转的目标地址由26位的label左移2位(乘4)后的28位字节地址与PC中的高4位拼接形成225006位26位例3—16 下面的指令j 10000 # 跳转到地址为10000的地方经汇编后,机器码(以十进制表示)为:指令执行后,跳转的目标地址为PC=PC[31--28]○2500*4: 2、分支指令的寻址:PC相对寻址beq/bne rs, rt, label其转移的目标地址是下条指令与目标指令之间的字节偏移量与PC之和。

      条件转移指令则不同,不仅有跳转地址,还要指定2个操作数下面的指令:bne$s0,$s1,Exit# 如果$s0≠$s1,则跳转到Exit经汇编后,机器码(以十进制表示)为:51617跳转地址偏移量6位5位5位16位 如果把程序的地址限于16位的域,则程序的指令数不能超过216,这显然是太少了MIPS的实际做法是,指定一个寄存器来与地址域中的跳转地址相加,把和作为实际的跳转地址,可以用下面的公式来计算:程序计数器程序计数器PCPC==PCPC寄存器的值寄存器的值 ++ 跳转地址偏移量跳转地址偏移量* *4 4这样,程序的指令数可达232,从而解决了条件转移指令的跳转地址大小问题这 种 方 式 的 跳 转 寻 址 称 为 PCPC 相 对 寻 址相 对 寻 址 (( PCPC- -relativerelativeaddressingaddressing)) PC-relative addressing(PC)PCPC+4BNE $t1, $t2 , SKIP低地址高地址-32768 PCPC相对寻址方式条件转移地址的计算公式相对寻址方式条件转移地址的计算公式PC= (PC+4) +地址偏移x4因为执行bne指令时, 取值操作已经完成,PC已经加了4,所以新的PC值等于: PC+4。

      例如:100: bne $s0, $s1, Exit 104: add $t1, $t2, $t3108:Exit: sub $t1, $t2, $t3假设$s0≠$s1 ,那么指令执行后 PC=?【解答】如果 $s0≠$s1 则PC=104+(offset)x4=104+1x4=108 例例3 3- -1717:展示机器语言中的转移地址偏移量:展示机器语言中的转移地址偏移量例3-11的while循环经编译后成为下面的MIPS汇编代码:Loop:add$t1, $s3, $s3add$t1, $t1, $t1add$t1, $t1, $s6lw$t0, 0($t1)bne$t0, $s5, Exitadd$s3, $s3, $s4jLoopExit:假设该循环在内存中的起始地址为80000,写出其MIPS机器代码 【【解答解答】】机器代码及其地址如下:MIPS分支指令使用相对PC的字距离来寻址,所以第五行的bne指令中的地址字段的值应该是2而不是8最后的jump指令使用对应于标号Loop的绝对字地址80000/4=20000220000 三、三、MIPS的寻址方式(的寻址方式(addressing modeaddressing mode)总结)总结1.寄存器寻址寄存器寻址((register addressing)):操作数都在寄存器中。

      2 基 地 址 寻 址 或 偏 移 量 寻 址基 地 址 寻 址 或 偏 移 量 寻 址 (( baseordisplacementaddressing)):有一个操作数在内存中,其地址是指令中的一个寄存器和指令中常量的值之和3.立即数寻址立即数寻址((immediate addressing)):有一个操作数是在指令中的常量4.PCPC相对寻址相对寻址((PC-relative addressing)):地址是PC和指令中常量*4的值之和5.伪直接寻址伪直接寻址((pseudodirect addressing)):地址是指令中的26位地址*4,同PC的高4位连接起来的32位,也即32位字节地址 四、机器语言的解码四、机器语言的解码例3-18 写出下面的机器指令对应的汇编语言:【【解答解答】】第一步是根据op域,确定这是什么指令从表3.5可以查到,31-26位为00000,该指令是R-format的指令然后按照R型指令格式把该机器指令重写一遍:op rs rt rd shamt funct 000000 00101 01111 10000 00000 100000再判断具体是什么操作:5-0位为100000,正好是add指令。

      最后看看其它域的值,rs、rt、rd的十进制值分别是5、15、16,说明对应的寄存器分别是$a0、$t7、$s0这时就可以写出该机器指令对应的汇编指令:add $s0, $a0, $t7  本章小结本章小结存储程序式的计算机的两条基本原理是,指令像数字一样表示,程序在内存能象数据一样读写指令集的设计,必须能够很好地平衡执行程序所需指令数,每条指令所需时钟周期,以及时钟的速度这3个因素以下4条设计原则对于实现指令集的这种平衡起着指导作用:1.规整化简化硬件规整化简化硬件Simplicity favors regularity. ))规整化促进了MIPS指令集的以下特性的形成:保持所有指令的大小相同,在算术指令中总是需要3个寄存器操作数,保持每种指令格式中的寄存器域在同一位置2. 越小越快越小越快Smaller is faster. ))对速度的要求正是MIPS选择32个寄存器而不是更多的寄存器的原因3.好的设计需 要 折衷考 虑好的设计需 要 折衷考 虑 Good design demands goodcompromises. ))在MIPS中的例子就是,在指令中提供更大的地址和常量的要求,与保持所有指令的长度相同的要求之间的折衷。

      4.常见的情况要快常见的情况要快Make the common case fast. ))例如,在MIPS中,条件转移指令使用PC相对寻址,常量操作数使用立即数寻址 3.9 程序的运行过程程序的运行过程 运行程序的第一步是编译运行程序的第一步是编译高级语言程序比汇编语言程序所用代码行要少得多,从而效率也高得多但机器不能直接识别高级语言程序,它需要编译器将把C程序转换成汇编语言程序,即机器能理解的符号指令形式1975年前,很多操作系统和汇编器都是用汇编语言写的,因为那时候的内存容量很小,编译器的效率也不高如今内存容量大大提高了,从而减少了对程序大小的限制;编译器经优化后产生的汇编语言程序,可以比得上汇编语言专家所写的程序,对于一些大程序,甚至比专家写的更好这使得高级语言和编译器得到了广泛的应用这使得高级语言和编译器得到了广泛的应用 汇编汇编: : 汇编语言是计算机提供给高层软件的一汇编语言是计算机提供给高层软件的一个接口个接口伪指令伪指令((pseudoinstructionpseudoinstruction)),它们不需要在硬件上实现,但汇编语言有了这些指令,可以简化编程和汇编的过程。

      move$t0, $t1 # 寄存器$t0获得$t1的值(伪指令伪指令) )汇编器把它转换成与下面这条指令等价的机器语言:add$t0, $zero, $t1# 寄存器$t0获得0 + $t1的值汇编器的主要任务是把汇编语言翻译成机器代码它把汇编语言的程序转换成目标文件目标文件((objectobject filefile)),该文件包括机器语言指令、数据,以及把指令正确放在内存中所需的信息汇编器还必须确定所有标号的地址它把这些标号放在一个符号表符号表((symbolsymbol tabletable))中,每个标号对应一个地址 Unix系统的目标文件通常包括6个不同部分:1.目标文件报头目标文件报头((oject file header)):描述目标文件其它部 分的大小和位置2.正文段正文段((text segment)):包含机器语言代码3.数据段数据段((data segment)):包含程序用到的数据,其中包括静态数据和动态数据4.重定位信息重定位信息((relocation information)):对取决于绝对地址的指令字和数据字进行标识,以便程序装入内存中时进行重定位。

      5.符号表符号表((symbol table)):包含没有定义的标号,如外部引用6.调试信息调试信息((debugging information)):对汇编模块的简单描述,以便调试器可以把机器指令同C语言源文件联系起来,使数据结构具有易读性 3.9.3 链接目标代码链接目标代码链接编辑器链接编辑器((linklink editoreditor))或链接程序链接程序((linkerlinker)),它把独立汇编后产生的所有机器语言程序“缝合”在一起链接程序需要3个步骤来完成它的使命:1.把代码模块和数据模块放在内存中2.确定数据和指令标号的地址3.修正内部和外部的引用链接程序在每个目标模块中使用重定位信息和符号表来处理所有未定义的标号,这些引用发生在branch指令、jump指令和数据地址中因此链接程序就如同一个编辑器,它找到旧的地址,并用新地址来代替使用链接程序的一个重要原因就是,修补代码比重新编译和重新汇编要快得多 堆栈指针初始化为7fff fffchex,程序代码的起始地址为00400000hex静态数据起始地址为1000 0000hex动态数据起始地址紧邻着静态数据, 向上增长全局指针$gp被初始化为1000 8000,以$gp为基地址,使用16位偏移量(正负),就可以存取从1000 0000hex到1000 ffffhex的范围。

      3.9.4 把程序装入内存中把程序装入内存中经过前面3步,可执行文件还在磁盘上,操作系统把它读到内存中,并启动程序在Unix系统中如下6个步骤:1.读取可执行文件报头,确定正文和数据段的大小2.为正文和数据创建一个足够大的地址空间3.把可执行文件中的指令和数据复制到内存中4.如果主程序有参数,则复制到内存中5.初始化寄存器,把堆栈指针指向上面创建的空间中第一个空闲位置6. 跳到一个启动例行程序,把参数复制到参数寄存器中,调用程序的主程序主程序返回时,启动例行程序用系统调用exit来结束整个程序 3.10 综合程序范例综合程序范例从C语言的两个子程序(交换数组元素的子程序swap和对数组元素排序的子程序sort)来进一步介绍MIPS汇编代码的设计方法C 子程序swap:swap ( intv[ ], intk ){inttemp;temp = v[k];v[k] = v[k + 1];v[k + 1] = temp;}编写MIPS汇编代码一般遵循以下步骤:1.为子程序中的变量分配寄存器2.为子程序体产生代码3.保护寄存器,以免其内容在子程序调用之间受到破坏。

      第一步:为第一步:为swap子程序子程序分配寄存器分配寄存器由于swap只有两个参数——v和k,它们就分别放在参数寄存器$a0和$a1中只有一个临时变量,用$t1.第二步:为第二步:为swapswap子程序体产生代码子程序体产生代码C语言中int型变量是4个字节长,MIPS是按字节寻址的,因此索引k要乘以4再参与地址运算(在用汇编语言编程时,很多人往往忘记这一点,这点需要加倍注意) 3.10.2 子程序子程序sort子程序sort,它对一个整数数组的元素进行排序它要调用前面的swap子程序sort ( int v[ ], int n ){inti, j;for ( i = 0; i < n; i = i + 1 ) {for ( j = i - 1; j >= 0 && v[j] > v[j+1]; j = j - 1 )swap ( v, j );}} 3.11 数组和指针的比较数组和指针的比较对使用数组及数组索引的汇编代码与使用指针的汇编代码进行比较 ,便于理解指针的用法 和优点.clear1 ( intarray[ ], intsize );用数组下标编写清0{inti;for ( i = 0; i < size; i = i + 1 )array[i] = 0;}clear2 ( int*array, intsize ); 用指针编写清0{int*p;for ( p = &array[0]; p < &array[size]; p = p + 1 )*p = 0;} loop1:add$t1, $t0, $t0# $t1 = i * 2add$t1, $t1, $t1# $t1 = i * 4add$t2, $a0, $t1# $t2 = address of array[i]sw$zero, 0($t2)# array[i] = 0addi$t0, $t0, 1# i = i +1slt$t3, $t0, $a1# $t3 = (i < size)bne$t3, $zero, loop1# 如果i < size则跳转到到loop1用指针:move$t0, $a0# p = address of array[0]add$t1, $a1, $a1# $t1 = size * 2add$t1, $t1, $t1# $t1 = size * 4add$t2, $a0, $t1 # $t2 = address of array[size]loop2:sw$zero, 0($t0)# Memory[p] = 0addi$t0, $t0, 4# p = p + 4slt $t3, $t0, $t2# $t3 = (p < & array[size])bne$t3, $zero, loop2# $t3 = 1则跳转到loop2 两个子程序放在一起比较一下: 3.12 PowerPCPowerPC和和80x8680x86的指令实例的指令实例1 IBM/Motorola PowerPCPowerPC多出的两种寻址方式是:1). 索引寻址(索引寻址(indexed addressingindexed addressing))lw$t1, $a0 + $s3# $t1 = Memory[$a0 + $s3]2).更新寻址(更新寻址(update addressingupdate addressing))lwu $t0, 4($s3) # $t0 = Memory[$s3 + 4]; $s3 = $s3 + 42 Intel 80x86我们在这里介绍80x86系列的目的是让读者对世界上最流行的体系结构的优点和缺点有所了解,而不是为了去写80x86的程序。

      详见课文 3.13 指令集发展历史指令集发展历史1 累加器体系结构 : A = B + C; 2 通用寄存器体系结构 :专用寄存器的通用化使得所有的寄存器都可用于任何目的的操作,这样就产生了通用寄存器(通用寄存器(generalgeneral- -purpose registerpurpose register)体系结)体系结构构MIPS就属于这种类型又分为二种:(1)(1)寄存器-内存型(寄存器-内存型(registerregister- -memory, Rmemory, R- -M(S)M(S))体系结构)体系结构; ;(2) 要求所有操作数都必须在寄存器中的装入-存储型(装入-存储型(loadload- -storestore)或寄存器-寄存器型()或寄存器-寄存器型(registerregister- -register, Rregister, R- -R R)体系)体系结构结构 3 紧凑编码和堆栈体系结构紧凑编码和堆栈体系结构在内存不足的情况下,保持程序的短小是很重要的,因此像Intel 80x86、IBM 360和VAX之类的机器都有变长指令,以匹配变长的操作数,并使代码最小化。

      这种技术称为紧凑编码紧凑编码((compactcompact codecode))Intel 80x86的指令的长度范围是1到17个字节;IBM 360指令长度为2、4或6个字节;VAX指令长度可以是1到54个字节之间的任一字节数如果指令内存空间开始变得宝贵,这样的技术可能又会流行起来4高级语言计算机体系结构高级语言计算机体系结构Burroughs B5000是这种思想的商业源头是这种思想的商业源头,,但如今它已没有但如今它已没有什么有显著影响的后代什么有显著影响的后代一种计算机设计的思想一种计算机设计的思想,,称为高级语称为高级语言 计 算 机 体 系 结 构言 计 算 机 体 系 结 构 (( highhigh- -levellevel- -languagelanguagecomputercomputerarchitecturearchitecture)),,其目标是使硬件更像编程语言其目标是使硬件更像编程语言后来更高效后来更高效的编程语言和编译器的产生的编程语言和编译器的产生,,加上内存的扩充加上内存的扩充,,注定了它的失注定了它的失败败 5 精简指令集计算机体系结构精简指令集计算机体系结构面向语言的思想被精简指令集计算机精简指令集计算机((reducedreduced instructioninstructionsetset computercomputer,,RISCRISC))所取代。

      编程语言、编译技术和内存容量的提高,使得需要在汇编级别做的事情更少了,因此指令集应该通过编译器使用指令集的好坏程度来衡量,而不是通过汇编语言程序员使用的好坏来衡量事实上从1982年以来,所有的新指令集都遵循RISC的思想:固定指令长度,装入-存储型指令集,少量的寻址方式和少量的操作RISC的实例有:MIPS, Sun SPARC, Hewlett-Packard PA-RISC,IBM PowerPC, 以及DEC Alpha 3.14 本章小结本章小结存储程序式的计算机的两条基本原理是,指令像数字一样表示,程序在内存能象数据一样读写指令集的设计,必须能够很好地平衡执行程序所需指令数,每条指令所需时钟周期,以及时钟的速度这3个因素以下4条设计原则对于实现指令集的这种平衡起着指导作用:1.规整化简化硬件规整化简化硬件Simplicity favors regularity. ))规整化促进了MIPS指令集的以下特性的形成:保持所有指令的大小相同,在算术指令中总是需要3个寄存器操作数,保持每种指令格式中的寄存器域在同一位置2. 越小越快越小越快Smaller is faster. ))对速度的要求正是MIPS选择32个寄存器而不是更多的寄存器的原因。

      3.好的设计需要折衷考虑好的设计需要折衷考虑Good design demandsgood compromises. ))在MIPS中的例子就是,在指令中提供更大的地址和常量的要求,与保持所有指令的长度相同的要求之间的折衷4.常见的情况要快常见的情况要快Make the common case fast. ))例如,在MIPS中,条件转移指令使用PC相对寻址,常量操作数使用立即数寻址。

      点击阅读更多内容
      关于金锄头网 - 版权申诉 - 免责声明 - 诚邀英才 - 联系我们
      手机版 | 川公网安备 51140202000112号 | 经营许可证(蜀ICP备13022795号)
      ©2008-2016 by Sichuan Goldhoe Inc. All Rights Reserved.