前两天在调试DragonOS的riscv引导代码的时候,想在真机上获取寄存器的值,就找到了这篇帖子,非常有用,就把里面的代码提取出来,在此记录。
因为在汇编里面难以对字符串进行格式化操作,因此可以考虑把寄存器的值转义一下,然后输出到串口,再使用一个C程序把它转义回来。方法如下:
编码函数
首先在汇编里面定义这样一个函数:
// 要打的值输入到a0
__do_show_val:
// todo: 为了保护寄存器,这里应当添加压栈操作,
// 把函数使用到的寄存器都保存一下,在ret之前弹栈
// 实际使用时,如果需要多次调用本函数,那么一定要补充
// 压栈的代码。
mv t0,a0
li t1, 0x0F
li t2, 16
2: beqz t2, 3f
and t3, t0, t1
addi a0, t3, 0x41
li a7, 0x01
ecall
srli t0, t0, 4
addi t2, t2, -1
j 2b
3: li a0, 0x0A # 打一个回车, 方便查看
li a7, 0x01
ecall
ret
当要使用上述代码的时候,就把要打印的寄存器的值,移动到a0,然后call这个函数即可。
// 示例:打印t3
mv a0,t1
call __do_show_val
然后运行的时候,就会输出一个十六位的字符串。比如:“PAAAIFPDAAAAAAAA“
解码
接着我们需要写个C程序对上述输出的数据进行解码。程序如下:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
void read_each()
{
char a[17] = {};
while (1)
{
printf("Enter:");
scanf("%s", a);
for (int i = 15; i >= 0; i--)
{
printf("%1X", a[i] - 'A');
}
printf("\n");
printf("\n");
}
}
int main(int argc, const char *argv[])
{
read_each();
}
运行
把上述数据输入到C程序内,就能输出寄存器值了:
longjin@longjin-server:~/$ ./show
Enter:PAAAIFPDAAAAAAAA
000000003F58000F
Enter:
所以我们可以看到这个寄存器的值就是“3F58000F“。