# While loop instructions in pic disassemby not clear

In an efford to save space I try to reduce the generated C code with inline asm(""); Looking at the original disassembly and good working code I do not understand line 0x17E4.

    // This loop ends when the enter key is pressed
while EnterOpen(){                 // SW3 = RE2

if ArrowUpClosed(){             //    RE0
while ArrowUpClosed(){};
asm("call MBD");
if ArrowUpOpen()
LCDGotoPos(ArrowUp[index]);
};
if ArrowDownClosed(){          // SW3 RE1
while ArrowDownClosed(){};
asm("call MBD");
if ArrowDownOpen()
LCDGotoPos(ArrowDown[index]);
};
if ArrowRightClosed(){          // SW4 RC1
while ArrowRightClosed(){};
asm("call MBD");
if ArrowRightOpen()
LCDGotoPos(ArrowRight[index]);
};
if ArrowLeftClosed(){           // SW5 RC0
while ArrowLeftClosed(){};
asm("call MBD");
if ArrowLeftOpen()
LCDGotoPos(ArrowLeft[index]);
};
};
Pause(300);
return;
// a little trick to save space
asm("MBD:");
delay();

// This loop ends when the enter key is pressed
while EnterOpen(){                 // RE2
0x178E: BCF STATUS, 0x5
0x178F: BCF STATUS, 0x6
0x1790: BTFSS PORTE, 0x2
// jumping out of the loop as expected
0x1791: GOTO 0x7E5
// returns to the beginning? but during execution goes to 0x1792.
// The way I expect
0x17E4: GOTO 0x78E
// during execution
//if ArrowUpClosed()             //   RE0
0x1792: BTFSC PORTE, 0x0

//other code
} // end of while EnterOpen

//    Pause(300);
0x17E5: MOVLW 0x8

• This is disassembly. What is the original assembly code (and do you have it)? – Anonymous May 12 '17 at 8:25
• Erm is it just the ordering of the lines which is wrong? I mean 0x1792 should be in front of 0x17e4. And your question is a bit hard to understand as there are comments which are part of the question and comments for old code (I think?). – Arsenal May 12 '17 at 8:25
• I have added the complete C code of the routine. The disassembly code is comming from the C code – Decapod May 12 '17 at 8:39
• According to @Arsenal's finding I would question quality of disassember output. In its output it has sequence of 0x1791, then 0x17E4, and then 0x1792. The middle location, 0x17E4, is out of the program counter sequence. – Anonymous May 12 '17 at 8:54
• Meanwhile I agree with Anonymous. I changed the instruction handling to my knowledge and datasheet and the routine works also in asm – Decapod May 12 '17 at 9:01

Caveats: It has been more than a decade since I routinely wrote PIC assembly code (and used their C compiler -- not sure if my license is any good anymore, either.) You also didn't say which compiler you are using, so I can't go get a copy and see what it generates. And I don't even know if you are using a PIC16 or a PIC18 (different creatures, with the PIC18 having nicer arrangements for assembly code.) Finally, I am assuming you pretty much are up on things with the PIC and that in some ways you will be more able than I am to answer specific questions about its assembly code because of your current work versus my decade old (and more) knowledge about it.

Assumptions:

1. It's a PIC16 (or lower) family part and not a PIC18.
2. When you write in assembly code you are using a real assembler and not hand-coding machine code.
3. You haven't been looking closely at the generated machine code.
4. You're unstated confusion is over the address there.

Assuming the above are correct, I suspect you may have missed out noticing that the GOTO instruction only uses 11 bits for the address. It can only branch within the current code "page," where the upper address bits remain unchanged in the branch to a new address.

When you write in assembly, you usually use labels. Even if you used absolute addresses, the assembler still does "do the math" for you to make sure that the address you specify is "within reach." So you wouldn't even know one way or another what is going on unless you look closely at the machine code it generates.

Let me document what I see above (along with a missing column which I sincerely wish you'd have also included):

Address    Machine Code    Code Lines             Description
0x178E                     BCF STATUS, 0x5        These two lines make sure that data access
0x178F                     BCF STATUS, 0x6            is on page 0 where PORTE is at.
0x1790                     BTFSS PORTE, 0x2       Skip GOTO if the loop should continue.
0x1791                     GOTO 0x7E5             Go out of loop to 0x17E5 (past the GOTO.)
0x1792                     BTFSC PORTE, 0x0       "if ArrowUpClosed()"
0x1793                                            <>
0x1794                                            <>
...                                             ...
0x17E1                                            <>
0x17E2                                            <>
0x17E3                                            <>
0x17E4                     GOTO 0x78E             Branch to address 0x178E (start of loop.)
0x17E5                     MOVLW 0x8


If you note that there are only 11 bits in the encoded machine instruction for the GOTO, then you can see why the entire "0x17E5" or "0x178E" can't be encoded into the machine word. However, that fact doesn't prevent the assembler and/or compiler from knowing that the address can in fact be properly reached (or not, indicating that more code may be needed to make a more distant transfer.)

The compiler's code works, I think you say. You also say that when you wrote some assembly code of your own that it also worked. I believe both of these are true. But the issue may simply be that you haven't realized how an assembler (more importantly, how a linker) works inside to generate correct code or to generate errors.