【計算機本科補全計劃】指令:計算機的語言(MIPS) --計算機組成原理 Part2

正文以前

今天折騰了一天的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,而後把$t00進行比較,若是等於就跳轉到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電腦身死道消之時!!!在此立誓!!!

相關文章
相關標籤/搜索