
微机原理 MIPS汇编程序设计 MIPS汇编程序设计.pdf
62页2010-10-10 1MIPS汇编语言程序设计LD(R31,x,R0)BNE(R0,skip,R31)LD(R31,y,R1)ADDC(R1,1,R1)ST(R1,y,R31)skip:...$%$^$&&$&$if(x==0)y=y+1;2010-10-10 2汇编程序设计思路01010110001110001001010010…2 汇编3 编译器4 典型程序结构及汇编语言设计1 机器语言图灵机模型无限长纸带读写头 {图灵机只要根据每一时刻读写头读到的一个方格的信息和当前的内部状态对程序进行查表,就可以确定下一时刻的内部状态和输出动作了 {具体的程序是一个列表,也叫做规则表回忆一下: 我们已经有了UTM的思想2010-10-10 4回忆一下: 我们已经有了UTM的思想我们的任务是计算所有的可计算的整数函数1:Tu查看Tape2和Tape3来决定图灵机的配置Tk(采用第k个图灵机)及它的输入j;2:Tu查看第一个磁带Tape1决定Tk会怎么做;3:修改磁带2和3以反映Tk (j)在计算过程中的动作和内部状态变化;2010-10-10 5解释:InterpretationTuring的解释器模型:•首先是有一个与问题无关的通用机器UTM; M1•为M1编写一个简单的程序使得M1完成一个简单的功能M2;•M1和程序Pgm一起变成了一个虚拟的(Virtual)M2;解释的层次:•在计算机中通常我们会使用多个不同层次的解释器来实现我们想要的行为,例如:•X86(pentium)上面运行着•Java VM上面又运行着•应用程序比如ant•数据结构比如走迷宫的蚂蚁2010-10-10 6编译器编译器的模型: 9给定一个UTM M1; 9寻找一个比较容易写的语言L2(比如是为了机器M2设计的)并写一段程序; 9编写一个Translator使得这个Translator可以将M2的语言转换为M1的语言Interpretation & Compilation: 两个不同的提高可编程性的方法. 9都容许改变我们的编程的模型 9都可以提供一种与平台(如处理器)无关的编程语言; 9都是在现代的计算机系统中被广泛采用2010-10-10 7Interpretation与Compilation这两种强有力的工具也有区别:我们以后会经常遇到的一个关键问题:是在运行时实现还是在编译时实现?Interpretation Compilation如何对待” x+2”计算x+2产生一个可以计算x+2的程序什么时候计算在执行过程中在执行之前什么代价(使什么变慢)程序执行时间程序的开发时间结果在什么时候确定运行时编译时2010-10-10 8MIPS汇编器:语法 {注释行以“#”开始; {标识符由字母、下划线(_)、点(.)构成,但不能以数字开头,指令操作码是一些保留字,不能用作标识符; {标号放在行首,后跟冒号(:),例如.data #将子数据项,存放到数据段中Item: .word 1,2 #将2个32位数值送入地址连续的内存字中.text #将子串即指令或字送入用户文件段.global main #必须为全局变量Main: lw $t0, itemMIPS汇编中的命令见Page6252010-10-10 9MIPS汇编器:存储器中位置 {汇编语言源文件:.s {特殊符号“.” (点): 表示当前位置 z “.” MIPS汇编命令标识符 z “label:” { label被赋值为当前位置的地址 { Fact = 0x00400100 z编译时就确定了 {汇编程序在地址0x00400000开始 z在LW,SW, BEQ, BNE等指令中都有应用move $s5, $31beq$0,$0,fact sw$s0,f($0) .text 0x00400100 fact: addiu$s0,$0,1lw$s1, n($0)loop: mul$s0,$s1,$s0subu$s1,$s1,1bnez$s1,loopaddi$31,$s5,4jr$31.data 0x10000200n: .word 4f: .word 00x004000200x004000240x00400028…0x004001000x004001040x004001080x0040010C0x004001100x004001140x00400118…0x100002000x100002042010-10-10 10能运行的版本(1):.textmain:addu $s3,$ra,$0ori $s6,$0,0x1000sll $s6,$s6,16addiu $s4,$s6,0x0200addiu $s5,$s6,0x0204addiu $s7,$s6,0x0208 #$s4=n, $s5=f#$s7为$ra开辟一个地址空间beq $0,$0, factresult: sw $s0,0($s5) addu $ra,$s3,$0jr $ra.text 0x00400100fact:sw $ra,0($s7)addiu $s0,$0,1lw $s1,0($s4) #$s0=n!loop: mul $s0,$s1,$s0subu $s1,$s1,1bnez $s1,loop #f=n!j result.data 0x10000200n: .word 4f: .word 02010-10-10 11.data 0x10000000 .word 4,0.textmain:addu $s7,$ra,$0ori $s6,$0,0x1000sll $s6,$s6,16addiu $s5,$s6,0x04fact: addiu $s0,$0,1lw $s1,0($s6)loop: mul $s0,$s1,$s0subu $s1,$s1,1bnez $s1,loopsw $s0,0($s5)addu $ra,$0,$s7jr $ra#下列语句行是数据代码行#定义了两个字型立即数4和0#下列语句行是指令代码行###$s6=0x10000000#$s5=0x10000004# ##$s0=n!, n=4###f=n!=24#退出子程序#根据ra寄存器中的返回地址返回test1能运行的版本(2)2010-10-10 12编程指南(1)变量(2)分支(3)数组(4)过程调用(5)阅读、改进程序单指令计算机2010-10-10 13编程指南:(1)变量 {变量存储在主存储器内(而不是寄存器内) z因为我们通常有很多的变量要存,不止32个 {为了实现功能, 用LW 语句将变量加载到寄存器中, 对寄存器进行操作, 然后再把结果SW回去 {对于比较长的操作(e.g., loops): z让变量在寄存器中保留时间越长越好 z LW and SW 只在一块代码开始和结束时使用 z saves on instructions z also, 事实上LW and SW 比寄存器操作要慢得多得多! {由于一条指令只能采用两个输入,所以必须采用临时寄存器计算复杂的问题e.g., (x+y)+(x-y)2010-10-10 14编程指南:(1)变量.data 0x10000000 .word 4,0.textmain: addu $s7,$ra,$0ori $s6,$0,0x1000sll $s6,$s6,16addiu $s5,$s6,4fact: addiu $s0,$0,1lw $s1,0($s6)loop: mul $s0,$s1,$s0subu $s1,$s1,1bnez $s1,loopsw $s0,0($s5)addu $ra,$0,$s7jr $ra#s1 get 4#s0 hold result#return result in s02010-10-10 15编程指南:(2)分支 {在符号汇编语句中,分支语句的目标位置是用绝对地址方式写的 z e.g., beq $0,$0,factmeans PC ← 0x00400100 {不过在实现中,要用相对于PC的地址来定义 z e.g., beq $0,$0,0x3fmeans PC ← 0x00400100.textmain: addu $s3,$ra,$0ori $s6,$0,0x1000sll $s6,$s6,16addiu $s4,$s6,0x0200addiu $s5,$s6,0x0204 addiu $s7,$s6,0x0208 beq $0,$0, factresult: sw $s0,0($s5) addu $ra,$s3,$0jr $ra.text 0x00400100fact: sw $ra,0($s7)addiu $s0,$0,1lw $s1,0($s4) #$s0=n!loop: mul $s0,$s1,$s0subu $s1,$s1,1bnez $s1,loop #f=n!j result .data 0x10000200n: .word 4f: .word 02010-10-10 16分支语句中的偏移量的使用 {偏移量=从下一条指令对应的PC开始到标号位置还有多少条指令 z e.g., beq $0,$0,fact如果位于地址0x00400000的话,word displacement=(target - (+4)) / 4=(0x00400100-0x00400004)/4=0xfc/4=0x3f z偏移量为0则表示执行下一条指令不产生任何跳转 {为什么在代码中用相对的偏移量? z relocatable代码(可重新定位的) z分支语句可以在每次被加载到内存不同位置的情况下正常工作2010-10-10 17分支:返回地址与Jr {记得: BEQ和BNE默认$31寄存器获得的是下一个next-PC z e.g., in beq $0,$0,factR31 gets 0x0040001c {此即返回地址return-address这样我们有一天还可以跳回来~这很重要! z e.g., jr $31我们就回到了0x0040001c.textmain: addu $s3,$ra,$0ori $s6,$0,0x1000sll $s6,$s6,16addiu $s4,$s6,0x0200addiu $s5,$s6,0x0204 addiu $s7,$s6,0x0208 beq $0,$0, factresult: sw $s0,0($s5) addu $ra,$s3,$0jr $ra.text 0x00400100fact: sw $ra,0($s7)addiu $s0,$0,1lw $s1,0($s4)#$s0=n!loop: mul $s0,$s1,$s0subu $s1,$s1,1bnez $s1,loop #f=n!j result .data 0x10000200n: .word 4f: .word 00x004000000x004000040x004000080x0040000c0x004000100x004000140x004000180x0040001c…0x004001000x004001040x00400108…0x100002000x100002042010-10-10 18编程指南:(2)分支 {分支 z如果和0比较, 则直接使用blez,bgez,bltz,bgtz,bnez {e.g., loop example before z更复杂的比较, 采用比较指令(如slt), 然后再用与0比较 { Example: if ( x >= 。
