PIC24F 汇编代码中如何实现循环
How loops are implemented in PIC24F assembly code
下面是以下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 生成的代码
它已将您的代码顺序更改为:
GOTO A
B: Counter++;
A: if (Counter <= 249) GOTO B
这是经过重新排序的程序集和我的评论:
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
是这里的关键循环指令。这意味着 BRAnch if Less than or Equal U没有签名。这意味着如果前一条指令留下的 C=0 或 Z=1,则采用分支。
一个容易混淆的细节是C
,是加法后的进位标志位。但是,如果像本例中那样,我们想将 ADD
视为减法,那么您应该将 not(C)
视为 借用 。这就是为什么 BRA LEU
在 C=0 时选择分支。
下面是以下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 生成的代码
它已将您的代码顺序更改为:
GOTO A
B: Counter++;
A: if (Counter <= 249) GOTO B
这是经过重新排序的程序集和我的评论:
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
是这里的关键循环指令。这意味着 BRAnch if Less than or Equal U没有签名。这意味着如果前一条指令留下的 C=0 或 Z=1,则采用分支。
一个容易混淆的细节是C
,是加法后的进位标志位。但是,如果像本例中那样,我们想将 ADD
视为减法,那么您应该将 not(C)
视为 借用 。这就是为什么 BRA LEU
在 C=0 时选择分支。