I am compiling C code for programming an EPROM for a device. The compiler being used is the Hi-Tech C Compiler. I believe it is version 7.80.
When I (Re-)Make my code, it produces a Binary (*.BIN) file for flashing to the EPROM.
I have found that the compiled code often comes with one single line in the Assembly that breaks the code and causes the device to shut off whenever it is reached. It seems as though the Compiler is changing a Branch-Always (BRA) statement to erroneously do BRA 0
, which when converted to hex opcodes gets converted to JMP 0000
by the compiler. This causes the code to reach an unexpected area of the code and thus the device shuts off.
When re-Making the code, this erroneous branch is always in the same place. However I find that if I make small changes to the code, a different BRA call gets this exact same corruption.
I am now at the point where I feel like I need to dig into the *.BIN file itself, find the erroneous BRA/JMP call, and fix it manually. The issue with this is that whenever I make changes to the code and then make a new Binary file, I will need to track down this erroneous BRA/JMP call, calculate what the correct opcodes would be for the BRA call that should be there, and edit it myself. I would much rather not have to do this every time I make a change as this can take up a lot of time.
Here is an example of the erroneous BRA call and the code around it. I am sorry but I cannot provide the full source code for this as it is for a proprietary system but I can share the Assembly and hex codes around the issue.
Equivalent C code with added note on where the erroneous BRA/JMP is happening:
if ( variable > 5.5 )
{
printf( "Variable is: %f", variable );
// right here is where the BRA 0 is in the Assembly (JMP 0000 in hex). It should be branching to function_call() below, but it is not
}
else
{
if ( variable < 5.4 )
{
// bunch of code in here
}
else
{
// if/else in here with some printf() calls
}
}
function_call();
This is from the compiled *.AS assembly file:
tsy
ldx 3,y
pshx
ldx 1,y
pshx
ldx #u189
bra 0
The above bra 0
assembly is invalid. In this particular case as per the labels within the Assembly file, it should be bra l28
(note, this is L28, with a lower-case L, to avoid confusion. It is a label that is defined lower in the Assembly code, where this branch should be going to).
This results in the following hexadecimal opcode:
18 30 CD EE 03 3C CD EE 01 3C CE F6 DD 7E 00 00
The following excerpt is from the *.LST Listing file.
758 03E0' 18 30 tsy
759 03E2' CD EE 03 ldx 3,y
760 03E5' 3C pshx
761 03E6' CD EE 01 ldx 1,y
762 03E9' 3C pshx
763 03EA' CE 005D' ldx #u189
764 03ED' 7E 0000 bra 0
As can be seen, it converts the bra 0
to JMP 0000
(7E 0000).
I would like to find a solution that will definitively resolve this situation such that the compiler will no longer corrupt a random BRA mnemonic within the assembly that does not require me to dig through the binary file, find the JMP call, and manually fix it every time I change the code.
To clarify, I understand that BRA 0
is not the same as JMP 0000
, however the Compiler is for unknown reasons (1) putting BRA 0
in the Assembly file instead of BRA l28
which is what it should be, and (2) converting this to JMP 0000
when creating the binary file.
Unfortunately at this stage the only solution I have found has been a workaround to manually edit and fix the Assembly rather than a definitive fix that stops the issue from happening in the first place.
Here are the steps that I took to manually work around the issue.
7E0000
. 0x7E is the opcode for JMP to an absolute address in 68HC11. If found, continue on. If not found, the code should be fineBRA 0
(note that the whitespace there is a tab character). Once found, continueBRA 0
in it and change it to branch to the correct label, i.e. BRA L8
7E0000