9

I have a static library archive which I try to understand.

First I use 'ar' to extract the object files.
The object files ar "ELF 32-bit LSB relocatable, ARM, EABI5 version 1 (SYSV), not stripped"
Then I use 'objdump -D' to get the assembly instructions.

Now I'm observing the assembly listing and find some curious (to me) instructions.
Apparently, after a branch with link (bl), R0 is moved into R3, and the next instruction moves R3 to R0.

23c:    e1a00003        mov     r0, r3
240:    ebfffffe        bl      0 <atoi>
244:    e1a03000        mov     r3, r0
248:    e1a00003        mov     r0, r3

This happens multiple times in different object files within the archive.

In the end both R0 and R3 are set to the value of R0 when returning from the branch.
What could be a good explanation for this behaviour?

2
  • Hi and welcome to RE.SE! Could you show the surroundings of the code you gave? Perhaps four more lines before and after ...
    – 0xC0000022L
    Commented May 20, 2020 at 19:19
  • 1
    The interface to external library functions needs r0 to contain the data to process, and it returns its result in r0 as well. The compiler doesn't know (or doesn't care), so it sets up the call, calls the library function, then restores the registers to resume what it was doing. It's just some not optimized stuff.
    – Jongware
    Commented May 20, 2020 at 21:08

2 Answers 2

6

This is most likely code that was compiled without optimizations (-O0 ). In such code redundant operations are very common as the compiler faithfully translates individual statements to machine code but does not try to perform optimizations to remove or simplify redundant ones.

1

There can be hidden requirements that affect what code is written. Sometimes weird code is written to obtain a certain timing, like a new massively parallel 144 core microcontroller from GreenArrays, which may require a no-op before or after a branch, and the two moves may provide just the right timing. Also, special kinds of RAM like FRAM or the early core memory, may have needed "constant refresh". Furthermore, sometimes instructions have to be aligned to be on a certain word-multiple boundary (like a multiple of 4 or 8 or 16 or 32 or 64...) and two moves achieves that. These reasons (or other interesting answers I don't know about) might or might not be the reason (I don't really know), but that code isn't probably just "unoptimized"; writing a register one direction, then immediately back again has some kind of hidden logic to it. Code is never just code. It interacts with the laws of physics, peripherals, magnetism, timing, etc. And how may hours over the 60 per week the developer was. ;-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.