LC3程序为何无法执行到RET或HALT指令?
问题分析与解决方案
核心问题点
- 寄存器未完整恢复:
GETSTR子程序中保存了R4寄存器,但返回前仅恢复了R2、R3,未恢复R4,导致寄存器值污染,可能引发后续执行异常。 - 字符串无终止符:输入ENTER后未在字符串末尾写入ASCII 0(null字符),
PUTS会持续输出内存内容直到遇到null,引发无限输出或异常循环。 - 数据布局冲突:原代码用
.stringz初始化STR1,但注释明确要求用.blkw预留存储空间,多余的'z'会导致PUTS输出无关内容。
修改后的代码
.orig x3000 MAIN LEA R0, STR1 ; R0指向字符串存储区 JSR GETSTR ; 获取用户输入的字符串 PUTS ; 打印字符串 HALT ; 字符串存储区:预留50个单元,用于存储输入的字符串 STR1 .blkw 50 ; 替换原.stringz,避免多余字符干扰 GETSTR ; 保存用到的寄存器 ST R2, GS_SR2 ST R3, GS_SR3 ST R4, GS_SR4 LD R4, GS_LR4 ; R4 = -10,用于判断是否为ENTER(ASCII 10) ADD R2, R0, #0 ; R2指向当前要存储字符的位置 GSTOP GETC ; 获取用户输入的字符 ADD R3, R0, R4 ; 计算输入字符 + (-10),若为ENTER则结果为0 BRZ GSEND ; 是ENTER则跳转到结束处理 STR R0, R2, #0 ; 将字符存入字符串存储区 OUT ; 回显字符 ADD R2, R2, #1 ; 移动到下一个存储位置 BRNZP GSTOP ; 继续获取字符 GSEND ; 在字符串末尾添加null终止符,确保PUTS能正常停止 AND R0, R0, #0 ; R0 = 0(ASCII null) STR R0, R2, #0 ; 存入当前位置 ; 恢复所有保存的寄存器 LD R2, GS_SR2 LD R3, GS_SR3 LD R4, GS_SR4 ; 新增恢复R4 RET ; 返回MAIN ; 寄存器保存区 GS_SR2 .fill 0 GS_SR3 .fill 0 GS_SR4 .fill 0 GS_LR4 .fill -10 ; 用于判断ENTER的常量 .end
修改说明
- 替换
STR1为.blkw 50:移除原.stringz的大量'z',改用干净的预留存储空间,避免PUTS输出无关内容。 - 添加null终止符:在
GSEND段中写入ASCII 0,确保PUTS输出到字符串末尾后停止。 - 恢复R4寄存器:补充
LD R4, GS_SR4指令,完整恢复所有保存的寄存器,避免寄存器值异常影响后续执行。
修改后,按下ENTER时代码会正常跳转到GSEND,添加终止符后返回MAIN,执行PUTS打印输入内容后停机,符合预期。
内容的提问来源于stack exchange,提问作者Carter Tipton
相关产品推荐
相关产品推荐

