Below is the disassembly of following C code:
268: while (Counter < 250)
269: {
270: Counter++;
271: }
Disassembly:
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
Couldn't able to understand how the while loop has been achieved.
Assume that [W14+6] refers to location RAM where Counter
is stored.
Note: The code generated for PIC24FV32KA304
It has changed the order of your code your code to something like:
GOTO A
B: Counter++;
A: if (Counter <= 249) GOTO B
Here is the reordered assembly with my comments:
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
is the key looping instruction here. It means BRAnch if Less than or Equal Unsigned. This means the branch is taken if C=0 or Z=1 as left by the previous instruction.
A detail that it is easy to get confused about is that C
, is the carry flag after addition. But if, as in this example, we want to regard the ADD
as a subtraction then you should treat not(C)
as borrow. That's why BRA LEU
takes the branch if C=0.