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