QEMU-RISCV64运行未知错误:调用RISC-V汇编函数程序冻结
RISC-V64汇编函数调用问题排查与修复
问题描述
我开发了一个程序,用来获取传入的第二个参数首字符,判断它是大写还是小写字母。现在调用另一个文件里的RISC-V64汇编函数时出了问题:汇编代码本该返回0、1、2给C文件里的int result变量,但实际没生效;而且汇编单独测试是好的,编译没错误,但运行时程序卡住,像在等输入。
相关代码
ARQUIVO.C
#include <stdio.h> extern int verificando(char*); int main(int argc, char *argv[]){ argc = 3; argv[1] = "maracuja"; argv[2] = "Graviola"; int result; result = verificando(&(argv[2][0])); if (result == 0){ printf("\n%s: Primeiro caracter da segunda string eh minusculo.\n", argv[2]); }else if (result == 1){ printf("\n%s: Primeiro caracter da segunda string eh maiusculo.\n", argv[2]); }else if (result == 2){ printf("\nNao existe uma segunda string.\n"); }else { printf("\nErro\n"); } return 0; }
ARQUIVO.S
.global verificando verificando: #ascii li t5, 65 li t6, 90 li t3, 97 li t4, 122 # carrega o primeiro caracter do segundo argumento em t1 e verifica lb t1, 0(a0) jal verifica verifica: bge t6, t1, maiuscula bge t1, t3, minuscula bge t3, t1, erro maiuscula: bge t1, t5, maiuscula_2 bge t1, t3, minuscula bge t5, t1, erro minuscula: bge t4, t1, minuscula_2 li a0, 2 ret maiuscula_2: # returns 1 li a0, 1 ret minuscula_2: # returns 0 li a0, 0 ret erro: # returns 2 li a0, 2 ret
MAKEFILE
default: riscv64-linux-gnu-gcc -static arquivo.s arquivo.c -o arquivo.x run: default qemu-riscv64-static arquivo.x clean: rm -rf *.x
问题分析与修复
1. 汇编函数无法返回导致程序冻结
verificando函数中使用jal verifica调用子过程,verifica执行ret后会回到jal verifica的下一行,但verificando中该位置没有任何返回指令(ret),导致函数无法正常返回给C调用者,程序因此陷入等待状态。
修复方式:移除冗余的jal verifica调用,将判断逻辑直接整合到verificando函数中,确保函数最终能通过ret返回。
2. 分支逻辑冗余且存在逻辑漏洞
原汇编的分支判断存在多余跳转,可能导致逻辑混乱。简化后的判断逻辑应该:
- 先检查字符是否属于大写字母范围(ASCII 65-90),是则返回1
- 否则检查是否属于小写字母范围(ASCII 97-122),是则返回0
- 其他情况返回2
修复后的汇编代码
.global verificando verificando: # 加载ASCII范围常量 li t5, 65 # 'A'的ASCII码 li t6, 90 # 'Z'的ASCII码 li t3, 97 # 'a'的ASCII码 li t4, 122 # 'z'的ASCII码 # 加载第一个字符到t1 lb t1, 0(a0) # 判断是否为大写字母 bge t1, t5, check_upper_bound j check_lower check_upper_bound: ble t1, t6, return_upper j check_lower check_lower: bge t1, t3, check_lower_bound j return_error check_lower_bound: ble t1, t4, return_lower j return_error return_upper: li a0, 1 ret return_lower: li a0, 0 ret return_error: li a0, 2 ret
3. C代码的优化建议
直接修改argc和argv的做法不符合规范,测试时可以直接传入目标字符串,避免潜在的内存问题:
#include <stdio.h> extern int verificando(char*); int main() { char *target_str = "Graviola"; int result = verificando(target_str); if (result == 0){ printf("\n%s: Primeiro caracter da segunda string eh minusculo.\n", target_str); }else if (result == 1){ printf("\n%s: Primeiro caracter da segunda string eh maiusculo.\n", target_str); }else if (result == 2){ printf("\nNao existe uma segunda string.\n"); }else { printf("\nErro\n"); } return 0; }
内容的提问来源于stack exchange,提问作者GreatField
相关产品推荐
相关产品推荐

