今天折腾了一天的ubuntu windows双系统,在windows下安装ubuntu 16.04 而后 安装引导启动器的时候选择的是/boot所在的sda12 每次除非开安全启动,不然就无法进去系统,如今在 Try Ubuntu 下修复了一次以后 开机出现一个 grub>的命令行工具,之前是直接开机一个 DHCP: \的东西,好麻烦啊,并且按照教程 grub>下选择了 (hd0,0)这种东西,也无法˙从C盘启动啊。心疼,如今试试try Ubuntu下的自动修复工具,还不行我就放弃了。直接把原来的盘删除,而后转回ntfs格式算了,虚拟机就虚拟机吧!程序员
一、过程或者函数是程序员进行结构化变成的工具,在过程(子程序)运行时,程序必须遵循如下6个步骤:ubuntu
二、结合上面的子程序的说法,咱们知道在计算机中是寄存器的数据存取能力最快,因此咱们但愿尽可能的多在寄存器中进行任务,那么就有了以下几个寄存器的分配windows
$a0~a3
四个寄存器用于传递参数进去;$v0~v1
用于返回值的两个寄存器;$ra
用于返回起始点的返回地址寄存器。三、除了寄存器外,MIPS 还包括一条过程调用指令【
jal Index
】:跳转到子程序的地址而且把当前位置所在的下一条指令位置存入ra
寄存器中,以用于子程序执行完后的返回 .安全
为了支持这种状况,MIPS还使用了寄存器跳转指令 jr 用于case语句,表示无条件跳转到寄存器所指定的地址:jr $ra
。因此,综上咱们就有了以下的定义:调用程序称为调用者caller,被调子程序称为被调用者 callee。caller 把参数放入$ a0 ~ a3
而后使用jal X 调到callee位置,而后callee执行完毕后把返回值放到$ v0 ~ v1
而后再用jr $ra
跳回到caller的位置。jr
实际上就是PC+4这个位置保存到了ra
寄存器中。(PC是程序计数器的意思。不论是哪儿我感受都是简写为PC,就是说,这个东西指在当前程序执行的指令的位置。)bash
四、若是咱们要使用更多寄存器?数据结构
不存在的。那就只能放到存储器中了。而后在寄存器中的一个放入存储器的地址,而后每次调用一波~。这个时候最理想的数据结构的是栈。至于什么是栈,please call baidu ~ ,因为使用普遍,因此MIPS就把29号寄存器给了栈,$ sp
就是栈指针,放入数据称为压栈,取出称为出栈。另外,栈指针是从高处往低处走,因此压入数据会致使指针位置编号变小。函数
五、减小寄存器数据换出的约定工具
$t0 ~ t9
是十个临时寄存器,过程调用中没必要被调用者(被调用的子程序)保存;$ s0 ~ s7
是八个保留寄存器,过程调用中必须被保存(一旦被使用,就要由被调用者进行保存和恢复)。六、上述内容过一遍以后,咱们就能够揣测一个嵌套的过程,好比递归,本身调用本身这种用法!编译一个递归C的过程,而且用MIPS表示出来:测试
我总结下,从第一个fact开始,每个fact都会保存当前的指令下一条的位置和当前的n值到栈中,具体的表现就是addi $sp,$sp,-8;
栈的长度增长了2个“字”而后比较当前的n值(保存在$a0
中)是否小于1,若是小于那么$t0
就等于1,不小于就等于0,而后把$t0
与0
进行比较,若是等于就跳转到L1,否则就接着往下跑,因此若是跳到L1,就会对$a0
内保存的n值执行-1的操做,而后继续跳回到fact
进行对n的检查。可是若是不跳到L1,也就是说达到中止条件了,那么就会忽略beq那一句往下跑,开始从栈顶抛出数据,同时对返回把$v0
修改成$v0*$a0
,此处也就是fac(n)=(n-1)*n
;而后无条件跳转到上一个调用程序fact的下一步,直到结束!ui
int fact(int n)
{ if(n<1) return 1;
else return(n*fact(n-1));
}
//转换为MIPS的代码以后以下:
//以过程标签为开始,栈顶保存两个寄存器,一个是返回地址,另外一个是$a0
fact:
addi $sp,$sp,-8;
sw $ra,4($)sp;
sw $a0,0($sp)
//第一次调用的时候sw保存程序中调用fact的地址,而后指令测试n是否知足结束条件小于1
slti $t0,$a0,1;
beq $t0,$zero,L1;
//若是n小于1,那么fact就把1置入一个寄存器及而且返回。
addi $v0,$zero,1;
addi $sp,$sp(8);
jr $ra;
//在从栈中退出两个内容以前,本应该加载$a0 和$ra 可是因为n小于1的时候,两个寄存器的内容不会有变化因此就跳过了上面的指令,若是n不小于1,那么n-1后传入fact中继续调用fact:
L1:
addi $a0,$a0,-1;
jal fact;
//下一条指令时fact的返回位置,从栈顶开始抛出数据(抛出数据的时候指针的位置序号会变大,前面说过的)
lw $a0,0($)sp;
lw $ra,4($sp);
addi $sp,8;
//接下来,返回值寄存器$v0获得原来的n-1的参数与当前的返回内的数据进行相乘:
mul $v0,$a0,$v0;
//最后 fact 跳转到返回地址;
jr $ra;复制代码
七、MIPS汇编语言的寄存器约定,加速大几率事件的思想重要体现
八、J型跳转指令,由于MIPS中每个操做指令的长度都是4字节,因此其实能够用字来表示单位,也就是说,当即数若是为20000,那么实际跳转的长度就是80000byte,也就是20000个“字”,这样一来咱们的跳转返回就能够增长4倍,另外,咱们用“
PC
相对寻址”的时候吗,其跳转基准是以PC+4
为基准的,也就是说,你跳转的距离是相对于下一条指令来讲的!这一点尤其重要,后面会讲到!另外,采用PC
跳转寻址是一种加速大几率事件的思想的体现!由于条件跳转有一半都是跳转到PC+4
的十六个指令范围内。
谁来救我!!!Ubuntu双系统要搞死我了!!!引导修复要搞死我了。天哪。待我计算机组成原理大成之日,就是个人dell电脑身死道消之时!!!在此立誓!!!