Question

With reference to this:
calculating FLASH utilisation by C code

I have decided to check the calculations of actual assembly instructions.
so my script counts the assembly instructions, lies in the assembly listing file of the feature enable code.
e.g.

if(TRUE == feature1_enable)
{
    // instruction counting starts here
    doSomething;
    .
    .
    .
    // instruction counting stops here
}

This gives me some counts x from which I can figure out the size of the code.

To cross check the result I decided to nm the object file of the feature code but nm gives the size of entire function and not the individual statements.
So I copied the code part for that feature in separate file, made the function of it, included necessary headers and declared variables to get this file compile (by taking care of locals would remain locals and globals would remain globals). so the new file looks like this:

#include "header1.h"
#include "header2.h"

global_variables;
void checkSize( void )
{
    local_variables;

    // feature1_enable code
    doSomething;
    .
    .
    .
 }

Now the function checkSize contains only the feature enable code so after compiling, if I nm the obj file, I should be able to get almost same result as assembly counts (apart from some extra size utilized by the function setup). But that not the case, I have received huge difference. (1335 bytes in the case of assembly instructions and 1458 bytes in the case of nm of obj file).
To get the further clarification, I have created assembly of the file with function checkSize and compared with original assembly file. I understand there is some extra stuff due to the addition of checkSize function but instructions of the feature enable code expected to be same (with the same compiler optimization and other options).
But they were not the same.

Now the question is why is there such difference in the assembly instructions for feature code inside big function and when I move it to the other file with the feature code alone.
Is there anything to predict the extra size in either case?

Was it helpful?

Solution

There could be several things happening here. To be sure you are going to have to read the actual assembly code and figure out what it is doing. The compiler is VERY clever when you have it set to a high optimization level. For example in your first code segment it is very possible for the compiler to have assembly statements out side of your

// instruction counting starts here
// instruction counting stops here

comments that perform work in between the comments. In your second example that optimization is not possible and all work needs to be done in the function. Also do not discount the amount of space the prolog and epilog of functions take. Depending on the instruction set of your processor and its stack and register usage it can be quite large. For example on Power PC there is no push many registers instruction and you have to push each individual register and pop each individual register off of the stack frame when enter and leaving a function. When you're dealing with 32 registers that can be quite a bit of code.

You could try a trick when you have high optimization levels set for you compiler. The compiler cannot optimize across "asm" statements as it does not know what happens in them. What you could do is put some dummy code in the "asm" statements. I personally like creating global symbols that are in the object file. That way I can get the address of the starting symbol and ending symbol and calculate the size of code in between. It looks something like this...

asm(" .globl sizeCalc_start");
asm(" sizeCalc_start: ");
// some code
asm(" .globl sizeCalc_end");
asm(" sizeCalc_end:");

Then you can do something in a function like

extern int sizeCalc_start;
extern int sizeCalc_end;
printf("Code Segment Size %d\r\n", &sizeCalc_end - &sizeCalc_start);

I've done this in the past and it worked. Have not tried to compile this so dunno you may need to mess around with it a bit to get what you want.

OTHER TIPS

Optimization is tricky. Within a big function (and the big file) the compiler has wider context, and may optimize more aggressively - reuse common expressions, pick shorter forms of branches, etc (hard to say exactly without knowing your target architecture).

PS: I am not quite sure how do you go from assembly count to the byte count.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top