MIPS 模擬器:Mars(需要安裝java)


register: s*
使用一些function時,不去修改裡面內容的register。
ex.
sub $t0, $s0, $s1 

Printing "Hello World!"

.data
    myMessage: .asciiz "Hello World!"
.text
    li $v0, 4 # Tell system to get ready.
    la $a0, myMessage # Loading address.
    syscall # Tell system to do it.
or

Printing a Character

.data
    myMessage: .byte 'm'
.text
    li $v0, 4
    la $a0, myMessage
    syscall

Printing an Integer

.data
    level: .word 999
.text
    li $v0, 1 # Tell system to get ready (an integer or a word).
    lw $a0, level
    syscall
Output: 999

Printing a Float

.data
    PI: .float 3.14
.text
    li   $v0 , 2
    # load word coprocessor 1
    lwc1 $f12, PI
    syscall 
* $f12

Printing a double

.data
    myDouble:   .double 1.618
    zeroDouble: .double 0.0
.text
    # Loading data from the location of random memory.
    ldc1 $f2, myDouble
    ldc1 $f0, zeroDouble
    
    # Tell system to get ready.
    li $v0, 3
    
    # Print result from $f12.
    add.d $f12, $f2, $f0
    
    syscall

Adding integers and Printing it

.data
    number1: .word 5
    number2: .word 3
.text
    lw $t0, number1($zero)
    lw $t1, number2($zero)
    
    add $t2, $t0, $t1    # t2 = t0 + t1
    
    # Tell system to print a integer.
    li $v0, 1
    
    add $a0, $zero, $t2
    syscall
Output: 8

Printing an Integer by "move"

.data
    number1: .word 10
    number2: .word 8
.text
    lw $s0, number1    # s0 = 10
    lw $s1, number2    # s1 = 8
    
    sub, $t0, $s0, $s1 # t0 = s0 - s1, t0 = 10 - 8
    
    # Tell system to print an integer.
    li $v0, 1
    # move is a pseudoinstruction
    move $a0, $t0      # a0 = t0, the system prints something from the argument.
    syscall
Output: 2

Multiplying Integers

.data

.text
    addi $s0, $zero, 10
    addi $s1, $zero, 4
    
    mul $t0, $s0, $s1
    
    li $v0, 1
    add $a0, $zero, $t0
    syscall
Output: 40

More Bigger Value by Multiplying

.data

.text
    addi $t0, $zero, 20000
    addi $t1, $zero, 30
    
    # The product is in the "lo" register
    mult $t0, $t1
    
    # Move from "lo".
    mflo $s0
    
    # Display multiplication result.
    li $v0, 1
    add $a0, $zero, $s0
    syscall

Multiplying by sll

.data

.text
    addi $s0, $zero, 4
    sll $t0, $s0, 3 # multiply 2^3 = 8
    
    # Display result
    li $v0, 1
    add $a0, $zero, $t0
    syscall

Dividing by div

.data

.text
    addi $t0, $zero, 20
    addi $t1, $zero, 4
    
    div, $s0, $t0, $t1
    
    #Display result by dividing
    li $v0, 1
    add $a0, $zero, $s0
    syscall

Dividing Integers and Display Quotient/Remainder

.data

.text
    addi $t0, $zero, 33
    addi $t1, $zero, 6
    
    div $t0, $t1
    
    mflo $s0 # Quotient
    mfhi $s1 # Remainder
    
    # Display Quotient
    li $v0, 1
    add $a0, $zero, $s0 
    syscall
    
    # Display Remainder
    li $v0, 1
    add $a0, $zero, $s1
    syscall

Function

.data
    msg: .asciiz "Hi, everybody.\nMy name is Jay."
.text
    main:
        # Jump and link (Call the function)
        jal displayMessage
    
    # Tell the system that the program is done.
    li $v0, 10
    syscall
    
    # Function
    displayMessage:
        li $v0, 4
        la $a0, msg
        syscall
        
        # Go back where you call.
        jr $ra

Passing parameters into function

.data

.text
    main:
        # The a* is stroages arguments
        addi $a1, $zero, 10
        addi $a2, $zero, 5
        
        jal addNumber
        jal printInteger
    
    # Tell the system that the program is done.
    li $v0, 10
    syscall
    
    # Adding number
    addNumber:
        add $v1, $a1, $a2
    
        jr $ra
        
    # Printing Integer
    printInteger:
        li $v0, 1
        add $a0, $v1, $zero
        # or
        # addi $a0, $v1, 0
        
        syscall
        
        jr $ra

Stack

.data
    newLine: .asciiz "\n"
.text
    main:
        # setting value 10 in $s0
        addi $s0, $zero, 10
        
        
        # jump to function
        jal increaseRegiter
        
        # printing new line
        li $v0, 4
        la $a0, newLine
        syscall
        
        # printing value
        li $v0, 1
        move $a0, $s0
        syscall
    
    # Tell the system that the program is done.
    li $v0, 10
    syscall
    
    
    increaseRegiter:
        # Push
	# Move stack pointer address decrease 4 bytes
	# Because a register's content is 4-byte for MIPS.
        addi $sp, $sp, -4 
        sw $s0, 0($sp) # Write $s0's value into stack pointer address.
        
        # Do something on $s0.
        addi, $s0, $s0, 30

        # print value
        li $v0, 1
        add $a0, $zero, $s0
        syscall
        
	# Pop back to the  original location.
        lw $s0, 0($sp) # Get back the content of stack pointer address.
        addi $sp, $sp, 4 # Move stack pointer address increase 4 bytes.
        
        
        jr $ra
        
    
Output:
40
10

Nested Procedure

.data
    newLine: .asciiz "\n"
.text
    main:
         addi $s0, $zero, 10
         
         jal increaseNumber
         
         
         # print integer
         jal printInteger
         
         
    # done
    li $v0, 10
    syscall
    
    increaseNumber:
        # push
        # a register's content in MIPS is 4-byte.
        addi $sp, $sp, -8
        sw $s0, 0($sp)
        sw $ra, 4($sp)
        
        # do something on $s0
        addi $s0, $s0, 30
        
        # call printInteger
        jal printInteger
        
        
        # pop back
        lw $s0, 0($sp)
        lw $ra, 4($sp)
        
        
        addi $sp, $sp, 8
        jr $ra
        
    printInteger:
        li $v0, 1
        add $a0, $s0, $zero
        syscall
        
        # print new line
        li $v0, 4
        la $a0, newLine
        syscall
        
        jr $ra
Output:
40
10

Getting user's input with integer.

.data

.text
    # Get user's input into $v0
    li $v0, 5
    syscall
    
    # Store input integer
    # move is a pseudoinstruction
    move, $t0, $v0
    
    # print it
    li $v0, 1
    add $a0, $zero, $t0
    syscall

Getting input with the float

.data
    zeroFloat: .float 0.0
.text
    # input float
    li $v0, 6
    syscall
    
    # Display result
    lwc1 $f4, zeroFloat
    li $v0, 2
    # $f0 = $v0
    # add single precision
    add.s $f12, $f0, $f4
    syscall

Getting double value from user.

.data
    zero: .double 0.0
.text
    # get double value from user.
    li $v0, 7
    syscall
    
    # display the result
    # load double word coprocessor
    ldc1 $f2, zero
    li $v0, 3
    # $f0 := $v0
    add.d $f12, $f0, $f2
    syscall
    

Getting Text from user

.data
    # create the 20 characters size array.
    input: .space 20
.text
    main:
        # Getting text from user.
        li $v0, 8
        la $a0, input
        li $a1, 20
        syscall
        
        # Display the result
        li $v0, 4
        la $a0, input
        syscall
    
    
    
    # end program
    li $v0, 10
    syscall

Branch on Equal(Condition)

.data
    msg1: .asciiz "Equal.\n"
    msg2: .asciiz "Different\n"
.text
    main:
        addi $s0, $zero, 20
        addi $s1, $zero, 25
    
        beq $s0, $s1, showMsg
        
        li $v0, 10
        syscall
        
    showMsg:
        li $v0, 4
        la $a0, msg1
        syscall

Set less than

.data
    msg: .asciiz "The number is less than other."
.text
    main:
        addi $t0, $zero, 1
        addi $t1, $zero, 10
    
        # If(t0<t1) s0:=1
        slt $s0, $t0, $t1
        bne $s0, $zero, showMsg
    
        # Tell the system that the program is done.
        li $v0, 10
        syscall
    
    showMsg:
        li $v0, 4
        la $a0, msg
        syscall
    

Pseudo Instruction

Make life easier!

Branch if the greater than

.data
    msg: .asciiz "The number is greater than other.\n"
.text
    main:
        addi $s0, $zero, 14
        addi $s1, $zero, 10
    
        # branch if the firt number is greater than the second one.
        bgt $s0, $s1, showMsg
    
    
    # End of program
    li $v0, 10
    syscall
    
    showMsg:
        li $v0, 4
        la $a0, msg
        syscall

Branch if the greater than

.data
    msg: .asciiz "The number is less than other.\n"
.text
    main:
        addi $s0, $zero, 5
        addi $s1, $zero, 10
    
        # branch if the firt number is less than the second one.
        blt $s0, $s1, showMsg
    
    
    # End of program
    li $v0, 10
    syscall
    
    showMsg:
        li $v0, 4
        la $a0, msg
        syscall

While loop

# C program sample
# int i=0;
# while(i<10) {
#     i++;
# }

# while loop
.data
    msg: .asciiz "Well Done!"
.text
    main:
        # int i=0;
        addi $t0, $zero, 0
        
        # while(i<10)
        while:
           #breaking loop for i>=10
           bgt $t0, 10, exit
           # i++
           addi $t0, $t0, 1
           b while
        exit:
            li $v0, 4
            la $a0, msg
            syscall
            
        # End of program.
        li $v0, 10
        syscall
        

Array

myArray(byte address)
.data
    myArray: .space 12 # storage 3 integers = 4-byte * 3
.text
    addi $s0, $zero, 10
    addi $s1, $zero, 14
    addi $s2, $zero, 47
    
    # index
    addi $t0, $zero, 0
    
    # save the first integer into array
    sw $s0, myArray($t0)
    
    # *** update index ***
    addi $t0, $t0, 4
    
    # save the second
    sw $s1, myArray($t0)
    
    # *** update index ***
    addi $t0, $t0, 4
    
    # save the third
    sw $s2, myArray($t0)
    
    
    
    # print the second integer from array.
    add $t0, $zero, 4
    lw $t1, myArray($t0)
    
    li $v0, 1
    add $a0, $zero, $t1
    syscall

while loop with array

.data
    myArray: .space 12
    newLine: .asciiz "\n"
    exitMsg: .asciiz "bye"
.text
    addi $s0, $zero, 33
    addi $s1, $zero, 21
    addi $s2, $zero, 48
    
    # index
    addi $t0, $zero, 0
    
    # save integer to the array
    sw $s0, myArray($t0)
        addi $t0, $t0, 4
    sw $s1, myArray($t0)
        addi $t0, $t0, 4
    sw $s2, myArray($t0)
    
    # reset index
    addi $t0, $zero, 0
    
    # while loop print content of array
    while:
        beq $t0, 12, exit
        
        lw $t1, myArray($t0)
        li $v0, 1
        addi $a0, $t1, 0
        syscall
            # update index
            addi $t0, $t0, 4
        # new line
        li $v0, 4
        la $a0, newLine
        syscall
        
        j while
    exit:
        li $v0, 4
        la $a0, exitMsg
        syscall

Initialize Array

.data
    # intialize array with 3 element and all integers are value 100.
    myArray: .word 100:3
    newLine: .asciiz "\n"
    whileFinish: .asciiz "exit"
.text
    main:
        # intialize index
        addi $t0, $zero, 0
        # print array content
        while:
            beq $t0, 12, exit
            # fetch array content
            lw $t1, myArray($t0)
            li $v0, 1
            add $a0, $zero, $t1
            syscall
                # update index
                addi $t0, $t0, 4
            # new line
            li $v0, 4
            la $a0, newLine
            syscall
                     
            j while
        exit:
            li $v0, 4
            la $a0, whileFinish
            syscall
        
        
        
        # End of program
        li $v0, 10
        syscall

Floating point arithmetic

.data
    num1: .float 3.2
    num2: .float 2.9
.text
    lwc1 $f2, num1
    lwc1 $f4, num2

    # add with single precesion
    add.s $f12, $f2, $f4
    
    # multiply
    mul.s $f12, $f2, $f4
    
    # divide
    div.s $f12, $f2, $f4    
    

Double point arithmetic

.data
    num1: .double 3.2
    num2: .double 2.9
.text
    ldc1 $f2, num1
    ldc1 $f4, num2

    # add with single precesion
    add.d $f12, $f2, $f4
    
    # multiply
    mul.d $f12, $f2, $f4
    
    # divide
    div.d $f12, $f2, $f4

If statements with floats and doubles

.data
    msg1: .asciiz "They are equal."
    msg2: .asciiz "They are not equal."
    num1: .float 2.43
    num2: .float 2.4
.text
    lwc1 $f2, num1
    lwc1 $f4, num2
    
    
    # compare floating point
    c.eq.s $f2, $f4
    # compare result
    # bc1f label
    # bc1t label
    # branch If the comparison is true.
    bc1t equal

    # If they are not equal.
    li $v0, 4
    la $a0, msg2
    syscall
    
    # System call to end of program
    li $v0, 10
    syscall
    
    
    equal:
       li $v0, 4
       la $a0, msg1
       syscall
     
       

Recursion

參考:

Tip:
$a0 當作判斷式的參數, 每次$a0之值賦予給$s0,由$s0跟$v0運算,結果由$v0得到。
記得習慣得到$v0之值,要存到data block。
# factorial in c program
# int factorial(int n) {
#     if(n==0) return 1;
#     else return n*factorial(n-1);
# }
.data
    msg:              .asciiz "Enter a number to find its factorial: "
    resultMsg:        .ascii "\nThe factorial of the number is "
    resultDot:        .asciiz ".\n"
    theNumber:        .word 0
    theResultNumber:  .word 0
.text
    .globl main
    main:
        # Get number from user.
        li $v0, 4
        la $a0, msg
        syscall
        
        li $v0, 5
        syscall
        # save number to theNumber
        sw $v0, theNumber($zero)
        
        # call factorial function
        lw $a0, theNumber($zero)
        jal fact
        sw $v0, theResultNumber
        
        # Display the result
        li $v0, 4
        la $a0, resultMsg
        syscall
        # Answer Number
        li $v0, 1
        lw $a0, theResultNumber($zero)
        syscall
        # Dot
        li $v0, 4
        la $a0, resultDot
        syscall
        
    
    
        # System call to end of program.
        li $v0, 10
        syscall
#----------------------
# Factorial Function
.globl fact
fact:
    addi $sp, $sp, -8
    sw $ra, 0($sp)
    # the s0 will be reset by $a0
    sw $s0, 4($sp)
    
    # Setting the value type is an integer.
    li $v0, 1
    # The zero is not to multiply.
    # Therefore, the procedurce start to return where call this procedure by label fractorialDone.
    # The register $a0 is the condition.
    beq $a0, $zero, fractorialDone
    
    # i--
    add $s0, $zero, $a0
    addi $a0, $a0, -1
    jal fact
    
    # Passing argument $a0 to $v0. $v0 := $a0
    # The $s0 is this stack's $s0.
    mul $v0, $v0, $s0
    
    fractorialDone:  
        lw $ra, 0($sp)
        lw $s0, 4($sp)
        addi $sp, $sp, 8
        
        # Return to the next of the instruction of "jal fact" on label fract.
        jr $ra

practice:

.data
    number: .word 0
    answer: .word 0
.text
.globl main
main:
    # get number from user.
    li $v0 5
    syscall
    
    sw $v0, number($zero)
    
    lw $a0, number($zero)
    jal fact
    sw $v0, answer($zero)
    
    # Display Output
    li $v0, 1
    lw $a0, answer($zero)
    syscall
    
    # end of program
    li $v0, 10
    syscall
    
#-----------
.globl fact
fact:
    addi $sp, $sp, -8
    sw $ra, 0($sp)
    # the s0 will be reset by $a0
    sw $s0, 4($sp)
    
    # start to recursion 
    # The register $a0 is the condition.
    li $v0, 1
    beq $a0, $zero, fracDone
    
    add $s0, $zero, $a0
    addi $a0, $a0, -1
    
    jal fact
    
    mul $v0, $v0, $s0
    
    fracDone:
        lw $ra, 0($sp)
        lw $s0, 4($sp)
        addi $sp, $sp, 8
        
        jr $ra

Sum and average

.data
    array: .word 10, 3, 68
    length: .word 3
    sum: .word 0
    avg: .word 0
    newLine: .asciiz "\n"
.text
    main:
        la $t0, array($zero)
        li $t1, 0, # index
        lw $t2, length($zero) # length
        li $t3, 0 # avgerage
        li $t4, 0 # sum
        
        sumLabel:
           lw $t5, 0($t0)
           # add elements
           add $t4, $t4, $t5
           addi $t1, $t1, 1
           addi $t0, $t0, 4
           blt $t1, $t2, sumLabel
           # save result
           sw $t4, sum($zero)
           # calculate average
           div $t3, $t4, $t2
           sw $t3, avg($zero)
        
        # Display sum
        li $v0, 1
        lw $a0, sum($zero)
        syscall
        
        # new line
        li $v0, 4
        la $a0, newLine($zero)
        syscall
        
        # Display average
        li $v0, 1
        lw $a0, avg($zero)
        syscall
        
        

2D Array and Sum diagonal of values

# [ [3, 4],
#   [2, 5] ]
.data
    twoDArray: .word 3, 4
               .word 2, 5
    size: .word 2 # Equal to rowLen and columnLen
    
    # The "eqv" is like as "#define" in C.
    .eqv DATA_SIZE 4
    
.text
    main:
    la $a0, twoDArray
    lw $a1, size
    jal sumDiagonal
    add $a0, $v0, $zero
    
    # Display result
    li $v0, 1
    syscall
    
    # End the program
    li $v0, 10
    syscall
    
sumDiagonal:
    li $v0, 0 # $v0 == sum
    li $t0, 0 # index == rowIndex == columnIndex
    
    sumLoop:
        mul $t1, $t0, $a1 # rowIndex * columnLen
        add $t1, $t1, $t0 # + columnIndex
        mul $t1, $t1, DATA_SIZE # *data size
        add $t1, $t1, $a0 # + base address
        
        lw $t2, 0($t1) # load content of address
        
        add $v0, $v0, $t2 # adding into sum
        addi $t0, $t0, 1 # update index
        blt $t0, $a1, sumLoop
    
    # end of sumDiagonal
    jr $ra
    
    
    
    
    
    

利用not or實現not功能

\( p \) \( q \) \( p \) nor \( q \)
1 1 0
1 0 0
0 1 0
0 0 1
假設我們需要讓$t1之值反轉($t0為真值表的p),放入$t0,那就固定q為0, 即可實現。
nor $t0, $t1, $zero 

利用exclusive or 實現swap

\( p \) \( q \) \( p \) xor \( q \)
1 1 0
1 0 1
0 1 1
0 0 0

假設$t0和$t1之值交換
xor $t0, $t0, $t1
xor $t1, $t0, $t1
xor $t0, $t0, $t1