Search code examples
gccassemblyembeddedthumb

ARM Thumb-2, GCC, code changes, and the `stmdaeq` instruction


I'm using and STM32F4 (Cortex-M4) MCU and compiling with arm-none-eabi-g++ (I'm using C++).

I have a requirement to reduce the amount of time it takes to upload my binary to the MCUs flash memory. I have figured out I can do this by only uploading changes to my binary between modifications. However, the compiler is generating some interesting code that is making this impossible.

Consider the following 2 programs:

(1)

int main()
{
    printf("hello");
    return 0
}

(2)

int main()
{
    //printf("hello");
    return 0
}

By simply removing the printf call, the binary is drastically different. I can see this by disassembling the code using arm-none-eabi-objdump -D mybinary. Here's a sample of the differences in WinMerge:

enter image description here

As can be seen in the image, almost all functions have a slightly different stmdaeq instruction, and I want to know more about this.

An answer to this question will include the following:

  • I know what the stmdaeq instruction is, but why is it at the end of nearly all functions? Is this the function's epilogue?
  • Is there anything I can do (compiler options or otherwise) to ensure that minor code changes, like my example above, don't cause such changes throughout the entire binary?

I'm using the GNU Tools for ARM Embedded Processors GCC toolchain.

Your help will be most appreciated.


Solution

  • It's not an instruction, it's a constant in the code section. You can tell because it's right past the return statement, which is pop ...,pc or bx lr.

    Its purpose? The only purpose that I can see is that it stores an address of a global variable. Most likely, it's a link-time constant - i. e. it's resolved by linker, not by the compiler. But its code is present in system functions (alloc-related, etc). So you can't get rid of it - the bytes for the constant are there in the RTL object file, along with a relocation instruction to the linker.

    It's probably an artifact of C++ RTL. Try switching to C.