[C Advanced] Program Environment

content

1 Introduction

2. Translation environment

   (1) Compile

           (1) Preprocessing

           (2) Compilation link

           (3) Assembly

    (2) Links

3. Operating environment


1 Introduction

In any implementation of ANSI C, there are two distinct environments.

  • The first is a translation environment, in which source code is translated into executable machine instructions.
  • The second is the execution environment, which is used to actually execute the code

For example, we wrote a source file test.c, which will become the test.exe file after a detailed process. This article will explain in detail how the test.c file is converted to the test.exe file. In fact, there are two main A large process, 1 is compiling, 2 is linking. The main environment on which this process depends is the translation environment, and the environment on which the test.exe file wants to run is the running environment.

  • The text begins:

2. Translation environment

  • Look at a picture first:

Suppose we wrote the three source files test.c, contact.c, common.c in a project. Each .c file will be processed by the compiler, and finally each generates an object file (with .obj as the suffix under windows), these object files and the link library are passed through the linker to finally generate an executable program.

  1. Each source file that makes up a program is individually converted into object code through the compilation process.
  2. Each object file is bundled together by the linker to form a single and complete executable program.
  3. The linker also introduces any functions in the standard C function library that are used by the program, and it can search the programmer's personal library and link the functions it needs into the program.
  • Explain Article 3: (using printf as an example)

 Libraries is a library, and printf is included in a static library named with the suffix .LIB . To use pritnf, the link library of these .LIB files should be linked in

  • The compilation can be divided into the following three parts (use a picture to transition first)

The following will describe in detail how a source file is converted into an executable program.

(1), compile

  • First look at a piece of code:
#include<stdio.h>
int g_val = 2021;
int Add(int x, int y)
{
	return x + y;
}
int main()
{
	int a = 10;
	int b = 20;
	int ret = Add(a, b);
	printf("%d\n", ret);
	return 0;
}

In the VS environment, we need to press ctrl+F5 to execute the program , but at this time, the executable program will be generated directly, and the specific conversion process cannot be compilation and splitting into preprocessing + compilation + assembly

  • Notice:

In the linux environment, if you use gcc to compile the test.c file directly, it will generate a file of a.out by default, which is also an executable program. In order to avoid directly generating an executable program like the VS environment, it cannot be observed. to the details, so we need to stop after preprocessing, stop after compilation, stop after assembly. The operation is as follows:

1. Preprocessing options gcc -E test.c -o test.i

After the preprocessing is completed, it stops, and the results generated after the preprocessing are placed in the test.i file.

2. Compile option gcc -S test.c

After the compilation is completed, it stops and the result is saved in test.s.

3. Assemble gcc -c test.c

After the assembly is completed, it stops and the result is saved in test.o.

  • The specific process is as follows:

(1) Preprocessing

Use the gcc test.c -E option to compile the test.c file in the linux environment , you can make it stop after preprocessing

After this command is executed, a bunch of codes will appear. At this time, we can use the gcc -test.c -E > test.i operation to redirect and output a bunch of codes to the test.i file and open the test. .i file

Look at the three pictures first:

  • Figure 1:

  •  Figure II:

At this point, we add some macro definitions to the test.c file, and then compare it with the preprocessing stage:

  •  Figure 3:

What happens in the preprocessing stage when we put some comments in the test.c file?

  • Through the above three pictures: three conclusions can be drawn in the preprocessing stage:
  1. Completed including header files
  2. Replacement of symbols and macros defined by #define
  3. Comment deletion
  • The above three operations are all text operations.

(2) Compilation link

After the above preprocessing, it comes to the compilation link:

We use the gcc test.i -S command to compile, and finally generate the test.s file, we open the test.s file to see:

Take a simple snippet first:

 The above code is the assembly code, and it can be concluded that:

  • The assembly process is to convert the C language code into assembly code, which mainly does the following four contents:
  1. Parsing
  2. lexical analysis
  3. Semantic Analysis
  4. Symbol summary
  •  First briefly explain the notation summary:

Summarize global variables and function names, such as main and global variable g_val, the usefulness of symbol summarization is reflected in the next stage of assembly and linking, which will be described in detail below:

  • A simple example:

(3) Assembly

After we compile, the test.s file is generated, and then we enter the assembly

We use the gcc test.s -c command to assemble, and finally generate a file such as test.o, and this test.o file is similar to the test.obj file on Windows, that is, the object file is generated. We open the test.o file: (simple interception)

The above picture is actually binary information. This leads to the conclusion of the compilation:

  1. Convert assembly code to machine instructions (binary instructions) 
  2. form symbol table

And what is the relationship between the generated symbol table in assembly and the symbol summary in compilation? The following is a detailed introduction:

  • To give another example:

As shown in the figure, we created two source files, add.c and test.c

 In the Linux environment, the test.c file and add.c file will be preprocessed, compiled, and assembled to generate the corresponding test.o file and add.o file.

The symbol table formed in the assembly is actually a table, which contains both the summarized symbols and the addresses corresponding to these symbols.

  • Take the example above:

  • Note:

The Add symbol summarized by test.c is briefly indicated with a red marker because Add is declared and the exact address cannot be found.

 After understanding the symbol table, when generating a .o file (object file), multiple .o files are linked by a linker to generate an executable program, the test.exe file. This process link plays a major role, as detailed below:

(2), link

  • There are two main operations implemented by the link:
  1. merge segment table
  2. Symbol table merging and symbol table relocation

As shown in the figure above, the test.c file and add.c file will be preprocessed, compiled, and assembled to generate the corresponding test.o file and add.o file. To link them together, the merged segment table must first occur.

  • Merge segment table:

A file like add.o has its byte format, which divides itself into segments. Naturally, test.o will be divided like this. The format of the two sections is the same, but the content is different. The merged segment table is to merge the data on the corresponding segments together, as shown in the figure:

  • Note: The format of these segment tables are all elf file formats 
  • Symbol table merging and symbol table relocation:

 After the above two operations are completed, the executable program can be generated, and the entire translation environment is explained at this time.

3. Operating environment

  • The process of program execution:
  1. The program must be loaded into memory. In an environment with an operating system: Usually this is done by the operating system. In a stand-alone environment, the loading of programs must be arranged manually, possibly by placing executable code into read-only memory.
  2. Execution of the program begins. Then call the main function.
  3. Start executing program code. At this point the program will use a runtime stack (stack) to store the function's local variables and return addresses. Programs can also use static memory. Variables stored in static memory retain their values ​​throughout the execution of the program.
  4. Terminate the program. Terminates the main function normally; it may also terminate unexpectedly.

Guess you like

Origin blog.csdn.net/bit_zyx/article/details/122888817