---
# System prepended metadata

title: Another Way to Check Register Value

---

# 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
```

