C Language Compiled Code
C Language Compiled Code refers to the machine-readable version of a program written in the C programming language. When you write C source code in human-readable files (.c and .h), it cannot be executed directly by a computer. A compiler translates this source code through several stages including preprocessing, compilation to assembly, assembling into object code, and linking with libraries to produce a standalone executable file. The resulting compiled code consists of binary instructions that the CPU can interpret and run directly. This makes compiled code fundamentally different from the original C source code, which is intended for humans to read, write, and modify.
Source Code
The code is in C language (.c and .h files)
cat # Command used to display the contents of a file
test.c # The C source file whose contents will be printed to the terminal
(host) cat test.c
#include <stdio.h> // Includes the Standard Input/Output library so we can use functions like printf()
int main(){ // The main function: program execution starts here
printf(“Hello World!”); // Prints the text “Hello World!” to the standard output (usually the terminal)
return 0; // Ends the program and returns 0 to the operating system indicating successful execution
}
#include <stdio.h>
int main(){
printf("Hello World!");
return 0;
}
Pre-Processor
This step includes the headers and expand the macros, the generated file have the .i, .ii extensions
gcc # GNU C Compiler
-E # Tells gcc to run only the preprocessor (expands #include, #define, etc.)
test.c # The C source file being processed
| # Pipe operator; sends the output of the command on the left to the command on the right
head # Displays only the first 10 lines of the output
(host) gcc -E test.c | head
# 0 "test.c"
# 0 "<built-in>"
# 0 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 0 "<command-line>" 2
# 1 "test.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 28 "/usr/include/stdio.h" 3 4
Compiler
The expanded code/preprocessed code gets converted into assembly code, the generated file have the .s, .asm extensions
gcc # GNU C Compiler
-S # Tells gcc to compile the code into assembly language but not create an executable
test.c # The C source file being compiled
(host) gcc -S test.c
cat # Command used to display the contents of a file
test.s # The generated assembly language file from the compilation step
(host) cat test.s
.file "test.c"
.text
.section .rodata
.LC0:
.string "Hello World!"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
leaq .LC0(%rip), %rax
movq %rax, %rdi
movl $0, %eax
call printf@PLT
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Debian 14.2.0-16) 14.2.0"
.section .note.GNU-stack,"",@progbits
Assembler
The assembly code gets converted into object code/machine code, the generated file have the .o, .obj extensions
gcc # GNU C Compiler
-c # Compile the source code into an object file (machine code) without linking
test.c # The C source file being compiled
(host) gcc -c test.c
cat # Outputs the contents of the file
test.o # Object file containing compiled machine code
| # Pipe operator; sends output of the left command to the right command
xxd # Converts binary data into a hexadecimal (hex) and ASCII representation
| # Pipe operator again
head # Displays only the first 10 lines of the hex output
(host) cat test.o | xxd | head
00000000: cffa edfe 0c00 0001 0000 0000 0100 0000 ................
00000010: 0400 0000 b801 0000 0020 0000 0000 0000 ......... ......
00000020: 1900 0000 3801 0000 0000 0000 0000 0000 ....8...........
00000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000040: 6800 0000 0000 0000 d801 0000 0000 0000 h...............
00000050: 6800 0000 0000 0000 0700 0000 0700 0000 h...............
00000060: 0300 0000 0000 0000 5f5f 7465 7874 0000 ........__text..
00000070: 0000 0000 0000 0000 5f5f 5445 5854 0000 ........__TEXT..
00000080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000090: 3400 0000 0000 0000 d801 0000 0200 0000 4...............
...
...
...
Linker
The last step is combining the object code/machine code and .lib/.a static library files, the generated file have the .exe, elf, bin extensions
gcc # GNU C Compiler used to compile and link the program
test.c # The C source file being compiled
-o # Option to specify the name of the output file
test.bin # Name of the final executable binary file that will be created
(host) gcc test.c -o test.bin
cat # Outputs the contents of the file
test.bin # The compiled executable binary file
| # Pipe operator; sends output of one command to another
xxd # Converts binary data into hexadecimal and ASCII representation
| # Pipe operator again
head # Displays the first 10 lines of the output
(host) cat test.bin | xxd | head
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............
00000010: 0300 3e00 0100 0000 5010 0000 0000 0000 ..>.....P.......
00000020: 4000 0000 0000 0000 9036 0000 0000 0000 @........6......
00000030: 0000 0000 4000 3800 0e00 4000 1f00 1e00 ....@.8...@.....
00000040: 0600 0000 0400 0000 4000 0000 0000 0000 ........@.......
00000050: 4000 0000 0000 0000 4000 0000 0000 0000 @.......@.......
00000060: 1003 0000 0000 0000 1003 0000 0000 0000 ................
00000070: 0800 0000 0000 0000 0300 0000 0400 0000 ................
00000080: 9403 0000 0000 0000 9403 0000 0000 0000 ................
00000090: 9403 0000 0000 0000 1c00 0000 0000 0000 ...............
...
...