assemblypicinstruction-setpic24dspic

How loops are implemented in PIC24F assembly code


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


Solution

  • 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.