LC3汇编GetString子程序返回异常及字符存储错误求助
LC3汇编GetString子程序调试问题
问题现象
- 返回异常:执行
RET指令后未返回主程序,反而跳回ADD R1, R0, #-10指令行 - 字符串存储错误:字符写入位置混乱,具体错误:
- 位置1的字符错误:' '应为'H'(出现2次)
- 位置2的字符错误:' '应为'H'
- 位置1的字符错误:' '应为'�'
- 位置3的字符错误:' '应为'�'
- 位置2的字符错误:' '应为'V'
- 位置2的字符错误:' '应为'S'
- 位置2的字符错误:' '应为'n'
- 位置1的字符错误:' '应为'b'
原始代码
GETSTRING ;Save ALL registers that you change except for return Registers. ST R1, GS_R1 ;Save R1 as an example. ST R7, GS_R7 ;.... PUT YOUR CODE HERE .... ADD R1, R0, #0 GS_TOP JSR GETLETTER ADD R1, R0, #-10 BRZ GS_DONE STR R0, R1, #0 ADD R1, R1, #1 BRNZP GS_TOP GS_DONE ST R1, #0 ;Registers registers you used. LD R1, GS_R1 ;Restore R1 LD R7, GS_R7 RET ;This subroutine should ONLY have one return here. ;Storage for GETSTRING. ;All .fill, .stringz, .blkw labels used in this subroutine should go here. GS_R1 .fill 0 ;Storage location for R1 in GETSTRING GS_R7 .fill 0 ;------------------------------------------------------------------------------ ;END OF GETSTRING ;------------------------------------------------------------------------------
错误根源分析
字符串指针被破坏:
代码中用ADD R1, R0, #-10判断输入是否为回车键(ASCII 10),但R1是存储字符串缓冲区指针的寄存器,这一步直接覆盖了指针值,导致后续STR R0, R1, #0把字符写入错误的内存地址,这是字符存储混乱的核心原因。返回逻辑被破坏:
GS_DONE处的ST R1, #0指令会把R1的值存入当前PC偏移0的位置,直接覆盖了后续的LD R1, GS_R1指令,导致寄存器恢复逻辑失效,最终RET使用了错误的返回地址。缺少字符串终止符:
输入结束后未给字符串添加ASCII 0终止符,不符合LC3字符串规范。
修复后的代码
GETSTRING ; 保存所有会修改的寄存器(除返回寄存器) ST R1, GS_R1 ST R7, GS_R7 ; 保存主程序传入的返回地址 ; 初始化字符串缓冲区指针:R0为传入的缓冲区起始地址 ADD R1, R0, #0 GS_TOP JSR GETLETTER ; 调用子例程获取字符,R7会被修改为当前指令的下一条地址 ; 用临时寄存器R2判断是否为回车键(ASCII 10),避免破坏R1指针 ADD R2, R0, #-10 BRZ GS_DONE ; 将获取到的字符存入缓冲区,指针自增1 STR R0, R1, #0 ADD R1, R1, #1 BRNZP GS_TOP GS_DONE ; 在字符串末尾添加ASCII 0终止符 AND R0, R0, #0 STR R0, R1, #0 ; 恢复寄存器 LD R1, GS_R1 LD R7, GS_R7 ; 恢复主程序的返回地址 RET ; 子程序存储区 GS_R1 .fill 0 GS_R7 .fill 0 ;------------------------------------------------------------------------------ ;END OF GETSTRING ;------------------------------------------------------------------------------
修复说明
- 改用R2寄存器进行回车键判断,保留R1作为字符串缓冲区指针,确保字符写入正确地址。
- 移除
GS_DONE处错误的ST R1, #0指令,替换为写入字符串终止符的逻辑。 - 保留R7的提前保存,确保最终
RET能正确跳回主程序的调用位置。
内容的提问来源于stack exchange,提问作者Bill
相关产品推荐
相关产品推荐

