第三章指令系统_第1页
第三章指令系统_第2页
第三章指令系统_第3页
第三章指令系统_第4页
第三章指令系统_第5页
已阅读5页,还剩93页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

3.1概述3.2计算机硬件的操作3.3计算机硬件的操作数3.4指令的计算机内部表示3.5决策指令3.6计算机硬件对过程的支持3.7计算机对字符的处理(略去)3.8MIPS的其他寻址方式,第三章指令系统,3.1概述要给计算机硬件直接下命令,就必须使用机器的语言。机器语言中的“单词”称为指令,其“词汇表”称为指令集。本章将介绍现实中计算机所使用的指令集系统。通过学习机器指令,你会了解到计算机中的一个重要概念:存储程序(stored-rogram)着重介绍的是MIPS指令集,涉及到MIPS指令的操作数、指令格式及指令类别,1、CISC-复杂指令系统计算机ComplexInstructionSetComputer,20世纪60年代后期,随着IC、LSI、VLSI的出现和发展,计算机硬件成本不断下降,人们热衷于在指令系统真增加更多的指令和复杂的指令,来提高操作系统的效率,促使指令系统越来越复杂,这一时期的计算机称为CISC。2、RISC-精简指令系统计算机ReducedInstructionSetComputer,1975年IBM公司开始研究指令系统的合理性问题,IBM的JohnCocke提出精简指令的想法,本书作者DavidA.Patterson创造了RISC一词,并定义了其含义,后来JohnL.Hennessy带领他在斯坦福的研究小组研制成功MIPS机,精简指令系统计算机从此诞生并发展起来。,一、指令系统的发展,二、RISC的特点1、优先选取一些使用频率最高的简单指令,以及一些很有用但不复杂的指令,避免复杂指令。2、指令长度固定,指令格式种类少,寻址方式种类少,指令各字段的划分比较一致,各字段功能较规整。3、只有存数、取数指令访问存储器,其余指令的操作都在寄存器之间进行。4、CPU中通用寄存器数量较多。,三、MIPS简介1、处理器的缩写MillionInstructionPerSecond,泛指每秒能执行百万条指令的处理器MicroprocessorwithoutInterlockingPipelineStage,一种无内锁的流水线微处理器2、MIPS公司,3.2计算机硬件的操作指令,一、指令的基本格式指令格式,是指令用二进制代码表示的结构形式,通常有操作码字段和地址码字段组成。操作码表示指令的操作特性和功能,而地址码通常指定参与操作的操作数的地址,故指令基本格式如下:,1、操作码操作码字段的位数取决于指令系统的规模,例如,只有8条指令的指令系统,OP字段有3位就够了,如果系统包含32条指令,则OP字段需要5位操作码。一般来说一个包含n位的操作码能够表示2n条指令。,2、地址码根据一条指令中有几个操作数地址,可将该指令称为几地址指令,一般有三地址指令、二地址指令、一地址指令和零地址指令格式:,1、加法指令addrd,rs,rt#注释每条指令只执行一个操作,并且有且只有三个变量书写时,每一行只有一条指令,注释放在行尾,由#号引出该指令执行rd=rs+rt的操作例如:adda,b,cb+c的和存放在a中其中add称操作符,表示加运算;紧跟add的a是目的操作数,即为结果,其余b、c表示源操作数。每条指令中由“”号领头的部分是注释。,三、MIPS算术运算指令,例如:计算a=b+c+d+e;adda,b,cb+c的和存放在a中adda,a,db+c+d的和已存放在a中adda,a,eb+c+d+e的和已存放在a中,2、减法指令subrd,rs,rt#注释例3.1把两个C语言赋值语句编译成MIPS汇编指令下面这段C语言代码包含5个变量a,b,c,d,e:a=b+c;d=ae;,【解答】adda,b,c#a=b+csubd,a,e#d=ae例3.2把一个复杂的C语言赋值语句编译成MIPS汇编指令f=(g+h)(i+j);,【解答】addt0,g,h临时变量t0=g+h的和addt1,i,j临时变量t1=i+j的和最后做减法,把差放在f中:subf,t0,t1f=t0-t1的值完成一个类似于加法的操作需要3个操作数:2个数参与运算,1个数存放结果。每条指令刚好包含3个操作数,不多也不少,这是遵循简化硬件的原则,因为操作数的个数不定的硬件实现比个数固定的硬件实现复杂得多。这就是硬件设计要考虑的第一条原则:设计原则1:简单性来自规则性。(Simplicityfavorsregularity.),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:越小越快。(Smallerisfaster.)寄存器的数量如果很大,则电信号需要传输的距离更长,因而时钟周期也会变得很长。,例3.3使用寄存器编译C语言赋值语句,以上例C语言赋值语句为例:f=(g+h)(i+j);,为变量f,g,h,i,j分别指定寄存器$s0,$s1,$s2,$s3,$s4而临时变量指定寄存器$t0,$t1,则MIPS汇编符号指令:add$t0,$s1,$s2寄存器$t0中包含g+h的和add$t1,$s3,$s4寄存器$t1中包含i+j的和sub$s0,$t0,$t1$t0-$t1的差放入f中,硬件/软件接口编译器不仅把变量同寄存器联系起来,还为数组和结构这样的数据结构分配内存空间。这样,编译器就能把恰当的基地址放入数据传送指令中。,二、操作数在内存单元中,计算机如何表示和存取数组这样的复杂数据结构呢?处理器只能在寄存器中保存很少的数据,而内存则可以存放数以百万计的数据单元。因此,数组这样的数据结构存放在内存中。内存单元用地址编号表示,叫内存地址,例:,实际MIPS内存地址:一个字=4字节表示,按字节编址:,字节寻址还影响数组的索引。要得到正确的地址,加到基址上的偏移量应该乘以4。,三、数据传送指令:LW与SW,1、取字指令(LoadWord)LW指令格式:Lwrt,offset(rs)#注释offset为偏移量,是数组首地址到数组中某元素存储位置的字节偏移量,是一个常数。rs是存储数组首地址的寄存器,称为基址寄存器rt为目的操作数寄存器,存放取自【(rs)+offset】的数据注意:offset(rt)表示存放数据的内存单元地址,即内存地址。例3.4编译有一个操作数在内存中的C语言赋值语句:g=h+A8;设数组A100,【解答】操作数A8在内存中,首先得把它转移到寄存器中。它的地址是数组A的基地址加上8*4的和。假设$s3存放数组A的基地址,g对应$s1寄存器,h对应$s2寄存器。lw$t0,32($s3)临时寄存器$t0存放A8的值add$s1,$s2,$t0g=h+A8数据传送指令中的常量称为偏移量(offset),用来计算地址的寄存器称为基地址寄存器(baseregister)。内存有效地址EA=offset(偏移量)+rs(基地址寄存器),2、存字指令(StoreWord)SW,例3.5使用取指令和存储指令进行编译:C语句:A12=h+A8;,指令格式:swrt,offset(rs)#注释指令功能:将rt寄存器中的数据存入【(rs)+offset】内存单元注意事项:同lw指令,【解答】首先应该使用lw指令将A8取到寄存器中,再做加法运算,最后利用sw指令将和存入A12。假设变量h在$s2寄存器中,数组A的基址在$s3中,则该C语句的MIPS汇编指令代码如下:,lw$t0,32($s3)临时寄存器$t0存放A8的值add$t0,$s2,$t0临时寄存器$t0存放h+A8的值sw$t0,48($s3)把h+A8的值存储到A12中,例3.6使用可变数组下标进行编译,假设A是100个元素的数组,基地址在寄存器$s3中,变量g,h,i分别和寄存器$s1,$s2,$s4相联系。写出下面的C语句的MIPS汇编代码:g=h+Ai,【解答】为了能从Ai中取出数据,首先要得到Ai的内存地址,且必须以offset(rs)的形式体现。通过计算A+4*i可得Ai的内存地址,将其放入基址寄存器,这样只要令偏移量offset为0,即可以offset(rs)的形式实现取数指令:,add$t1,$s4,$s4临时寄存器$t1=2*iadd$t1,$t1,$t1临时寄存器$t1=4*iadd$t1,$t1,$s3临时寄存器$t1=Ai的地址(4*i+$s3),然后把Ai取到临时寄存器中:lw$t0,0($t1)临时寄存器$t0=Ai,最后把Ai和h加起来,放到变量g中:add$s1,$s2,$t0g=h+Ai,四、软硬件接口:溢出(spilling)寄存器,很多程序中变量的数量比寄存器的数量多。因此,编译器尽量把使用最频繁的变量保持在寄存器中,而把其余的放在内存中,并用取数和存储指令在寄存器和内存之间传送数据。将不常用或是以后才用到的变量存入内存的过程称为溢出(spilling)寄存器。,五、小结,P83图34,指令与操作数小结,3.4指令的计算机内部表示,在计算机内部,指令体现为二进制数,由连续的0,1串组成,计算机为了识别指令,会将这个32位的二进制数分成几个字段,用来表示不同的信息,如表示操作码、寄存器号等。机器指令格式以二进制表示:,计算机如何识别和解释指令呢?首先要了解机器指令的表示。,MIPS汇编指令如下所示:add$t0,$s1,$s2二进制表示为:00000010001100100100000000100000,一、R型指令格式,这些字段的意义是:op:指令的操作码,传统上称为opcode,此处为0。rs:表示第1个源操作数的寄存器。rt:表示第2个源操作数的寄存器。rd:表示目的操作数的寄存器,用来保存操作的结果。shamt:移位位数,移位指令用作移位次数控制。funct:功能域,用来选择op域的一个特定的操作。有时称为函数码(functioncode)R型(R-typeorR-format)指令,其中R代表寄存器(Register),意为操作数都在寄存器中。,以上的R型指令非常适合运算类的指令,但当用于存、取数指令时,如果偏移地址使用5位字段,则偏移的范围就表达的太小了,并不适用。因此,一方面要使所有指令长度都相同,另一方面又要让每条指令的格式都合适,产生了矛盾,因而提出了硬件设计的第三个原则:好的设计需要合适的折衷。Gooddesigndemandsgoodcompromises.由此进行折衷,设计出适合数据传送类指令的I型指令格式。,例题:写出指令add$t0,$s1,$s2的机器代码,二、I型指令格式(Immadiate-Type),各字段含义如下:op字段:操作码字段,35表示取数指令lw,43表示存数指令swrs字段:基址字段,存放基址寄存器号rt字段:取指令的目的操作数寄存器号或存指令的源寄存器号。offset字段:偏移量字段,指定相对于基址rs的字节偏移量。,16位的偏移量意味着存、取数指令可以装入的字的地址范围是,以rs中的基地址为中心,215(即32,768)个字节的范围,也即213(即8192)个字的范围。,分析下列取数指令的机器代码:lw$t0,32($s3)临时寄存器$t0存放A8的值,注意:在取指令lw中,rt字段指定的是目的操作数寄存器。,这里,$s3(寄存器号19)放在rs域中,$t0(寄存器号8)放在rt域中,偏移量32放在offset域中。该指令用十进制数表示的格式为:,MIPS指令的编码,注意:n.a.即notapplicable,表示在这条指令中无此字段。,例3.7将MIPS汇编语言翻译成机器语言,写出C语句:A300=h+A300的机器语言代码。,【解答】假设数组A的基地址在$t1中,变量h对应于寄存器$s2,则C赋值语句编译后的MIPS汇编代码如下:,lw$t0,1200($t1)临时寄存器$t0存放A300的值add$t0,$s2,$t0临时寄存器$t0存放h+A300的值sw$t0,1200($t1)将h+A300的值存回A300中,然后再写出这3条指令的MIPS机器语言代码。为了方便起见,先用十进制数来表示机器指令。根据前页表3.1,可得出下面的机器指令:,A300=h+A300;,lw$t0,1200($t1)add$t0,$s2,$t0sw$t0,1200($t1),四、存储程序(stored-program)的概念。,计算机的两个重要原理:1.指令是以数的形式表示的。2.程序可以存放在内存中,像数字一样被读写。,三、小结:P87图36,3.5决策指令,计算机区别于简单的计算器之处就在于它的决策能力。基于输入数据和计算中产生的值的各种情况,执行的指令也可能不同。在高级语言中一般用if语句代替决策,有时用带goto的if语句实现决策,MIPS中有类似功能的两种决策指令:,一、分支指令(条件跳转指令)1、beq指令指令格式:beqregister1,register2,Label#注释指令功能:若register1=register2则跳转到标号为Label的语句,例3.8将if语句编译成条件分支语句if(i=j)gotoL1;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,$s2f=g+h(如果i等于j则该指令被跳过)L1:sub$s0,$s0,$s3f=f-i(该指令总是要执行),2、bne指令,指令格式:bneregister1,register2,Label#注释指令功能:若register1register2则跳转到标号为Label的语句,例3.9将if-then-else语句编译成条件转移指令if(i=j)f=g+h;elsef=g-h;,【解答】bne$s3,$s4,Else如果ij则跳转到Elseadd$s0,$s1,$s2f=g+h(如果ij则该指令被跳过)jExit跳转到ExitElse:sub$s0,$s1,$s2f=g-h(如果i=j则跳过该指令)Exit:,3、beq与bne指令的机器指令格式,由于beq与bne指令中包含了跳转位置与当前指令的字偏移量,故采用I型指令格式更为合适:,其中,beq指令的op值为4,bne指令的op值为5,rs、rt两寄存器指定进行比较的两个数据,Label表示当前指令的下一条指令地址与跳转目标地址之间的字偏移量,可正可负。,需要注意的是,本来程序顺序执行,遇到beq/bne指令后,一旦发生跳转,则PC寄存器的内容会被修改,由原来的PC+4修改为PC+4+Label*4,即:需要将标号左移2位。,二、无条件跳转指令,指令格式:jLabel#注释指令功能:无条件跳转到标号为Label的语句机器格式:,其中,Label表示跳转目标地址的26位字地址,但内存地址均为32位,故此26为字地址需要左移2位后形成28位字节地址,所以用当前PC寄存器的高4位与这个28位字节地址拼接形成一个32位内存地址,写入PC,以实现跳转。,三、循环结构的实现,决策指令在if语句和循环结构的实现中都起着重要的作用,在分支结构中用于二者选一;在循环结构中用于重复执行。在这两种情况下,关于决策的汇编指令是相同的,即高级语言中的if语句和while语句都是由决策指令beq和bne来实现的。,例3.10编译一个带有可变数组下标的循环Loop:g=g+Ai;i=i+j;if(i!=h)gotoLoop写出该循环的MIPS汇编代码,【解答】假设A是100个元素的数组,数组A的基地址在$s5中,变量g,h,i,j分别对应于寄存器$s1,$s2,$s3,$s4。,首先将Ai取出放入临时寄存器$t0Loop:add$t1,$s3,$s3临时寄存器$t1=2*iadd$t1,$t1,$t1临时寄存器$t1=4*iadd$t1,$t1,$s5$t1=addressofAilw$t0,0($t1)临时寄存器$t0=Ai,下面两条指令把Ai加到g中,j加到i中:add$s1,$s1,$t0g=g+Aiadd$s3,$s3,$s4i=i+jbne$s3,$s2,Loop如果ih则跳转到Loop,例3.11编译while循环while(savei=k)i=i+j;写出这段C程序的MIPS汇编代码。,【解答】假设i,j,k分别对应于寄存器$s3,$s4,$s5,数组save的基地址在$s6中。写出该循环的MIPS汇编代码。,程序员一般不使用goto语句实现循环,传统的循环结构是用while语句来实现的,可通过编译器来翻译。,Loop:add$t1,$s3,$s3临时寄存器$t1=2*iadd$t1,$t1,$t1临时寄存器$t1=4*iadd$t1,$t1,$s6$t1=addressofsaveilw$t0,0($t1)临时寄存器$t0=saveibne$t0,$s5,Exit如果saveik则结束循环add$s3,$s3,$s4i=i+jjLoop跳转到LoopExit:,作业:P150习题3.9优化此程序段,四、小于时置1指令:slt,指令格式:sltrd,rs,rt#注释,R型指令指令功能:对rs、rt两个寄存器进行比较,若rsrt,则将rd寄存器的值置为1,反之置为0。软硬接口:必须引入一个专用寄存器$zero来实现各种大小关系的判断,$zero的值恒为0,且slt必须与beq/bne指令联用。,例3.12编译小于判断比较变量a(对应于寄存器$s0)是否小于变量b(对应于寄存器$s1),如果小于则跳转到标号Less,写出其MIPS汇编代码。,slt$t0,$s0,$s1如果$s0$s1(ab),则$t0的值为1bne$t0,$zero,Less如果$t00(也即,ab)则跳转到Less;$zero是mips计算机cpu中的0号寄存器,其值=0这样,slt和bne指令一起,就实现了branchonlessthan(小于时跳转)。,五、高级语言case/switch语句的实现,在汇编语言程序中,多分支结构最常用的实现方法是跳转地址表法,即在内存中开辟一个空间(数组)用来存放所有分支程序段的入口地址,通过查询该表获得转移地址,从而跳转到相应的分支程序段。为了支持这种情况,MIPS之类的计算机包含了一个跳转寄存器(jumpregister)指令jr,意思是无条件转移到寄存器中指定的地址执行下一条指令。而编译器在编译switch语句时,会建立一张跳转地址表(jumpaddresstable)而该表中对应单元里的值是转移地址:,跳转寄存器指令jr(jumpregister)指令格式:jrrs#注释,R型指令指令功能:无条件跳转到rs指定的地址处执行机器格式:,例3.13使用跳转地址表法来编译switch语句switch(k)case0:f=i+j;break;/*k=0*/case1:f=g+h;break;/*k=1*/case2:f=gh;break;/*k=2*/case3:f=ij;break;/*k=3*/,【解答】假设从f到k的6个变量对应于从$s0到$s5的6个寄存器,寄存器$t2中的值为4,跳转表首地址在$t4中。,首先测试(0k3)slt$t3,$s5,$zero测试k是否小于0bne$t3,$zero,Exit如果k=4,则退出程序,K值合法(0k3),将跳转地址AK取到$t0中:add$t1,$s5,$s5临时寄存器$t1=2*kadd$t1,$t1,$t1临时寄存器$t1=4*kadd$t1,$t1,$t4$t1=addressofJumpTableklw$t0,0($t1)临时寄存器$t0=JumpTablekjr$t0基于寄存器$t0进行跳转,各分支程序段:L0:add$s0,$s3,$s4k=0时,f=i+jjExit该case语句结束了,退出L1:add$s0,$s1,$s2k=1时,f=g+hjExit该case语句结束了,退出L2:sub$s0,$s1,$s2k=2时,f=g-hjExit该case语句结束了,退出L3:sub$s0,$s3,$s4k=3时,f=i-jExit:switch语句的出口,swith语句中的前3种情况的汇编代码是类似的,都是由一个标号,一个执行case语句的指令,一个退出switch语句的跳转指令所组成,最后一种情况,直接进入switch语句的出口。,六、小结P95图39总结MIPS汇编语言的各个组成部分,在MIPS指令中增加了分支指令和跳转指令,并在一个寄存器中永久地固定了一个很有价值的值:0,3.6计算机硬件对过程的支持,子程序(subroutine),或称作过程(procedure),是程序员使程序结构化的手段,它使程序易懂,代码可以重复使用。在过程的执行中,程序必须遵循以下6个步骤:1.把参数放在子程序能够存取的地方:参数传递2.把控制权转交给子程序:调用子程序3.获取子程序所需的存储资源:保护寄存器等4.执行所需的任务:执行子程序体5.把结果的值放在子程序的主调程序能够存取的地方:返回结果6.把控制权返回给主调程序:返回主程序MIPS为子程序调用提供一些专用寄存器。,一、过程专用寄存器,1、$a0$a3:4个用来传递参数的寄存器,a代表argument。2、$v0$v1:2个用来返回值的寄存器,v代表value。3、$ra:一个用来返回到主调程序调用点的返回地址寄存器,ra代表returnaddress。4、$sp:一个堆栈指针寄存器,用于指向栈顶位置,Sp代表stackpointer,各寄存器编号见:P102图3-13,二、与过程调用相关的指令,1、跳转并链接指令jal(jump-and-link),也称过程调用指令。指令格式:jal子程序入口标号指令功能:1)把该指令的下一条指令地址PC+4保存在$ra中;2)跳转到子程序所在的地址,子程序入口地址送给PC。机器格式:,指令中的link表示一个地址或链接,指向调用点以便子过程能正确返回,该链接保存在$ra中,称为返回地址。存储程序概念隐含这样一种思想:需要有一个寄存器来保存当前执行的指令的地址。由于历史上的原因,在MIPS体系结构中,这个寄存器通常称为程序计数器(programcounter,PC)。尽管“指令地址寄存器”这个名称可能更合理些,如IBM-PC计算机称作IP。,2、过程返回指令jr指令格式:jr$ra#功能类似ret指令,过程的最后一条指令。,子程序参数传递方法:1)通过寄存器:主调程序(caller)把参数值放在$a0$a3中,并用指令jalX跳转到子程序X,X是被调程序(callee)。X接着执行其指令,把结果放在$v0$v1中,然后把控制权返回给主调程序。2)通过堆栈:数据进入堆栈称为“压入”(push),数据离开堆栈称为“弹出”(pop)。堆栈指针(stackpointer),其符号为$sp,堆栈的栈顶地址比栈底地址低,把值压入栈中时,$sp的值就减小。增加$sp的值则使堆栈收缩,从而把值从堆栈中弹出。,例3-14编译一个非嵌套过程intleaf_example(intg,inth,inti,intj)intf;f=(g+h)-(i+j);returnf;,【解答】参数变量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)-(i+j):add$t0,$a0,$a1$t0=g+hadd$t1,$a2,$a3$t1=i+jsub$s0,$t0,$t1f=$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返回调用程序,作业:P1483.13.23.33.4,$t1,$t0,$s0保护进堆栈的堆栈变化状况,MIPS使用寄存器的约定:,MIPS提供了两类寄存器:$t0$t9:10个临时(temporary)寄存器,在子程序的调用中不要保护。$s0$s7:8个需要保存的(saved)寄存器,在子程序的调用中必须加以保护。,leaf_example:#子程序名,标号sub$sp,$sp,4调整堆栈,腾出空间保护寄存器sw$s0,0($sp)保存寄存器$s0以防破坏add$t0,$a0,$a1$t0=g+hadd$t1,$a2,$a3$t1=i+jsub$s0,$t0,$t1f=$t0-$t1add$v0,$s0,$zero返回f,($v0=$s0+0)lw$s0,0($sp)恢复寄存器$s0以备主调程序使用add$sp,$sp,4调整堆栈,收回堆栈空间jr$ra返回调用程序,这样,例3-14就可以简化如下:,三、为新数据分配空间,过程中的一些大型数据结构如数组、结构体等通常保存在堆栈中,除此之外,如果有超过四个参数需要传递到过程中,则前4个参数放入$a0-$a3寄存器,后面的参数压入堆栈,用$fp框架指针寻址。P101图3-12,硬件/软件接口(P102图3-13),C语言中的变量是一个存储单元,C语言有自动(automatic)和静态(static)两种存储类别,为了简化对静态存储变量的存取,MIPS提供了一个寄存器,称为全局指针(globalpointer),其符号为$gp。,3.8MIPS的其它寻址方式,很多时候,程序中需要对常数进行操作,而如果采用目前所学过的指令,则需要先从内存中读取常数,然后才能使用,而程序中有大量使用常数的指令,这样太复杂了,为了提高效率,根据硬件设计的最后一个原则:设计原则4:加快对常见情况的处理Makethecommoncasefast引入能对常数直接进行操作的指令,即在算术指令中加入常数字段,这样就比从存储器中读取要快得多。,一、立即数指令,1、加立即数指令addi指令格式:addirt,rs,imm#注释,I型指令指令功能:rt=rs+imm机器格式:,例:addi$sp,$sp,4addi$sp,$sp,-4,2、小于立即数则置1指令slti指令格式:sltirt,rs,imm#注释指令功能:若rs立即数imm,则rt寄存器置为1机器格式:,3、装入高位立即数指令lui指令格式:luirt,imm#注释指令功能:将16位立即数imm送入rt寄存器的高16位,而rt寄存器的低16位清零机器格式:,lui把16位立即数装入寄存器高16位,而低16位清零.,硬件/软件接口:不管是编译器还是汇编器都必须把大常数分割成小常数,然后重新汇集到寄存器中。I型指令中immediate域的大小限制,对于内存地址以及I型指令中常量的使用可能会有影响。如果这一问题由汇编器来解决,那么汇编器需要一个临时寄存器来创建大常量。这就是为汇编器保留寄存器$at的原因。,例3-15加载一个32位的常数怎样用MIPS指令把下面的32位常数装入$s0寄存器中?00000000001111010000100100000000,【解答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、跳转指令的寻址:伪直接寻址(pseudodirectaddresssing)jlabel其跳转的目标地址由26位的label左移2位(乘4)后的28位字节地址与PC中的高4位拼接形成。,例316下面的指令j10000跳转到地址为10000的地方经汇编后,机器码(以十进制表示)为:,2、分支指令的寻址:PC相对寻址beq/bners,rt,label其转移的目标地址是下条指令与目标指令之间的字节偏移量与PC之和。,条件转移指令则不同,不仅有跳转地址,还要指定2个操作数。下面的指令:bne$s0,$s1,Exit如果$s0$s1,则跳转到Exit经汇编后,机器码(以十进制表示)为:,如果把程序的地址限于16位的域,则程序的指令数不能超过216,这显然是太少了。MIPS的实际做法是,指定一个寄存器来与地址域中的跳转地址相加,把和作为实际的跳转地址,可以用下面的公式来计算:程序计数器PCPC寄存器的值跳转地址偏移量*4这样,程序的指令数可达232,从而解决了条件转移指令的跳转地址大小问题。这种方式的跳转寻址称为PC相对寻址(PC-relativeaddressing)。,PC-relativeaddressing(PC相对寻址),PC,PC+4,BNE$t1,$t2,SKIP,低地址,高地址,-32768,PC相对寻址方式条件转移地址的计算公式,PC=(PC+4)+地址偏移x4因为执行bne指令时,取值操作已经完成,PC已经加了4,所以新的PC值等于:PC+4。,例如:100:bne$s0,$s1,Exit104:add$t1,$t2,$t3108:Exit:sub$t1,$t2,$t3假设$s0$s1,那么指令执行后PC=?,【解答】如果$s0$s1则PC=104+(offset)x4=104+1x4=108,例3-17:展示机器语言中的转移地址偏移量,例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=20000。,2,20000,三、MIPS的寻址方式(addressingmode)总结,1.寄存器寻址(registeraddressing):操作数都在寄存器中。2基地址寻址或偏移量寻址(baseordisplacementaddressing):有一个操作数在内存中,其地址是指令中的一个寄存器和指令中常量的值之和。3.立即数寻址(immediateaddressing):有一个操作数是在指令中的常量。4.PC相对寻址(PC-relativeaddressing):地址是PC和指令中常量*4的值之和。5.伪直接寻址(pseudodirectaddressing):地址是指令中的26位地址*4,同PC的高4位连接起来的32位,也即32位字节地址。,四、机器语言的解码,例3-18写出下面的机器指令对应的汇编语言:【解答】第一步是根据op域,确定这是什么指令。从表3.5可以查到,31-26位为00000,该指令是R-format的指令。然后按照R型指令格式把该机器指令重写一遍:oprsrtrdshamtfunct00000000101011111000000000100000再判断具体是什么操作:5-0位为100000,正好是add指令。最后看看其它域的值,rs、rt、rd的十进制值分别是5、15、16,说明对应的寄存器分别是$a0、$t7、$s0。这时就可以写出该机器指令对应的汇编指令:add$s0,$a0,$t7,本章小结,存储程序式的计算机的两条基本原理是,指令像数字一样表示,程序在内存能象数据一样读写。指令集的设计,必须能够很好地平衡执行程序所需指令数,每条指令所需时钟周期,以及时钟的速度这3个因素。以下4条设计原则对于实现指令集的这种平衡起着指导作用:1.规整化简化硬件。(Simplicityfavorsregularity.)规整化促进了MIPS指令集的以下特性的形成:保持所有指令的大小相同,在算术指令中总是需要3个寄存器操作数,保持每种指令格式中的寄存器域在同一位置。2.越小越快。(Smallerisfaster.)对速度的要求正是MIPS选择32个寄存器而不是更多的寄存器的原因。3.好的设计需要折衷考虑。(Gooddesigndemandsgoodcompromises.)在MIPS中的例子就是,在指令中提供更大的地址和常量的要求,与保持所有指令的长度相同的要求之间的折衷。4.常见的情况要快。(Makethecommoncasefast.)例如,在MIPS中,条件转移指令使用PC相对寻址,常量操作数使用立即数寻址。,3.9程序的运行过程,运行程序的第一步是编译,高级语言程序比汇编语言程序所用代码行要少得多,从而效率也高得多。但机器不能直接识别高级语言程序,它需要编译器将把C程序转换成汇编语言程序,即机器能理解的符号指令形式。1975年前,很多操作系统和汇编器都是用汇编语言写的,因为那时候的内存容量很小,编译器的效率也不高。如今内存容量大大提高了,从而减少了对程序大小的限制;编译器经优化后产生的汇编语言程序,可以比得上汇编语言专家所写的程序,对于一些大程序,甚至比专家写的更好。这使得高级语言和编译器得到了广泛的应用。,汇编:汇编语言是计算机提供给高层软件的一个接口,伪指令(pseudoinstruction),它们不需要在硬件上实现,但汇编语言有了这些指令,可以简化编程和汇编的过程。move$t0,$t1寄存器$t0获得$t1的值(伪指令)汇编器把它转换成与下面这条指令等价的机器语言:add$t0,$zero,$t1寄存器$t0获得0+$t1的值汇编器的主要任务是把汇编语言翻译成机器代码。它把汇编语言的程序转换成目标文件(objectfile),该文件包括机器语言指令、数据,以及把指令正确放在内存中所需的信息。汇编器还必须确定所有标号的地址。它把这些标号放在一个符号表(symboltable)中,每个标号对应一个地址。,Unix系统的目标文件通常包括6个不同部分:1.目标文件报头(ojectfileheader):描述目标文件其它部分的大小和位置。2.正文段(textsegment):包含机器语言代码。3.数据段(datasegment):包含程序用到的数据,其中包括静态数据和动态数据。4.重定位信息(relocationinformation):对取决于绝对地址的指令字和数据字进行标识,以便程序装入内存中时进行重定位。5.符号表(symboltable):包含没有定义的标号,如外部引用。6.调试信息(debugginginformation):对汇编模块的简单描述,以便调试器可以把机器指令同C语言源文件联系起来,使数据结构具有易读性。,3.9.3链接目标代码,链接编辑器(linkeditor)或链接程序(linker),它把独立汇编后产生的所有机器语言程序“缝合”在一起。链接程序需要3个步骤来完成它的使命:1.把代码模块和数据模块放在内存中。2.确定数据和指令标号的地址。3.修正内部和外部的引用。链接程序在每个目标模块中使用重定位信息和符号表来处理所有未定义的标号,这些引用发生在branch指令、jump指令和数据地址中。因此链接程序就如同一个编辑器,它找到旧的地址,并用新地址来代替。使用链接程序的一个重要原因就是,修补代码比重新编译和重新汇编要快得多。,堆栈指针初始化为7ffffffchex,程序代码的起始地址为00400000hex静态数据起始地址为10000000hex动态数据起始地址紧邻着静态数据,向上增长全局指针$gp被初始化为10008000,以$gp为基地址,使用16位偏移量(正负),就可以存取从10000000hex到1000ffffhex的范围。,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=vk;vk=vk+1;vk+1=temp;编写MIPS汇编代码一般遵循以下步骤:1.为子程序中的变量分配寄存器。2.为子程序体产生代码。3.保护寄存器,以免其内容在子程序调用之间受到破坏。,第一步:为swap子程序分配寄存器由于swap只有两个参数v和k,它们就分别放在参数寄存器$a0和$a1中。只有一个临时变量,用$t1.第二步:为swap子程序体产生代码C语言中int型变量是4个字节长,MIPS是按字节寻址的,因此索引k要乘以4再参与地址运算(在用汇编语言编程时,很多人往往忘记这一点,这点需要加倍注意),3.10.2子程序sort,子程序sort,它对一个整数数组的元素进行排序。它要调用前面的swap子程序。sort(intv,intn)inti,j;for(i=0;i=0,3.11数组和指针的比较,对使用数组及数组索引的汇编代码与使用指针的汇编代码进行比较,便于理解指针的用法和优点.clear1(intarray,intsize);用数组下标编写清0inti;for(i=0;isize;i=i+1)arrayi=0;clear2(int*array,intsize);用指针编写清0int*p;for(p=,loop1:add$t1,$t0,$

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论