RISC-V 的寄存器分為以下幾類:
臨時寄存器:t0-t6(x5-x7, x28-x31)
保存寄存器:s0-s11(x8, x9, x18-x27)
參數寄存器:a0-a7(x10-x17)
返回地址寄存器:ra(x1) 注意:不是返回值,call函數的時候的下一條指令
棧指針寄存器:sp(x2)
全局指針寄存器:gp(x3)
線程指針寄存器:tp(x4)
參數傳遞
前8個參數:通過參數寄存器 a0-a7 傳遞。
超過8個參數:通過棧傳遞,超出的參數會依次壓入棧中。
返回值
返回值:使用寄存器 a0 和 a1 返回。如果返回值超過兩個寄存器的大小,則通過棧傳遞。
棧幀佈局
每個函數調用都會創建一個新的棧幀,棧幀的佈局如下:
返回地址:保存調用者的返回地址。
保存寄存器:保存被調用函數使用的保存寄存器。
局部變量和臨時數據:函數的局部變量和臨時數據。
調用者保存和被調用者保存
調用者保存(Caller-saved):臨時寄存器(t0-t6)和參數寄存器(a0-a7)。調用函數前,調用者需要保存這些寄存器的值。
被調用者保存(Callee-saved):保存寄存器(s0-s11)和返回地址寄存器(ra)。被調用函數需要保存和恢復這些寄存器的值。
# 調用者函數
caller_function:
# 保存調用者保存寄存器
addi sp, sp, -16
sd ra, 8(sp)
sd t0, 0(sp)
# 設置參數並調用被調用者函數
li a0, 5
li a1, 10
call callee_function
# 恢復調用者保存寄存器
ld t0, 0(sp)
ld ra, 8(sp)
addi sp, sp, 16
ret
# 被調用者函數
callee_function:
# 保存被調用者保存寄存器
addi sp, sp, -16
sd s0, 0(sp)
# 函數體
add s0, a0, a1 # s0 = a0 + a1
# 恢復被調用者保存寄存器
ld s0, 0(sp)
addi sp, sp, 16
ret