Once the pre-processing phase concludes, the source code is prepared for compilation.
During the compilation phase, the pre-processing code undergoes translation into assembly language.
So it's worth noting that compilers often incorporate significant optimization capabilities in this
phase, so these optimizations can be adjusted using the GCC uppercase or zero through GCC uppercase
or three.
So from 0 to 3 options in GCC.
So the level of optimization choosing can greatly impact the resulting disassembly as you will explore
in detail in next sections.
So now you might wonder why the compilation phase produces assembly language instead of directly generating
machine code.
So this design decisions becomes clearer when considering the multitude of programming languages in
existence.
So aside from C, there are numerous popular compiled languages like C Plus plus objective C, Common
Lisp, Delphi, Go and Haskell to just name a few.
So developing a compiler that directly emits machine code from each of these languages would be an incredibly
daunting and time consuming task.
Instead, it is more practical to emit assembly code, which is already quite challenging for developers,
and utilize a dedicated assembler that handles the final translation from assembly to machine code for
all supported languages.
Therefore, the output of the compilation phase is assembly code represented in a reasonably human readable
format with preserved symbolic information.
So in the case of GCC, which automates all compilation phases by default, you need to instruct it
to halt after the compilation stage and save the assembly files to disk.
To examine the emitted assembly as we did for in previous lecture for pre-processing phase.
So to achieve this you can use the s flag where where's is conventional extension for assembly files?
Additionally, the maxim here m a s m Intel option is passed to GCC instructing it to generate assembly
Intel syntax instead of the default AT&T syntax.
So to provide you with a visual representation, we will use visual and practical representation.
We will create an example code.
So here now let's create this code here.
GCC again, as we said, we will use the uppercase S and m a s m Intel here.
And after that we will input our C file, which is my app dot C here, and that's it.
It's compiled.
And what we're going to do is we will read the compilation example with Mousepad with some text editor
here.
Mouse pad.
The my app dot here.
As you can see, we have C and S, we will open the S, which just generated and here this is assembly
generated by the compilation phase for the Hello World Program.
And for now I won't go into details about the assembly code just for now.
But but what's interesting here is that the assembly code is relatively easy to read because the symbols
and functions have been preserved.
So for instance, constant and variable variables have symbolic names rather than like just addresses,
even if it's just an automatically generated name such as SC zero for the Nameless Hello World String,
and there's an explicit label for the main function.
The only function in this case here.
And the main function is going to be right here above LSB zero and.
And there's an explicit label for the um, also hello world String.
So.
And any reference code to the data are also symbolic, such as reference to this.
Hello world.
Here.
This.
Hello, world here.
And.
And you will have no such luxury when dealing with a stripped binaries.
Later in this course.
Here, for example, we have all the variable names and so on.
And in the next lecture we will go with the assembly phase.
So I'm waiting you in the next lecture.