計算機組成原理-匯編語言程序設計_第1頁
計算機組成原理-匯編語言程序設計_第2頁
計算機組成原理-匯編語言程序設計_第3頁
計算機組成原理-匯編語言程序設計_第4頁
計算機組成原理-匯編語言程序設計_第5頁
已閱讀5頁,還剩15頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

計算機組成原理實驗》實驗報告實驗二)學院名稱:數據科學與計算機學院專業(班級):學生姓名:學 號時 間:2019年10月19日成績:實驗二:MIPS匯編語言程序設計實驗實驗目的初步認識和掌握MIPS匯編語言程序設計的基本方法;熟悉QEMU模擬器和GNU/Linux下x86-MIPS交叉編譯環境的使用。實驗內容我的題目為31%4+1,第四題。【密碼】編寫一個程序,先從鍵盤輸入一個字符串(有英文字母,可能也有數字),然后顯示其中數字符的個數、英文字母的個數和字符串的長度;字符串中不能有空格,若有將其刪除,并將改變后的字符串按相反的順序顯示出來;輸入第二個字符串,然后將輸入的字符串與前面處理后的字符串比較是否相同,若相同,輸出'PasswordRight!”,否則輸出“PasswordError!”。實驗器材PC機一臺,裝有Linux操作系統的虛擬機一套,QEMU模擬器軟件一套,GNU跨平臺交叉編譯環境一套。實驗過程與結果說明:根據需要書寫相關內容,如:程序流程圖、設計的思想與方法、分析、實驗步驟和實驗結果及分析等。1、程序流程圖首先,遍歷輸入字符串并記錄字符串長度,字母個數,數字個數,并把非空格字符存到分配好的空間。

然后,逆轉字符串并再存入另一個空間。隨后再讀入一個字符串,判斷兩者是否相等。是是否否兩個宇符是否相等商個宇符串長度是否相等兩個字符串不相等按順序遍歷兩個字符串 是是否否兩個宇符是否相等商個宇符串長度是否相等兩個字符串不相等按順序遍歷兩個字符串 *逆轉宇符串如果相等就輸出PasswordRight!,否則輸出PasswordError!2、可能用到的指令lb/lh/lw:從存儲器中讀取一個byte/halfword/word的數據到寄存器中?如lb$1,0($2)sb/sh/sw:把一個byte/halfword/word的數據從寄存器存儲到存儲器中?如sb$1,0($2)add/addu:把兩個定點寄存器的內容相加add$1,$2,$3($1=$2+$3);u為不帶符號加。addi/addiu:把一個寄存器的內容加上一個立即數add$1,$2,#3($1=$2+3);u為不帶符號加。sub/subu:把兩個定點寄存器的內容相減。and/andi:與運算,兩個寄存器中的內容相與and$1,$2,$3($1=$2&$3);i為立即數。or/ori:或運算。xor/xori:異或運算。beq/beqz/benz/bne:條件轉移eq相等,z零,ne不等。j/jr/jal/jalr:j直接跳轉;jr使用寄存器跳轉;slt/slti/sltui:如果$2的值小于$3,那么設置$1的值為1,否則設置$1的值為0。sit$1,$2,$3。mov/movz/movn:復制,n為負,z為零。mov$1,$2;movz$1,$2,$3($3為零則復制$2到$1)。本實驗主要涉及字符串和字符的操作,此外還涉及到計數。所以一般使用lb/sb和1w/sw來解決寄存器存儲數據空間不足的情況。本實驗涉及判斷單個字符的類型,需要用到大小比較。我使用sit/slti和beq/beqz/benz/bne來跳轉。另外,必須用到的還有加減法、寄存器賦值、邏輯運算等指令。3、設計流程首先我們為輸入字符串和操作后的字符串分配內存空間,分配:origin_str:.space1000#原始輸入字符串nospace_str:.space1000#去除空格后的字符串reversed_str:.space1000#翻轉后的字符串然后分配存儲計數的整形變量的內存空間:str_len:.word0#字符串長度num_let:.word0#字母字符數量num_dig:.word0#數字字符數量打印特定的字符串使用syscall4,預設一些可能用到的asciiz字符串。輸入字符串使用syscall8,需要把目的地址放入寄存器,如下:la$a0,strli$a1,100li$v0,8syscall遍歷字符串取字符的操作可以使用不斷自增當前地址+尋址的方式進行:loop:lb$t2,($t0)add$t0,$t0,1#$t0地址加一jloop題目涉及連續判斷的條件。判斷大于和小于都可以通過siti和slt來進行,只需要顛倒寄存器的位置即可。對連續判斷條件,可以分別計算并作邏輯運算,例如,判斷字符是不是數字:slti$t6,$t2,58#$t2<'9'+1時置位slti$t7,$t2,48#$t2<'0時置位nor$t7,$zero,$t7#$t7取反and$t6,$t6,$t7#$t6='0'<=$t2<='9beq$t6,1,adddigit需要一個取反操作,或者把48放入寄存器中。類似的,判斷是不是字母,是不是空格也使用類似的方法。循環過程中進行存數操作,每次存一個字節然后地址增加一個字節。save1:sb$t2,($t5)addi$t5,$t5,1jjudge遍歷結束后,使用另一塊空間把字符串作逆轉,使用C代碼的指針實現如下。char*p1=str;char*p2=reversed_str+length-1;while(*p1!=0){*p2=*p1;p2--;p1++;}指針可以直接用地址代替,使用MIPS匯編實現如下:reverse:la$t0,nospace_strla$t1,reversed_stradd$t2,$t3,$t4#$t2=nospace_str字符串的有效長度#做一個t2次的循環,不斷存字節使(reversed_str+$t2-i-1)=i(nospace_str)add$t1,$t1,$t2addi$t1,$t1,-1li$t3,0loop:beq$t3,$t2,Retypeadd$t4,$t3,$t0lb$t5,($t4)sub$t6,$t1,$t3sb$t5,($t6)addi$t3,1jloop

然后再次輸入一個字符串,比較兩個字符串是否相等。如流程圖所示,先判斷長度相等與否,再判斷每個字符的相等與否。length_equal:la$t0,num_letlb$t2,($t0)la$t0,num_diglb$t3,($t0)add$t2,$t2,$t3bne$t1,$t2,not_equalla$t0,origin_strla$t1,reversed_strli$t3,0if_equal:beq$t2,$t3,equallb$t4,($t0)lb$t5,($t1)bne$t4,$t5,not_equaladd$t0,$t0,1add$t1,$t1,1add$t3,$t3,1jif_equalnot_equal:li$v0,4la$a0,errorsyscalljexitequal:li$v0,4la$a0,rightsyscallexit:li$v0,10#退出syscall#系統調用如果都相等就打印right,否則打印error。先使用PCSPIM進行調試,在修改了部分bug后模擬結果如下。0Console — □X^Inputstring:abcdefgh123ijkl^StringLength:17.Nluinberofletters:3:Nlumberofdigits:121ReversedString:lkj132lhgfedchaRetype:lkji32lhgf&dcba'PasswordRight!圖1輸入正確時的程序輸出0匚onsole — □XInputstring:huangwK8StringLength:9NTumberofletters:1KTuinberofdigits:7ReversedString:aswgnauhRetype:Shu.ztngwxPasswordErrorI圖2輸入錯誤時的程序輸出可以看到基礎的功能都得到實現,嘗試在x86環境下匯編鏈接代碼并生成MIPS可執行文件,隨后使用QEMU來運行。QEMU和PCSPIM的不同點在于使用的是linux內核調用,所以與syscall相關的代碼必須得到修改。此外,由于寫整數的接口無法使用,我們需要自己實現一個把整數轉換為字符串的函數,用于打印該整數。基本思路還是把整數不斷除10,把余數放入對應的地址,如下:#打印一個整數的代碼,整數保存在t1中,返回地址保存在ra中Printint:#先確定該整數長度la $t0, int_strTOC\o"1-5"\h\zli $t2, 10li $t4, 0move $t3, $t1get_int_len:div$t3,$t2 除#10mflo$t3

add $t4,$t4,1bnez$t3,get_int_lenadd$t5,,$t0,$t4sb $zero,($t5)置末尾為0addi$t4,,$t4,-1assign:blt$t1,$t2,saveint如果t1小于10div$t1,$t2除10mflo$t1商#mfhi$t3余#數addi$t3,$t3,48#acsi碼add$t5,$t0,$t4#七為存字節的地址sb$t3,($t5)存數addi$t4,$t4,-1調整地址jassign循環saveint:addi$t1,$t1,48#acsi碼add$t5,$t0,$t4#七為存字節的地址sb$t1,($t5)存數printStr:li$a0,1la$a1,int_strli$a2,100li$v0,4004syscalljr $ra這樣我們用jal調用它時,就可以直接打印出$t1中的整數了。自此程序設計環節完成。4、實驗測試結果與分析嘗試在1inux虛擬機上運行這段程序的MIPS可執行文件,并使用不同的輸入例來尋找程序的不足。基礎輸入例使用例子中的輸入,查看到輸出如下:sysu^debian:^./pwInputstring:abcdefghl23ijklStringLength:17Numberofletters:3Numberofdigits:12ReversedString:lkji321hgfedcbaRetype:lkji321hgfedcbaPasswordRight! 0__I I ! 圖3QEMU的執行結果1符合我們的預期,再嘗試一下其他的測試例。長度不同的輸入例查看到輸出如下:sysuOdebian:^./pwInputstring:huangwx8StringLength:9Numberofletters:1Numberofdigits:1ReversedString:SxwgnauhRetype:EixwgnauhePasswordError!圖4QEMU的執行結果2長度相同字符不同的輸入例查看到輸出如下:Inputstring:huangwxSStringLength:3Numberofletters:1Numberofdigits:1ReversedString:SxuugnauhRetype:3xuugnauhPasswordError!圖5qemu的執行結果3全都是空格的輸入例輸出如下:Inputstring:StringLength:5Numb已『ofJ.已tt已rs:0Numberofdigits:0ReversedString:Retype:PasswordError!圖6QEMU的執行結果4可見程序已經能夠實現我們題目中給定的邏輯,并能應對一些特殊情況。實驗心得實驗的主題是使用MIPS匯編進行程序設計,應該說MIPS匯編的難度比起X86要小了很多。比起X86它擁有更靈活的跳轉語句,由此可以帶來更精簡的循環和遞歸調用;算術和邏輯運算的數據傳輸也變得更清晰;此外還有比較容易的變量空間分配和聲明。用MIPS來做程序設計是一個很好的提升自己的過程。實驗中要實現的功能很簡單,如果使用C++等高級語言很快就能實現,但當我們只能使用純粹的匯編碼時,難度就上升了一個等級。原本方便的數據類型、循環等操作都要用匯編碼和編譯器實現,體驗上和高級語言的設計過程有很大的不同。實驗的另一個特點就是要在linux環境下用QEMU進行模擬。QEMU的環境和普通的MIPS環境有所不同,這要求我們靈活地進行代碼修改和系統功能的調用。對我的題目,需要設計itoa的匯編代碼,對別的題目可能還需要atoi的函數。這種擴展性的問題有助于我們提升資源有限情況下的解決問題能力。總之,本實驗通過匯編程序設計,不僅能夠提升我們的編程能力,更能加深我們對機器碼的運行原理,內存空間和數據的關系,以及編譯器、計算機硬件和操作系統之間的交互和協同工作關系的理解。【程序代碼】.dataorigin_str:.space1000#原始輸入字符串nospace_str:.space1000#去除空格后的字符串reversed_str:.space1000#翻轉后的字符串int_str:.space100 #用于儲存整形的字符串input:.asciiz"Inputstring:"stringlength:.asciiz"StringLength:"letternum:.asciiz"Numberofletters:"digitnum:.asciiz"Numberofdigits:"reversedstr:.asciiz"ReversedString:"retype:.asciiz"Retype:"right:.asciiz"PasswordRight!\n"error:.asciiz"PasswordError!\n"endl:.asciiz"\n"str_len:.word0#字符串長度num_let:.word0#字母字符數量num_dig:.word0#數字字符數量.text.globalmainmain:li$v0,4004li$a0,1la$a1,input#提示輸入字符串li$a2,14syscallli$a0,0la$a1,origin_str#a0=原始字符串地址li$a2,900li$v0,4003syscallla$t0,origin_str#使用寄存器保存三個計數li$t1,0li$t3,0li$t4,0la$t5,nospace_str#循環,計數字符串長度,字母和數字個數#并把除空格以外的字符錄入nospace_strcount:lb $t2, ($t0)beq $t2, 0,endcount #結束count循環li $t6, 32bne $t6, $t2,savel # $t2!=''時存字符到nospace_strjudge:add$t0,$t0,1#$t0地址加一add$t1,$t1,1#字符串長度加一slti$t6,$t2,58#$t2〈'9'+1時置位slti$t7,$t2,48#$t2<'0'時置位nor$t7,$zero,$t7#$t7取反and$t6,$t6,$t7#$t6='0'<=$t2<='9'beq$t6,1,adddigitslti$t6,$t2,91#$t2〈'Z'+1時置位slti$t7,$t2,65#$t2<'A'時置位nor$t7,$zero,$t7#$t7取反and$t6,$t6,$t7#$t6='A'<=$t2<='Z'beq$t6,1,addletterslti$t6,$t2,123#$t2〈'z'+1時置位slti$t7,$t2,97#$t2<'a'時置位nor$t7,$zero,$t7#$t7取反

and$t6,$t6,$t7#$t6='A'<=$t2<='Z'beq$t6,1,addletterjcountsavel:#存數sb$t2,($t5)addi$t5,$t5,ljjudgeadddigit:#數字字符計數加一add$t3,$t3,ljcountaddletter:#字母字符計數加一add$t4,$t4,ljcount#打印一個整數的代碼,整數保存在tl中,返回地址保存在ra中Printint:#先確定該整數長度la$t0,int_strli$t2,l0li$t4,0move$t3,$tlget_int_len:div$t3,$t2#除10mflo$t3add$t4,$t4,1bnez$t3,get_int_lenadd$t5,$t0,$t4sb$zero,($t5) #置末尾為0addi$t4,$t4,-1assign:blt$t1,$t2,saveint#如果tl小于10div$t1,$t2#除10mflo$t1#商mfhi$t3#余數addi$t3,$t3,48#acsii碼add$t5,$t0,$t4#t5為存字節的地址sb$t3,($t5)#存數addi$t4,$t4,-1#調整地址jassign#循環saveint:addi$t1,$t1,48#acsii碼add$t5,$t0,$t4#t5為存字節的地址sb$t1,($t5)#存數printStr:li$a0,1la$a1,int_strli$a2,100li$v0,4004syscalljr$raendcount:la$t0,str_lenaddi$t1,$t1,-1#輸入的origin_str最后一個字符為\n,所以長度要減一TOC\o"1-5"\h\zsw $t1, ($t0)la $t0, num_letsw $t3, ($t0)la $t0, num_digsw $t4, ($t0)li$v0,4004#打印stringlength的一行li$a0,1la$a1,stringlengthli$a2,15syscallla$t0,str_lenlw$t1,($t0)jalPrintintli$v0,4004li$a0,1la$a1,endlli$a2,1syscallli$v0,4004#打印letternum的一行li$a0,1la$a1,letternum

li$a2,19syscall#打印整形la$t0,num_letlw$t1,($t0)jalPrintintli$v0,4004li$a0,1la$a1,endlli$a2,1syscallli$v0,4004#打印digitnum的一行li$a0,1la$a1,digitnumli$a2,18syscall#打印整形la$t0,num_diglw$t1,($t0)jalPrintintli$v0,4004li$a0,1la$a1,endlli$a2,1syscallreverse:#逆向字符串la$t0,num_let

lw$t3,($t0)la$t0,num_diglw$t4,($t0)la $t0,nospace_strla $t1,reversed_stradd $t2, $t3, $t4#$t2=nospace_str字符串的有效長度TOC\o"1-5"\h\z#做一個t2次的循環,不斷存字節使(reversed_str+$t2-iT)=i(nospace_str)add $t1, $t1, $t2addi $t1, $t1, -1li $t3, 0loop:#循環,直到到達有效長度beq$t3,$t2,Retypeadd$t4,$t3,$t0lb$t5,($t4)sub$t6,$t1,$t3sb$t5,($t6)addi$t3,1jloopRetype:#打印reversed_

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論