【问题标题】:How loops are implemented in PIC24F assembly code如何在 PIC24F 汇编代码中实现循环
【发布时间】:2019-02-01 18:03:33
【问题描述】:

以下是以下C代码的反汇编:

268:                   while (Counter < 250)
269:                   {
270:                       Counter++;
271:                   }

反汇编:

268:                   while (Counter < 250)
001B08  370003     BRA 0x1B10
001B10  90406E     MOV.B [W14+6], W0
001B12  404FE7     ADD.B W0, #0x7, [W15]
001B14  36FFFA     BRA LEU, 0x1B0A
269:                   {
270:                       Counter++;
001B0A  90406E     MOV.B [W14+6], W0
001B0C  E84000     INC.B W0, W0
001B0E  984760     MOV.B W0, [W14+6]
271:                   }
272:                   
273:                   // call foo
274:                   foo(LAT, 4, Set, &Code);
001B16  203F20     MOV #0x3F2, W0
001B18  40000E     ADD W0, W14, W0
001B1A  780180     MOV W0, W3
001B1C  B3C012     MOV.B #0x1, W2
001B1E  B3C041     MOV.B #0x4, W1
001B20  202C40     MOV #0x2C4, W0
001B22  0709C7     RCALL foo

无法理解 while 循环是如何实现的。 假设 [W14+6] 指的是存储Counter 的位置 RAM。

注意:为PIC24FV32KA304生成的代码

【问题讨论】:

  • 我猜271: } 下面可能还有几行 asm 行可以跳回循环。
  • 显然没有。无论如何,更新了问题以在 271 以下添加行。
  • 嗯,编译器可能会优化计数?如果代码只是循环,或者如果您在没有任何优化的情况下进行编译,您会得到什么?
  • 行在哪里:001BA、001BC 和 001BE?
  • @msbit 在 0x01B08 指令是跳转到 0x1B10。 0x1B10 不是 0x01B08 之后的下一个地址; 001B0A 在 0x01B08 之后。在 0x1B10,检查发生(如果 Counter

标签: assembly pic instruction-set pic24 dspic


【解决方案1】:

它已将您的代码顺序更改为:

GOTO A
B:  Counter++;
A:  if (Counter <= 249) GOTO B

这是我的 cmets 重新排序的程序集:

001B08  370003     BRA 0x1B10               // GOTO A
                         B: Counter++;
001B0A  90406E     MOV.B [W14+6], W0        // Copy Counter to W0
001B0C  E84000     INC.B W0, W0             // Increment W0
001B0E  984760     MOV.B W0, [W14+6]        // Put W0 back in Counter
                         A:  if (Counter <= 249) GOTO B
001B10  90406E     MOV.B [W14+6], W0        // Get counter to W0
001B12  404FE7     ADD.B W0, #0x7, [W15]    // Add 7 in modulo 256.
                                            // This is the same as subtracting 249
001B14  36FFFA     BRA LEU, 0x1B0A          // if result <= 0 GOTO B
                                            // else just drop through to code below

BRA LEU 是这里的关键循环指令。如果 Less than 或 Equal Unsigned,则表示 BRAnch。这意味着如果 C=0 或 Z=1 与前一条指令一样,则执行分支。

一个容易混淆的细节是C,是添加后的carry标志。但是,如果像本例中那样,我们想将ADD 视为减法,那么您应该将not(C) 视为借用。这就是为什么 BRA LEU 在 C=0 时采用分支的原因。

【讨论】:

    猜你喜欢
    • 2015-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多