天天看點

comp1521-MIPS快速入門(一)數組以及函數

文章目錄

  • ​​1 數組​​
  • ​​2 函數​​
  • ​​2.1 sw和lw​​
  • ​​2.2 ra​​
  • ​​2.3 函數使用的一些預設寄存器​​
  • ​​2.4 函數調用 jal​​
  • ​​2.5 無參函數直接調用示例​​
  • ​​2.6 無參有傳回值​​
  • ​​2.7 嵌套函數調用​​
  • ​​2.7.1 sp​​
  • ​​2.7.2 fp​​
  • ​​2.7.3 示例​​
  • ​​2.8 函數調用時假設不變量:​​

1 數組

// Read 10 numbers into an array
// then print the numbers which are
// larger than the last number read.

#include <stdio.h>

int main(void) {
    int i, last_number;
    int numbers[10] = { 0 };

    i = 0;
    while (i < 10) {
        scanf("%d", &numbers[i]);
        last_number = numbers[i];
        i++;
    }
    i = 0;
    while (i < 10) {
        if (numbers[i] >= last_number) {
            printf("%d\n", numbers[i]);
        }
        i++;
    }
}      

c語言對應的彙編

# Read 10 numbers into an array
# then print the numbers which are
# larger than the last number read.

# i in register $t0
# registers $t1, $t2 & $t3 used to hold temporary results
# t4 is the last value
main:
    li   $t0, 0         # i = 0
loop0:
    bge  $t0, 10, end0  # while (i < 10) {

    li   $v0, 5         #   scanf("%d", &numbers[i]);
    syscall             # 輸入的數字儲存在v0中

    mul  $t1, $t0, 4    #   calculate &numbers[i],一個int是4個bit
    la   $t2, numbers   #  儲存數組的首位址
    add  $t3, $t1, $t2  #  數組的首位址,加上i * 4,就是0号元素應該在的位置
    sw   $v0, ($t3)     #   store entered number in array,sw就是save word的意思。
                        # v0輸入的值儲存在t3位址
    add  $t4, $v0, 0    # also can be s0
    addi $t0, $t0, 1    #   i++;
    j    loop0          # }
end0:
    li   $t0, 0         # i = 0
loop1:
    bge  $t0, 10, end1  # while (i < 10) {

    mul  $t1, $t0, 4    #   calculate &numbers[i]
    la   $t2, numbers   #
    add  $t3, $t1, $t2  #
    lw   $a0, ($t3)     #   load numbers[i] into $a0
    bge  $a0, $t4, print # 如果大于等于,就需要去有輸出的分支。

    addi $t0, $t0, 1    #   i++
    j    loop1          # }
print:
    li   $v0, 1         #   printf("%d", numbers[i])
    syscall

    li   $a0, '\n'      #   printf("%c", '\n');
    li   $v0, 11
    syscall
    addi $t0, $t0, 1    #   i++  在輸出分支裡繼續增加控制變量。
    j    loop1          # }
end1:

    jr   $ra              # return

.data

numbers:
    .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0  # int numbers[10] = {0};      

2 函數

2.1 sw和lw

主要是sw和lw,這兩個指令在操作記憶體。

sw   $v0, ($t3)     #   store entered number in array,sw就是save word的意思。
                        # v0輸入的值儲存在t3位址


lw   $a0, ($t3)     #   load *t3 into $a0      

2.2 ra

​jr $ra​

​ 在一個函數裡,ra儲存的位址是該函數執行完之後,應該傳回的位址。是以,該指令執行後,相當于将PC的值設定為ra裡的位址值。跳轉回去原本函數調用的位置。

2.3 函數使用的一些預設寄存器

存放函數輸入參數的四個寄存器: $a0, $a1, $a2, $a3

傳回值寄存器在 $v0

2.4 函數調用 jal

jal function set $ra to PC+4 and jumps to function

2.5 無參函數直接調用示例

comp1521-MIPS快速入門(一)數組以及函數

2.6 無參有傳回值

comp1521-MIPS快速入門(一)數組以及函數

2.7 嵌套函數調用

學會将目前的ra值壓入stack!

當又調用一個函數的時候,stack向低位址生長!

comp1521-MIPS快速入門(一)數組以及函數

2.7.1 sp

目前的棧指針

2.7.2 fp

comp1521-MIPS快速入門(一)數組以及函數

2.7.3 示例

#include <stdio.h>

int sum_product(int a, int b);
int product(int x, int y);

int main(void) {
    int z = sum_product(10, 12);
    printf("%d\n", z);
    return 0;
}

int sum_product(int a, int b) {
    int p = product(6, 7);
    return p + a + b;
}

int product(int x, int y) {
    return x * y;
}      

對應的彙編

main:
    addi $sp, $sp, -4   # move stack pointer down to make room
    sw   $ra, 0($sp)    # save $ra on $stack

    li   $a0, 10         # sum_product(10, 12);
    li   $a1, 12
    jal  sum_product

    move $a0, $v0       # printf("%d", z);
    li   $v0, 1
    syscall

    li   $a0, '\n'      # printf("%c", '\n');
    li   $v0, 11
    syscall

    lw   $ra, 0($sp)    # recover $ra from $stack
    addi $sp, $sp, 4    # move stack pointer back up to what it was when main called

    li   $v0, 0         # return 0 from function main
    jr   $ra            # return from function main



sum_product:
    addi $sp, $sp, -12  # move stack pointer down to make room
    sw   $ra, 8($sp)    # save $ra on $stack
    sw   $a1, 4($sp)    # save $a1 on $stack
    sw   $a0, 0($sp)    # save $a0 on $stack

    li   $a0, 6         # product(6, 7);
    li   $a1, 7
    jal  product

    lw   $a1, 4($sp)    # restore $a1 from $stack
    lw   $a0, 0($sp)    # restore $a0 from $stack

    add  $v0, $v0, $a0  # add a and b to value returned in $v0
    add  $v0, $v0, $a1  # and put result in $v0 to be returned

    lw   $ra, 8($sp)    # restore $ra from $stack
    addi $sp, $sp, 12   # move stack pointer back up to what it was when main called

    jr   $ra            # return from sum_product


product:                # product doesn't call other functions
                        # so it doesn't need to save any registers
    mul  $v0, $a0, $a1  # return argument * argument 2
    jr   $ra            #      

2.8 函數調用時假設不變量:

繼續閱讀