Lab 4

For this lab we are going to compile a simple hello world c program, int main(){ printf(“hello world\n”);} using different compiler optimization flags and then decompile the generated executable and analyze what’s really going on.

To start we are going to compile the program using the gcc compiler with three flags: -g to enable debugging information, -O0 for zero optimization and lastly -fno-builtin to not use builtin functions for optimizing.  Running this on our C program produces an 11kb executable file. We then analyze the code generated by the compiler with the objdump command with the –source flag which will show the source code along with the disassembly code. We then search for the section, which contains the part of the code we wrote. Since we used the –source flag we can see where the printf command is run. We can also see that the string is being stored in register eax which is the 32bit version of register a extended.

The first modification we’ll look at is adding the compiler option -static. When we add this flag the size of the program becomes almost 10x larger at 90kb. This is because the compiler packaged all of the libraries we included in the program allowing the program to run dependency free. When we decompile we can see more sections which represent the packaged libraries.

The next modification is taking out the -fno-builtin flag. When we take out this flag we allow the compiler to use built in functions to optimize. What this did was it allowed the compiler freedom to accomplish our task using methods it deems fastest. In this case the compiler scanned our printf call for the argument count and when we decompile our code and go to the main section we can see that it chose a function called puts to perform our printing instead of printf.

We then took out the -g flag we could no longer see information of where our printf and int main source code translate to assembly. The source file was a bit smaller around 8kb.

We then modified our code and gave printf three integer arguments. When we looked at objdump we saw each integer was placed in it own general purpose 32 bit register for example %eax, ebx and ecx.

Next we moved printf to a seperate function called output and in the object code we could see that above <main> we now had a section called <output> where our original printf code was.

The final change we made was -O0 zero optimization to -O3 which is maximum optimization. When we looked at our obj code their were less lines of code to execute with some of the mov and push’s changed to xor. The size of the executable was a couple hundred bytes larger.

It was interesting to see how much work the compiler does to your code and how much and even how little control you actually have over the code you are writing. Its important to understand what the compiler is doing to at least some degree especially as software developers.




Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s