简体   繁体   English

如何修复68HC11编译器制作无效的JMP / BRA代码

[英]How to fix 68HC11 Compiler from making invalid JMP/BRA codes

I am compiling C code for programming an EPROM for a device. 我正在编译用于为设备编程EPROM的C代码。 The compiler being used is the Hi-Tech C Compiler. 正在使用的编译器是Hi-Tech C编译器。 I believe it is version 7.80. 我相信它是版本7.80。

When I (Re-)Make my code, it produces a Binary (*.BIN) file for flashing to the EPROM. 当我(重新)创建我的代码时,它会生成一个二进制(* .BIN)文件,用于闪存到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. 似乎编译器正在更改Branch-Always(BRA)语句以错误地执行BRA 0 ,当转换为十六进制操作码时,编译器将其转换为JMP 0000 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. 但是我发现如果我对代码进行少量更改,则不同的BRA调用会获得完全相同的损坏。

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. 我现在处于这样的地步,我觉得我需要深入了解* .BIN文件本身,找到错误的BRA / JMP调用,并手动修复它。 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. 这个问题是每当我对代码进行更改然后创建一个新的二进制文件时,我将需要跟踪这个错误的BRA / JMP调用,计算应该存在的BRA调用的正确操作码,并自己编辑。 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. 以下是错误的BRA调用及其周围代码的示例。 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: 等效C代码,并附加了错误BRA / JMP发生位置的说明:

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: 这是来自编译的* .AS程序集文件:

    tsy
    ldx 3,y
    pshx
    ldx 1,y
    pshx
    ldx #u189
    bra 0

The above bra 0 assembly is invalid. 上面的bra 0程序集无效。 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). 在这种特殊情况下,根据Assembly文件中的标签,它应该是bra l28 (注意,这是L28,带有小写的L,以避免混淆。它是在汇编代码中定义得较低的标签,其中这个分支应该去)。

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. 以下摘录来自* .LST列表文件。

 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). 可以看出,它将bra 0转换为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. 我想找到一个解决方案,明确解决这种情况,使编译器不再破坏程序集中的随机BRA助记符,不需要我挖掘二进制文件,找到JMP调用,并每次手动修复它我改变代码的时间。

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. 为了澄清,我理解BRA 0JMP 0000 ,但编译器的原因不明(1)将BRA 0放入汇编文件而不是BRA l28 ,这应该是什么,以及(2)转换它创建二进制文件时到JMP 0000

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. 以下是我手动解决此问题的步骤。

  1. Re-Make the code. 重新制作代码。 This will compile new OBJ files and link them to create the Binary (*.BIN) file 这将编译新的OBJ文件并链接它们以创建二进制(* .BIN)文件
  2. Open the resulting Binary file (*.BIN) within some form of Hex Editor (I use HxD) 在某种形式的十六进制编辑器中打开生成的二进制文件(* .BIN)(我使用HxD)
  3. Search for the following hexadecimal values: 7E0000 . 搜索以下十六进制值: 7E0000 0x7E is the opcode for JMP to an absolute address in 68HC11. 0x7E是JMP到68HC11中的绝对地址的操作码。 If found, continue on. 如果找到,继续。 If not found, the code should be fine 如果没有找到,代码应该没问题
  4. Open each Code file (*.C) and compile them out to Assembly (*.AS) files and optionally Listing (*.LST) files 打开每个代码文件(* .C)并将它们编译为Assembly(* .AS)文件和可选的Listing(* .LST)文件
  5. Search through each Assembly (or Listing) file to find BRA 0 (note that the whitespace there is a tab character). 搜索每个Assembly(或Listing)文件以查找BRA 0 (请注意,空格中有一个制表符)。 Once found, continue 一旦找到,继续
  6. Determine the correct label that this line of Assembly should be branching to. 确定此行程序集应分支的正确标签。 This step can be quite difficult and I was using the wrong label at first. 这一步可能非常困难,我最初使用的是错误的标签。
  7. Open the Assembly file with the erroneous BRA 0 in it and change it to branch to the correct label, ie BRA L8 打开装配文件,其中包含错误的BRA 0 ,并将其更改为分支到正确的标签,即BRA L8
  8. With the Assembly file still open, compile it into an Object (*.OBJ) file. 在Assembly文件仍然打开的情况下,将其编译为Object(* .OBJ)文件。 This will use the updated (and hopefully correct) branch label 这将使用更新的(并且希望是正确的)分支标签
  9. Make the code. 制作代码。 Do not re-make . 不要重新制作 This will pick up that only the new Object file has changed and it will use it to create a new Binary file. 这将获取只有新的Object文件已更改,并将使用它来创建新的二进制文件。 This time it will not have the erroneous JMP0000 这次它不会有错误的JMP0000
  10. Optionally ( but recommended ) check the resulting Binary (*.BIN) file to ensure that it no longer has the hexadecimal values 7E0000 (可选)( 但建议 )检查生成的二进制(* .BIN)文件,以确保它不再具有十六进制值7E0000

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM