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.
- It's a PIC16 (or lower) family part and not a PIC18.
- When you write in assembly code you are using a real assembler and not hand-coding machine code.
- You haven't been looking closely at the generated machine code.
- 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()"
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.
The assembler and C compiler will generate an object file that contains what amounts to "strings" of literal byte values + periodic "patch up" records which instruct the linker exactly where and exactly how to fix up bits and pieces of those literal strings, during the linking phase when the code actually gets placed somewhere. For assembly generated code, I'm pretty sure this is a very simple process and the linker will complain if you write instructions that would require an out-of-range encoding. For the C compiler, I'm not so sure about the complexity extended to the linker. But it is possible that the C compiler doesn't want to worry about whether or not some bit of code spans across a code page and instead just provides the linker with enough added information so that the linker can make the determination and "automatically extend" a string of bytes as needed (making the linking process more complex but also leading to less confusion of the typical C coder.)
I've had my say about it. It could be that I totally misunderstood your quandary here. I just woke up and who knows if I'm just sleep-walking through this. But there it is. Perhaps you could clarify the device, etc., too?
For those interested in some history about the XC8 C compiler, as well as some information about the optimizations differences in the PRO versions, I found this link immediately useful. From it, I can see that the XC8 compiler is basically the Hi-Tech compiler code, with added "impairments" in order to "improve" motivations to buy the PRO version of their compiler toolset. Interesting details there.