Program Running Mechanism,
After writing the program, press Ctrl + F5 to finish. We never care about the process. If it is correct, we don't know where to start. This is also a constant headache for many new programmers. However, the great gods quickly locked the error range and checked them one by one. Next we will share with you some of the mechanisms behind program running.
The C language program we compile is a source program. Computers cannot directly identify and execute commands written in advanced languages. The compiler must translate the C source program into a binary program, then connect the target program with the system function library and other target programs to form an executable program.
For example:
1 #include <stdio.h>2 int main()3 {4 printf("hello world !\n");5 return 0;6 }
None of the simplest programs in history. Start with this simple program.
In fact, the above process can be divided into four steps: preprocessing, compilation, assembly, and link ,.
I. Preprocessing:
First, the source code file hello. c and related header files, such as stdio. h, are pre-compiled into a. I file by the CPP pre-compiler. For a C ++ program, the extension of its source code file may be. CPP or. cxx, the extension of the header file may be. hpp, and the extension of the pre-compiled file may be ii. The pre-compilation process in the first step is equivalent to the following command (-E indicates that only pre-compilation is performed)
Debugging code on linux:
gcc -E hello.c -o hello.i
The pre-compilation process mainly processes the pre-compilation commands starting with "#" in the source code files. For example, "# include". # define ". The main processing rules are as follows:
1. Delete All "# define" and expand all macro definitions.
2. process all conditional pre-compilation commands, such as "# if", "# ifdef", "# elif", "# else", and "# endif ".
3. process the "# include" pre-Compilation instruction and insert the included files to the pre-Compilation instruction location. Note that this process is recursive, that is, the contained file may contain other files.
4. delete all the primary keys "1/" and "/**/".
5. Add the row number and file name identifier, for example, #2 "hello. c "2, so that the compiler generates the line number information for debugging during compilation and displays the line number when a compilation error or warning occurs during compilation.
6. Keep all # pragma compiler instructions because the compiler needs to use them.
The pre-compiled. I file does not contain any macro definition, because all macros have been expanded and the included files have been inserted into the. I file. Therefore, when we cannot determine whether the macro definition is correct or whether the header file contains the correct information, we can check the pre-compiled file to determine the problem.
After this step is compiled, the file contains a large header file, and other code. It is not convenient to paste it here. You can debug it on your own.
Ii. Compilation:
The compilation process is to conduct a series of lexical analysis, syntax analysis, Semantic Analysis and Optimization of the pre-processed files to produce the corresponding assembly code files, this process is often the core part of the entire program building. It is also one of the most complex parts that involve compilation principles. In the next section, we will briefly introduce the specific compilation steps. Because it is not the core content introduced in this book, it is just an introduction. The above compilation process is equivalent to the following command: $ gcc-S hello. I-o hello. s
1 .file "hello.c" 2 .section .rodata 3 .LC0: 4 .string "hello world !" 5 .text 6 .globl main 7 .type main, @function 8 main: 9 pushl %ebp 10 movl %esp, %ebp 11 andl $-16, %esp 12 subl $16, %esp 13 movl $.LC0, (%esp) 14 call puts 15 movl $0, %eax 16 leave 17 ret 18 .size main, .-main 19 .ident "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-4)" 20 .section .note.GNU-stack,"",@progbits
Both methods can get the Assembly output file hello. s. for C-language code, this pre-compiled and compiled program is cc1plus, f is for C ++, and for C ++, there is a corresponding program called cc1plus.
Therefore, in fact, the gcc command is only the packaging of these background programs. It will call the pre-compiled program, assembler as, and linker ld according to different parameter requirements.
Iii. Assembly:
Assembler converts assembly code into commands that can be executed by machines. Each assembly statement corresponds to almost one machine command. Therefore, the compilation process of the assembler is relatively simple compared with that of the compiler. It has no complicated syntax, no semantics, and no instruction optimization is required, just according to the comparison table of Assembly commands and machine commands, you can translate them one by one. The name of "assembly" also comes from this. The above assembly process can be completed by calling the assembler:
As hello. s-o he11o. o
You can also use the gcc command to directly output the target file (ObjectFile) from the C source code file after pre-compilation, compilation, and compilation ):
Gcc-c hello. c-o hello. o
4. Links:
The link is usually a confusing process. Why does the assembler output a target file instead of an executable file? What does the link Process contain? Why? This may be a question for many readers. It is precisely because these questions are always lingering. Therefore, we use the length of this chapter to analyze the link, specifically the static link chapter. Let's take a look at how to call ld to generate a normal operation of the helloworld program:
ld-static /u8r/lib/crt1.o /usr/1ib/crti.o/u8r/1ib/gcc/i486-1inux-gnu/4.1.3/crtbeginT.o-L/u8r/lib/gcc/i486-1iux-gnu/4.1.3-L/u8r/1ib-L/11b hello.o--start-group-1gcc-1gcc_eh-lc--end-group /u8r/1ib/gcc/1486-11nux-gnu/4.1.3/crtend.o/usr/1ib/crtn.o
If all the paths are omitted, the preceding command is:
ld -static crt1.o crti.o crtbeginT.o hello.o -start -group -lgcc -lgcc_eh -lc-end-group crtend.o crtn.o
We can see that we need to link a lot of files to get the "a. out", that is, the final executable file. The final machine runs the. o file. When we understand these processes, we can better understand where a program will go wrong.
5. Execution
Program execution is also divided into many stages
Phase 1: the operating system loads the program into the memory, and those variables that are not stored in the stack that have not been initialized will get the initial values at this time.
Phase 2: a small startup program that processes daily things is connected with the executable program, and then the main function is called.
Stage 3: Code Execution started
The program will use
Runtime StackThe stack is used to store the "local variables" and "return address" of the function ";
The program can also be used
Static MemoryThe variable stored in static memory will keep its value during program execution.
Stage 4: the final stage of the program is the termination of the program. Of course, termination is also divided into "normal termination" and "Abnormal Termination". Normal termination is the return of the main function, unusual termination may be caused by multiple circumstances. Note: All commands in this article are debugging on the linux platform, the vim editor, and the gcc compiler. References: Yu jiazi, Shi fan, Pan aimin. self-cultivation of programmers Beijing: Electronic Industry Press, 2009