In order to understand the content of this blog more clearly, it is recommended to download VScode and configure the relevant environment for practice (of course, only reading can also be understood). Download tutorial links: VScode installation, C/C++ environment configuration
Article directory
1. Program translation environment and execution environment
In any implementation of ANSIC, there are two distinct environments.
The first is the translation environment, where source code is converted into executable machine instructions.
The second is the execution environment, which is used to actually execute the code
translation environment
Each source file that makes up a program is individually converted into object code through the compilation process.
Each object file is bundled together by a linker to form a single and complete executable program.
The linker will also import any functions used by the program in the standard C function library, and it can search the programmer's personal program library and link the functions it needs into the program
Each source file is processed individually by the compiler to generate an object file.
Several stages of compilation itself
2. Detailed explanation of the program compilation process (continued from the above)
1. Precompilation process
Inclusion of header files in precompilation
After writing test.c (test.c is a C language program written by yourself), press ctrl and · (note that it is a apostrophe, the one below the esc key (if it doesn’t work, press the shift key at the same time)) and enter the command gcc test .c -E The result is:
If you want to observe the output content carefully, you can input it into the test.i file (the test.i file is created by the system). The specific method is as follows:
input the command gcc test.c -E -o test.i Input the above code into the test.i file (note that it is the .i file, not the other).
Comparison of test.c and test.i files:
So what is this?
We know that when writing a C program, a header file such as #include<stdio.h> needs to be added, and the header file will be included in the test.c file when the code is running. Enter the command gcc test.c -E -o test.i The test.i file generated at this time contains the simplified stdio.h and the written C program. This process is the inclusion of the header file in precompilation.
Deletion of comments and replacement of #define definitions
Modify the above code and regenerate the test.i file (if the test.i file is still unmodified, you need to save the test.c file first and then regenerate it).
The result is as follows:
It can be seen that the compiler deletes the comment and replaces the #define definition. This is the deletion of comments and the replacement of #define definitions .
2. Compilation process
translated into assembly code
Enter gcc test.i -S to generate the test.s file, open the test.s and you can see: the
generated test.s file at this time is the assembly code translated from the source code. (I believe everyone has a certain understanding of what assembly code is, so I won’t explain too much.) The process includes syntax analysis, lexical analysis, semantic analysis, and symbol summary . (The summary of symbols will be explained together with others at the end of the article)
3. Assembly process
convert to target file
Continuing from the above, enter the command gcc test.s -c to generate a test.o file, the result is as follows:
It can be seen that the file is a binary file and an object file (the suffix of the object file on VS is .obj and on gcc is .o ). The assembly process is to convert the assembly code into an object file and generate a symbol table ( the symbol table is explained together with others at the end of the article), which is convenient for the operation of the linker.
4. Linking process
The merging and relocation of the merged segment table and symbol table takes place during the linking process. (In the linker)
As mentioned above, each source file will be processed separately by the compiler to generate an object file, and the linking process is closely related to it.
Modified the above code slightly and added an add.c file. (The linking process will be explained together with the symbol summary and symbol table)
The modified code is as follows:
Summarizing symbols and forming symbol tables
In the symbol summary process, the code will be analyzed to find out whether there are global symbols (such as Add, main) in the code and summarize them, and then form a symbol table in the assembly process. (happens during compilation)
Merge Segment Table
Next, merge and relocate the merged segment table and symbol table. (Occurs during the linking process)
It needs to be mentioned here that the .o file, that is, the target file, has been generated at this time, and the target file has a format. Taking gcc as an example, the format of the object file is elf format. A brief overview of the process of merging segment tables follows .
Merging and relocation of symbol tables
Merge the above symbol tables, and determine the merged address according to whether the address is valid or not.
The frequent errors are also identified and reported in the process:
Finally, an executable program is generated.
Triple if helpful (⑅˃◡˂⑅)