loops - AVR 组装 BRNE 延迟循环如何工作?

标签 loops assembly delay avr

online delay loop generator给我这个运行在 16MHz 的芯片的延迟循环为 0.5 秒。

我心中的问题是:

  1. 如果寄存器变为负数,分支是否会继续分支?
  2. 如何准确计算一开始加载的值?

        ldi  r18, 41
        ldi  r19, 150
        ldi  r20, 128
    L1: dec  r20
        brne L1
        dec  r19
        brne L1
        dec  r18
        brne L1
    

最佳答案

准确回答您的问题:

1:DEC指令不知道“有符号”数字,它只是递减一个 8 位寄存器。二进制补码算法的奇迹使这项工作在环绕(0x00 -> 0xFF,与 0 -> -1 的位模式相同)。 DEC 指令还在状态寄存器中设置 Z 标志,BRNE用于确定是否应该发生分支。

2:从AVR手册可以看出DEC是单循环指令。 BRNE在不分支的时候也是一个周期,分支的时候是2个周期。因此,要计算循环的时间,您需要计算每条路径的执行次数。

考虑单个 DEC/BRNE 循环:

    ldi r8 0
L1: dec r8
    brne L1

这个循环将恰好执行 256 次,即 DEC 的 256 个周期和 BRNE 的 512 个周期,总共 768 个周期。在 16MHz 时,即 48us。

将其包装在外部延迟循环中:

    ldi r7 10
    ldi r8 0
L1: dec r8
    brne L1
    dec r7
    brne L1

您可以看到,每次内循环计数器达到 0 时,外循环计数器就会递减。因此在我们的示例中,外循环 DEC/BRNE 将发生 10 次(768 个周期),内循环将发生 10 x 256 次,所以这个循环的总时间是 10 x 48us + 48us 为 528us。对于 3 个嵌套循环也是如此。

从这里开始,计算每个循环应该执行多少次才能达到所需的延迟是微不足道的。这是外部循环可以少于所需时间的最大迭代次数,然后将这段时间移出,对下一个嵌套循环执行相同的操作,依此类推,直到最里面的循环填满剩下的少量。

关于loops - AVR 组装 BRNE 延迟循环如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47453737/

相关文章:

assembly - 使用 Windows WinAPI 函数写入控制台 Unicode (UTF-16) 文本?

libgdx - 等待 Actor 完成一个 Action

c - 使用 C 中的 Do..while 循环登录

c++ - ebp + 6 而不是 JIT 编译器中的 +8

JavaScript:.forEach() 和 .map() 之间的区别

assembly - 大多数现代系统中堆栈增长的方向是什么?

ios - 如何在 ionic 中增加 IOS 设备的启动画面时间

jquery - 如何延迟警报?

python - 在 Python 中使用 if 条件加速逐行循环

java - 尝试使用循环来处理备用数组