Easy68k下M68k汇编双字数组标量积计算无限循环问题求助
M68k汇编标量积程序无限循环问题分析与优化建议
无限循环原因分析
你遇到的无限循环问题,核心是moveq #len,d1的行为不符合预期。M68k的moveq指令会将8位立即数符号扩展为32位存入目标寄存器:
- 当
len≤127时,符号扩展后d1是正常正数;但如果后续len被修改为大于127的数值,符号扩展会让d1变成极大的负数,此时subq.l #1,d1会持续递减,永远无法到达0,触发无限循环。 - 你用
move.b #len,d1修复有效,是因为move.b仅修改d1的低8位,高24位保持为0,确保d1初始值为$00000004,后续递减能正常到0。
更规范的写法是用move.w #len,d1或move.l #len,d1,明确操作字/长字,彻底避免符号扩展的潜在风险。
代码优化建议
1. 减少寄存器占用
当前代码使用d5、d6两个寄存器做乘法,可合并操作节省一个寄存器:
move.w (a0)+,d5 mulu.w (a1)+,d5 ; 直接用d5存储乘数和乘积结果 add.l d5,d0
2. 用专用循环指令提升效率
M68k的dbra指令将“递减计数器+判断分支”合并为单条指令,比subq+bne更高效。注意dbra要求计数器初始值为len-1:
move.w #len-1,d1 LOOP: ; 循环体操作 dbra d1,LOOP ; 自动递减d1,非零则跳转
3. 精简初始化与计数操作
- 用
moveq #0,d0替代clr.l d0:前者是单字节指令,执行速度更快。 - 用
subq.w #1,d1替代subq.l #1,d1:因为len是4,16位计数足够,减少指令长度和执行周期。
优化后的完整代码(dbra版本)
ORG $8000 START: moveq #0,d0 ; 高效清零长字寄存器 lea.l A,a0 lea.l B,a1 move.w #len-1,d1 ; dbra循环初始值设为元素个数-1 LOOP: move.w (a0)+,d5 mulu.w (a1)+,d5 ; 合并乘法操作,节省寄存器 add.l d5,d0 dbra d1,LOOP ; 单指令完成递减+分支 move.l d0,scalar_prod SIMHALT ; 数据定义 A DC.W 10,20,30,40 B DC.W 50,60,70,80 len EQU 4 scalar_prod DC.L 0 END START
内容的提问来源于stack exchange,提问作者Pizza
相关产品推荐
相关产品推荐

