# Another Way to Check Register Value
恩,Spike Debug Mode 是真的很難用。不直覺而且浪費時間。在這裡用另外一種方式去解決。
## 原理
如果想要用`stdio.h`,中的`printf` function,必然需要多處理兩種問題。
- Calling convention
- 因為是 function
- String
- 第一個 argument 是char array
這個新方法的重點就是要盡可能的避開這兩個問題。而且又可以達成印出暫存器結果的效果。
總結而言,就是用 `toolchain` 直接生成有 String 與大部分 `calling convenction` 的程式碼。然後讓主程式去調用它。
## 用法
分成兩部份
1. 把下面的`source code`給你的程式一起編譯
> 我姑且先稱呼這個 source code 為 print.c
2. 在你想要印出`register value`的地方調用這個`function`
對於第二點需要補充幾點。
1. 雖然大多數的`caller save register`,可以進 `function`再處理。但是對於 `return address` 在調用程式當下就被更新了。所以需要在外面就要先處理。
用起來大概只要在你想要查看 `Register value` 的地方插入這一段`assembly`。
```
add t5, t3, t4 ; Want to check t5 value
addi sp, sp, -8 ; alloca memory for ra
sd ra, 0(sp) ; Save ra in stack
addi sp, sp, -8 ; alloca memory for a0
sd a0, 0(sp) ; Save a0 in stack
mv a0, t5 ; Move t5 as argument
call print ; invoke print function
ld a0, 0(sp) ; restore a0
addi sp, sp, 8 ; dealloc memory for a0
ld ra, 0(sp) ; restore ra
addi sp, sp, 8 ; dealloc memory for ra
```
```
addi sp, sp, -8
sd ra, 0(sp)
addi sp, sp, -8
sd a0, 0(sp)
mv a0, t5
call print
ld a0, 0(sp)
addi sp, sp, 8
ld ra, 0(sp)
addi sp, sp, 8
```
然後記得跟最下面的 source code 一起編譯。
## Source code
```c
#include <stdio.h>
void print(int a) {
asm volatile(
"addi sp, sp, -1024\n\t"
"addi sp, sp, -1024\n\t"
"sd t0, 2040(sp)\n\t"
"sd t1, 2032(sp)\n\t"
"sd t2, 2024(sp)\n\t"
"sd t3, 2016(sp)\n\t"
"sd t4, 2008(sp)\n\t"
"sd t5, 2000(sp)\n\t"
"sd t6, 1992(sp)\n\t"
"sd a0, 1984(sp)\n\t"
"sd a1, 1976(sp)\n\t"
"sd a2, 1968(sp)\n\t"
"sd a3, 1960(sp)\n\t"
"sd a4, 1952(sp)\n\t"
"sd a5, 1944(sp)\n\t"
"sd a6, 1936(sp)\n\t"
"sd a7, 1928(sp)\n\t"
);
printf("%d\n", a);
asm volatile(
"ld t0, 2040(sp)\n\t"
"ld t1, 2032(sp)\n\t"
"ld t2, 2024(sp)\n\t"
"ld t3, 2016(sp)\n\t"
"ld t4, 2008(sp)\n\t"
"ld t5, 2000(sp)\n\t"
"ld t6, 1992(sp)\n\t"
"ld a0, 1984(sp)\n\t"
"ld a1, 1976(sp)\n\t"
"ld a2, 1968(sp)\n\t"
"ld a3, 1960(sp)\n\t"
"ld a4, 1952(sp)\n\t"
"ld a5, 1944(sp)\n\t"
"ld a6, 1936(sp)\n\t"
"ld a7, 1928(sp)\n\t"
"addi sp, sp, 1024\n\t"
"addi sp, sp, 1024\n\t"
);
}
```
## Example
這個範例是用`Blink.s`,加上這個`function`的使用範例。
### 編譯與執行
```
riscv64-unknown-elf-gcc Blink.s print.c
spike pk a.out
```
- Blink.s
- 你的 HW3 產生出來的assembly
- 對應到下面的Blink.s
- print.c
- 上一個章節提供的source code
### Blink.s
```
.file "Blink.cpp"
.text
.align 1
.global main
.type main, @function
main:
addi sp, sp, -16
sd s0, 8(sp)
addi s0, sp, 16
addi sp, sp, -8
addi t3, zero, 1024
sd t3, -8(s0)
ld t3, -8(s0)
addi sp, sp, 8
addi sp, sp, -8
sd t3, -8(s0)
addi sp, sp, -8
addi t3, zero, 512
sd t3, -16(s0)
ld t3, -16(s0)
addi sp, sp, 8
addi sp, sp, -8
sd t3, -16(s0)
ld t3, -8(s0)
addi sp, sp, -8
sd t3, -24(s0)
ld t3, -8(s0)
addi sp, sp, -8
sd t3, -32(s0)
ld t3, -16(s0)
addi sp, sp, -8
sd t3, -40(s0)
ld t3, -40(s0)
addi sp, sp, 8
ld t4, -32(s0)
addi sp, sp, 8
add t5, t3, t4
addi sp, sp, -8
sd t5, -32(s0)
ld t3, -8(s0)
addi sp, sp, -8
sd t3, -40(s0)
ld t3, -16(s0)
addi sp, sp, -8
sd t3, -48(s0)
ld t3, -48(s0)
addi sp, sp, 8
ld t4, -40(s0)
addi sp, sp, 8
mul t5, t3, t4
addi sp, sp, -8
sd t5, -40(s0)
ld t3, -40(s0)
addi sp, sp, 8
ld t4, -32(s0)
addi sp, sp, 8
add t5, t3, t4
addi sp, sp, -8
sd ra, 0(sp)
mv a0, t5
call print
ld ra, 0(sp)
addi sp, sp, 8
addi sp, sp, -8
sd t5, -32(s0)
ld t3, -32(s0)
addi sp, sp, 8
sd t3, -8(s0)
main_END:
addi sp, s0, 0
ld s0, 8(sp)
addi sp, sp, 16
ret
.size main, .-main
```