汇编技术求助:如何将寄存器中的位移动至8个连续寄存器?
解决AVR汇编中位拆分到多个寄存器的问题
首先修正你现有代码的基础错误:
ldi r17缺少立即数,应该写成ldi r17, sequen来加载定义的常量- 当前代码仅将r17的位循环移位到r18单个寄存器,所以只会得到反转后的位序列,无法分到多个寄存器
关于循环中途切换操作寄存器的问题
可以实现,AVR汇编没有直接的“寄存器索引”指令,但有两种常用思路:
方法1:利用寄存器内存映射自动切换寄存器
AVR的通用寄存器会映射到内存地址(比如r18对应0x12,r19对应0x13,以此类推),可以用Z指针指向目标寄存器起始地址,每次写入后自动切换到下一个寄存器:
.equ sequen = 0x10001011 ldi r17, sequen ; 加载源数据到r17 ldi r16, 0x8 ; 循环计数器,共处理8位 ldi zh, high(r18) ; Z指针高字节指向r18的内存地址高位 ldi zl, low(r18) ; Z指针低字节指向r18的内存地址低位 next: lsr r17 ; 将r17的最低位移到进位标志C clr r0 ; 清空临时寄存器r0 rol r0 ; 把进位标志C的位移入r0的最低位,此时r0仅存当前处理的位 st z+, r0 ; 将r0存入当前目标寄存器,Z指针自动+1(切换到下一个寄存器) dec r16 brne next ; 计数器不为0则继续循环 rjmp pc ; 原地跳转终止程序
方法2:手动判断计数器切换寄存器(适合新手理解)
通过判断循环计数器的值,直接指定要操作的寄存器,把当前位存入:
.equ sequen = 0x10001011 ldi r17, sequen ldi r16, 0x0 ; 计数器从0开始计数 loop: lsr r17 ; 当前位移入进位标志C ; 根据计数器值选择目标寄存器 cpi r16, 0 breq set_r18 cpi r16, 1 breq set_r19 cpi r16, 2 breq set_r20 cpi r16, 3 breq set_r21 cpi r16, 4 breq set_r22 cpi r16, 5 breq set_r23 cpi r16, 6 breq set_r24 cpi r16, 7 breq set_r25 set_r18: clr r18 rol r18 rjmp next_step set_r19: clr r19 rol r19 rjmp next_step set_r20: clr r20 rol r20 rjmp next_step set_r21: clr r21 rol r21 rjmp next_step set_r22: clr r22 rol r22 rjmp next_step set_r23: clr r23 rol r23 rjmp next_step set_r24: clr r24 rol r24 rjmp next_step set_r25: clr r25 rol r25 rjmp next_step next_step: inc r16 cpi r16, 8 brne loop rjmp pc
原代码反转位的原因
lsr r17是右移操作,每次把r17的最低位移到进位标志C,而rol r18会把C移入r18的最高位。循环8次后,r18的位顺序刚好是r17的反转(比如r17的bit0到了r18的bit7,bit7到了r18的bit0)。你的需求是拆分到多个寄存器,所以重点是将每一位单独存入不同寄存器而非合并到单个寄存器。
内容的提问来源于stack exchange,提问作者Samsen12
相关产品推荐
相关产品推荐

