Assembly Programming: 環境架設+第一次作業

前言

Mars IDE

因爲學校計算機組織會擋修,所以就去看清大的開放課程了(Link)
這一次,是個人首次接觸組合語言,MIPS的組語環境還滿容易處理,有模擬軟體
比較麻煩的是,組語的可閱讀性很低,沒有註解幾乎沒辦法馬上知道該行的功能...

環境架設

我們要撰寫的是MIPS的組合語言,使用這套“MARS"模擬器
下載後的檔案是.jar,在*NIX系統下請在終端機輸入java -jar MARS.jar來開啓檔案

開啓MARS後,新增檔案,就可以開始撰寫程式了!

run的順序是先組譯(Assemble-F3),再執行(Go-F5)或者是單步驟執行(Step-F7)
反正上面的選項沒有多少,很快就能搞定的

開始寫code

清大今年的第一次作業的第一題,題目是

輸入a, b, c, d
計算x=a+b-1, y=32*c-16*d
並將計算之x和y的結果輸出(不能使用乘法函數)
結果示範:
input a: 1
input b: 1
input c: 1
input d: 1
x = 1
y = 16

不過這邊爲了節省一些版面還有邏輯打結的時間,我們將題目簡化成

輸入a, b
計算x=32*a-16*b
並將計算之x的結果輸出(不能使用乘法函數)

下面是我的程式碼

OurCode
.data

input: .asciiz "Input "
a: .asciiz "a: "
b: .asciiz "b: "
x: .asciiz "x= "

result: .asciiz "Result: x= "

.text

#Print "Input a: "
li $v0, 4
la $a0, input
syscall
la $a0, a
syscall

#Get input from keyboard and store a into $s0
li $v0, 5
syscall
move $s0, $v0   #$s0 as a

#Print "Input b: "
li $v0, 4
la $a0, input
syscall
la $a0, b
syscall

#Get input from keyboard and store b into $s1
li $v0, 5
syscall
move $s1, $v0   #$s1 as b

#Start to caculate 32a and 16b
li $t0, 0
li $t1, 32
li $t2, 0   #$t2 as 32a
li $t3, 0   #$t3 as 16b

loop1:
add $t2, $t2, $s0
addi $t0, $t0, 1
bne $t0, $t1, loop1

li $t0, 0
li $t1, 16

loop2:
add $t3, $t3, $s1
addi $t0, $t0, 1
bne $t0, $t1, loop2

#Caculate x=32a-16b
sub $s2, $t2, $t3

#Print result
li $v0, 4
la $a0, result
syscall

li $v0, 1
move $a0, $s2
syscall

#System call for quit
li $v0, 10
syscall

下面是運行結果
Result

簡單解說

  • .data
    表示該行以下的內容,作爲記憶體配置,以input: .asciiz "Input "來看,前面的input可視爲變數(細節尚待學習),後面則表示將"Input"這段文字以ascii編碼存起來(.asciiz會在字串的尾巴加上一個NULL的結束字元)

  • .text
    表示該行以下的內容,作爲程式碼

  • 暫存器(Register)
    上課沒有睡着的話,應該都會提到
    $s0~$s7:作爲一般儲存用途
    $t0~$t7:作爲一般 暫時 儲存用途(實際上和$s暫存器並無差異,是用法上的差異)
    $a0~$a3:作爲參數(argument)
    $v0, $v1:作爲回傳數值
    剩下的這次沒用上,有些我也還沒學到

  • li $v0, NUMBER
    li=Load Immediately,將NUMBER存入$v0裏面
    這個程序是爲了接下來system call所做,$v0內的數值不同,呼叫system call時會有不同的行爲,以下是這次實作我們用上的功能

li $v0, 1:此時syscall,會print出存在$a0內的 數值
li $v0, 4:此時syscall,會print出存在$a0內 目標地址字串 (你不會把字串存在$a0,存在$a0的是地址)
li $v0, 5:此時syscall,會讀入使用者輸入的數值到$v0
li $v0, 10:此時syscall,會結束運行

  • la $a0, input
    la=Load Address,把input的地址讀入$a0中

  • loop1:
    由於這份作業限制了乘法的使用,所以必須自己建立一個迴圈來處理乘法運算
    使用$t0和$t1來計數,用bne來重複迴圈工作
    注*:我知道可以用shift的方式來達成2^n的乘法運算,不過我對於暫存器內資料是signed和unsigned,尚不是很瞭解,所以先不用該方式實作

  • 其他
    請去問老師,問課本,或是問問神奇海螺

雜談

清大黃婷婷教授的網頁,字元編碼居然是BIG5...
頗腦人

參考資料

A Minimalistic Introduction to MIPS Instruction
黃婷婷教授的授課教材

Comments

comments powered by Disqus