ARM汇编自定义函数中如何使用循环 处理LR寄存器及倍数判断问题
ARM汇编计数程序问题解决方案
核心问题说明
- 指令使用误区:内部循环不需要用
BL跳转,BL仅用于函数调用,会自动修改LR寄存器存储返回地址,普通循环用B指令跳转即可,不会修改LR,不存在覆盖问题 - 逻辑优先级错误:当前代码先判断8的倍数再判断3的倍数,若数值同时为二者倍数,会导致后写入的
0xbbbb覆盖先写入的0xffff,无法得到要求的0xffbb - 返回地址存储冗余:不需要在数据段预定义空间存储LR,直接通过栈
PUSH/POP操作保存恢复LR更简洁 - 计数起始值错误:初始
r0=10后进入_loop先执行add R0, #1,会跳过10直接从11开始计数
具体修改方案
1. 3的倍数判断循环实现
直接在_multOf3函数内实现循环,不需要单独拆成函数,用B跳转实现迭代,完全不修改LR:
_multOf3: PUSH {LR} @ 直接用栈保存返回地址,不需要存到数据段 MOV R1, R0 @ 复制待判断数值到临时寄存器R1,不修改原R0 3_loop: SUBS R1, #3 @ 每次减3,影响标志位 BPL 3_loop @ 如果结果>=0就继续循环 @ 循环结束后R1为-2/-1/0,等于0就是3的倍数 CMP R1, #0 BNE _multOf3_end @ 不是3的倍数直接返回 @ 是3的倍数,判断是否同时是8的倍数 CMP R3, #0xffff MOVEQ R3, #0xffbb MOVNE R3, #0xbbbb _multOf3_end: POP {PC} @ 直接把栈里存的LR弹到PC,完成返回
2. 其他逻辑修正
- 调整
_loop的计数初始值,保证从10开始计数 - 简化所有函数的LR保存逻辑,统一用栈操作
- 删掉冗余的数据段返回地址存储逻辑,减少代码复杂度
完整可运行修改后代码
.section .text .global _start _start: MOV R0, #9 @ 初始设为9,进循环先加1得到10,符合计数要求 BL _loop _end: B _end _loop: ADD R0, #1 @ 递增计数 MOV R3, #0 @ 重置R3 CMP R0, #50 @ 到50就退出 BEQ _end BL _multOf8 @ 先判断8的倍数 BL _multOf3 @ 再判断3的倍数,处理同时满足的情况 B _loop _multOf8: PUSH {LR} AND R1, R0, #7 CMP R1, #0 MOVEQ R3, #0xffff @ 是8的倍数先赋值0xffff POP {PC} _multOf3: PUSH {LR} MOV R1, R0 3_loop: SUBS R1, #3 BPL 3_loop CMP R1, #0 BNE _multOf3_end CMP R3, #0xffff MOVEQ R3, #0xffbb MOVNE R3, #0xbbbb _multOf3_end: POP {PC}
内容的提问来源于stack exchange,提问作者Hamza Qureshi
相关产品推荐
相关产品推荐

