如何修改汇编代码实现输入与QUIT比较,解决程序停滞问题?
字符串比较逻辑导致程序停滞的问题排查与修复
我需要实现用户输入与"QUIT"的比较功能,要求输入与"QUIT"不匹配时退出循环。但实际运行程序时,无论输入什么内容,程序都会停滞。已经尝试调整代码执行顺序、使用调试器排查,仍未定位到具体问题。相关循环的汇编代码如下:
; 字符串比较函数 STRING_COMPARE_QUIT AND R0, R0, #0 ; 初始化结果为0 ; R1指向'QUIT',R2指向输入缓冲区 ; R3/R4为字符串中的字符 ; R5是比较标志,R6用于小写检查 ; R6是小写掩码 CASE_INSENSITIVE_COMPARE_QUIT LEA R1, QUIT ; 指向字符串"QUIT" LD R2, INPUT_BUFFER ; 指向输入缓冲区 AND R5, R5, #0 ; 清除比较标志 CHECK_LOOP_QUIT LDR R3, R1, #0 ; 从"QUIT"加载字符 LDR R4, R2, #0 ; 从输入缓冲区加载字符 ; 检查R3是否为小写,若是则转为大写 LD R6, MASK ; 将小写掩码值加载到R6 AND R6, R3, R6 ; 用掩码判断是否为小写字母 BRz NOT_LOWERCASE_1_QUIT ; 零标志表示不是小写字母 ADD R3, R3, #0 ; 根据R3设置条件码 BRn NOT_LOWERCASE_1_QUIT ; 负标志表示不是小写字母(ASCII < 'a') BRzp CASE_CHECK_R3_QUIT ; 零或正表示是小写字母 NOT_LOWERCASE_1_QUIT BRnzp SKIP_CONVERSION_1_QUIT ; 不是小写则跳过转换 CASE_CHECK_R3_QUIT LD R6, MASK ; 从内存加载32到R6 AND R6, R3, R6 ; 用掩码检查R3是否为小写 BRz CONVERT_R3_QUIT ; 若为零,将小写转为大写 ; 由于此处BRnzp是无条件跳转,该标签已无必要 SKIP_CONVERSION_1_QUIT ; 后续可移除该行,除非添加新代码 BRnzp NEXT_INSTRUCTION_QUIT ; 无需转换则跳转到下一条指令 CONVERT_R3_QUIT LD R6, TO_UPPERCASE ; 加载32到R6 NOT R3, R3 ; 取反R3准备加法 ADD R3, R3, #1 ; 加1完成2's补码取反 ADD R3, R3, R6 ; 加R6(32)完成减法,实现小写转大写 NEXT_INSTRUCTION_QUIT ; 检查R4是否为小写,若是则转为大写 LD R6, MASK ; AND R6, R4, R6 ; 用掩码判断是否为小写字母 BRz NOT_LOWERCASE_2_QUIT ; 零标志表示不是小写字母 ADD R4, R4, #0 ; 根据R4设置条件码 BRn NOT_LOWERCASE_2_QUIT ; 负标志表示不是小写字母(ASCII < 'a') BRzp CASE_CHECK_R4 ; 零或正表示是小写字母 NOT_LOWERCASE_2_QUIT BRnzp SKIP_CONVERSION_2_QUIT ; 不是小写则跳过转换 CASE_CHECK_R4_QUIT LD R6, MASK AND R6, R4, R6 BRz CONVERT_R4_QUIT SKIP_CONVERSION_2_QUIT BRnzp NEXT_INSTRUCTION_FOR_R4_QUIT CONVERT_R4_QUIT LD R6, TO_UPPERCASE NOT R4, R4 ADD R3, R3, #1 ADD R4, R4, R6 ; 加二进制0010000将小写转大写 ; 继续处理R4 NEXT_INSTRUCTION_FOR_R4_QUIT ADD R6, R3, #0 ; 根据R3更新标志位 BRz CHECK_QUIT_END ; 若R3为空,检查输入缓冲区是否结束 ADD R6, R4, #0 ; 根据R4更新标志位 BRz STRINGS_NOT_EQUAL_QUIT ; 若R4为空,说明不匹配 ; 未遇到空字符,比较字符 CHAR_EQUAL_QUIT ADD R1, R1, #1 ; 移动到"QUIT"的下一个字符 ADD R2, R2, #1 ; 移动到输入缓冲区的下一个字符 BRnzp CHECK_LOOP ; 继续循环 CONTINUE_COMPARE_QUIT ADD R1, R1, #1 ; 移动到"QUIT"的下一个字符 ADD R2, R2, #1 ; 移动到输入缓冲区的下一个字符 BRnzp CHECK_LOOP_QUIT ; 循环返回 CHECK_QUIT_END ADD R6, R4, #0 ; 复制R4检查输入是否结束 BRz STRINGS_ARE_EQUAL_QUIT ; 若R4为空,两个字符串都结束,即相等 BRnzp STRINGS_NOT_EQUAL_QUIT ; 若R4不为空,不匹配 STRINGS_NOT_EQUAL_QUIT BRnzp STRING_COMPARE_QUIT_EXIT STRINGS_ARE_EQUAL_QUIT ; 设置"相等"标志,输入匹配"QUIT"(忽略大小写) AND R5, R5, #0 ; 清除R5 ADD R5, R5, #1 ; 设置R5表示字符串相等 BRzp EXIT STRING_COMPARE_QUIT_EXIT
问题定位与修复方案
标签跳转错误
CHAR_EQUAL_QUIT块末尾跳转到CHECK_LOOP,但正确的循环标签是CHECK_LOOP_QUIT,这会导致跳转到错误位置引发死循环,需修改为BRnzp CHECK_LOOP_QUIT。R4转换操作错误
CONVERT_R4_QUIT块中错误执行了ADD R3, R3, #1,破坏了已处理的R3值,应改为ADD R4, R4, #1(配合前面的NOT R4, R4完成2's补码取反)。缺失字符不等判断逻辑
当前代码仅处理字符相等的情况,未判断字符不等时的分支。需在字符加载转换后添加比较逻辑:; 比较转换后的R3和R4 NOT R6, R4 ADD R6, R6, #1 ADD R6, R3, R6 BRnp STRINGS_NOT_EQUAL_QUIT ; 字符不等则跳转到不匹配分支标签定义不匹配
跳转时使用CASE_CHECK_R4_QUIT,但标签定义为CASE_CHECK_R4,需统一标签后缀为_QUIT。冗余检查逻辑简化
CASE_CHECK_R3_QUIT中的重复掩码检查可移除,直接在确认是小写后执行转换,减少冗余操作。
内容的提问来源于stack exchange,提问作者Keoni Roring
相关产品推荐
相关产品推荐

