# This example shows an implementation of the mathematical
# factorial function (! function) to find the factorial value of !7 = 5040.
.data
argument: .word   7
str1:     .string "Factorial value of "
str2:     .string " is "
.text
main:
        lw  a0, argument   # Load argument from static data
        jal ra, fact       # Jump-and-link to the 'fact' label
        # Print the result to console
        mv  a1, a0
        lw  a0, argument
        jal ra, printResult
        # Exit program
        li a7, 10
        ecall
fact:
        addi sp, sp, -16
        sw   ra, 8(sp)
        sw   a0, 0(sp)
        addi t0, a0, -1
        bge  t0, zero, nfact
        addi a0, zero, 1
        addi sp, sp, 16
        jr x1
nfact:
        addi a0, a0, -1
        jal  ra, fact
        addi t1, a0, 0
        lw   a0, 0(sp)
        lw   ra, 8(sp)
        addi sp, sp, 16
        mul a0, a0, t1
        ret
# --- printResult ---
# a0: Value which factorial number was computed from
# a1: Factorial result
printResult:
        mv t0, a0
        mv t1, a1
        la a0, str1
        li a7, 4
        ecall
        mv a0, t0
        li a7, 1
        ecall
        la a0, str2
        li a7, 4
        ecall
        mv a0, t1
        li a7, 1
        ecall
        ret
這段c code 是一個在 RISC-V 上實作數學 階乘函數(factorial function)的範例,目標是計算 7 的階乘(即 7! = 5040),並將結果輸出到控制台。以下是分步解釋:
這個部分定義了靜態資料,包括要計算的參數和一些字串:
argument: 定義要計算階乘的數字,這裡是 7。str1: 定義字串 "Factorial value of "。str2: 定義字串 " is "。這裡是實際的程式碼,包括主程式 main,階乘計算函數 fact,以及結果輸出的 printResult。
main)lw a0, argument: 從資料區段載入 argument,即要計算的數字 7,並存入暫存器 a0。jal ra, fact: 跳到 fact 標籤,開始計算階乘,並將返回地址存入 ra 暫存器。mv a1, a0: 把階乘計算結果從 a0 移動到 a1,這是為了後續輸出。lw a0, argument: 再次載入 argument,為了在輸出時顯示原始數字。jal ra, printResult: 跳到 printResult 函數進行結果輸出。li a7, 10: 設定 a7 暫存器為 10,這是系統呼叫的代碼,用於退出程式。ecall: 執行系統呼叫,退出程式。fact)這裡是計算階乘的遞迴函數。
addi sp, sp, -16: 將堆疊指標 sp 向下移動 16 字節,為儲存資料預留空間。sw ra, 8(sp): 將返回地址 ra 存入堆疊。sw a0, 0(sp): 將目前的參數 a0(即階乘的值)存入堆疊。addi t0, a0, -1: 將 a0 減去 1,存入暫存器 t0,準備比較。bge t0, zero, nfact: 如果 t0 大於或等於 0,跳到 nfact,否則返回 1(表示遞迴結束)。如果數字小於等於 1,則返回 1:
addi a0, zero, 1: 將 a0 設為 1。addi sp, sp, 16: 將堆疊指標 sp 恢復。jr x1: 返回主程式。nfact)處理當 a0 > 1 的情況:
addi a0, a0, -1: 將 a0 減去 1。jal ra, fact: 再次呼叫 fact 函數,進行遞迴。addi t1, a0, 0: 將結果存入 t1 暫存器。lw a0, 0(sp): 從堆疊中取回原本的參數。lw ra, 8(sp): 從堆疊中取回返回地址。addi sp, sp, 16: 將堆疊指標 sp 恢復。mul a0, a0, t1: 計算階乘結果(a0 = a0 * t1)。ret: 返回主程式。printResult 函數負責將計算結果輸出到控制台:
a0,然後通過 ecall 系統呼叫輸出:
將編寫RISC-V彙編程式(RV32I ISA)並透過環境呼叫輸出到控制台。