The story behind GCC; allocation of constant variables in C programs

?
1. Learn and master the compilation and assembly process of executable programs.
The learning tasks are as follows: read, understand and study the materials “Using gcc to generate static libraries and dynamic libraries.pdf” and “Generation and use of static library .a and .so library files.pdf”, please do so under the Linux system (Ubuntu) Copy it again.
1. Edit the subroutine first
?

Then compile .c->.o

Create a static library from the .o file and use it

Use static library: gcc main.c libmyhello.a -o hello


Generate the .o file into a dynamic library and use the dynamic library gcc -shared -fPIC -o libmyhello.so hello.o

At this time, an error will be reported when running. Just mv libmyhello.so /usr/lib can solve the problem.

Generation and use of static library .a files

(1) Generate target file gcc -c A1.c A2.c
(2) Generate static library .a file. ar crv libafile.a A1.o A2.o
(3) Use the .a library file to create an executable program. gcc -o test test.c libafile.a
(4) Run the program. ./test
Generation and use of shared library .so files
(1) Generate target file xxx.o
The .o file generated here must be added with “-fpic” (small mode, less code), otherwise an error will occur when generating the .so file gcc -c -fpic A1.c A2.c
(2) Generate shared library .so file. gcc -shared *.o -o libsofile.so
(3) Use the .so library file to create an executable program. gcc -o test test.c libsofile.so
(4) Run the program. ./test

2. The specific operations are as follows:
The first four lines of the static library
Later dynamic library

Comparison of size
dynamic library

static library

It is obvious that static libraries are much smaller than dynamic libraries
two,
Linux gcc common commands
Preprocessing: gcc -E test.c -o test.i
Compile to assembly code: gcc -S test.i -o test.s
Assembly: gcc -c test.s -o test.o
Connection: gcc test.o -o test
Error checking: gcc -pedantic test.c -o test

Disassembly

three,
1. Concept
(1) The allocation address programming display of stm32’s heap, stack, and global variables\\
In an STM32 program code, from the high memory address to the low memory address, the stack area, heap area, and global area (static area) are distributed in sequence. , constant area, code area, among which the .bss segment is distributed at high addresses in the global area, and the data segment is distributed at low addresses.
stack
Temporarily created local variables are stored in the stack area. When a function is called, its entry parameters are stored in the stack area. When a function returns, its return value is stored in the stack area. Local variables defined by const are stored in the stack area.
2) Heap area (heap)
The heap area is used to store dynamically distributed memory segments during program running, which can be increased or decreased. Functions such as malloc can be used to dynamically distribute memory. Memory distributed by the malloc function must be released using free, otherwise memory leaks will occur.
3) Global area (static area)
The global area consists of .bss segment and .data segment, which is readable and writable.
4) bss section
Uninitialized global variables are stored in the .bss section.
Global variables initialized to 0 and static variables initialized to 0 are stored in the .bss section.
The .bss section does not occupy executable file space, and its contents are initialized by the operating system.
5) data segment
Initialized global variables are stored in the .data section. Static variables are stored in the .data section. The .data section occupies executable file space, and its content contains program initialization. Global variables defined by const are stored in the .rodata section.
6) Constant area
Strings are stored in the constant area. The contents of the constant area cannot be modified.
7) Code area
Program execution code is stored in the code area. String constants may also be stored in the code area
(2) Concepts and conclusions to be verified The execution of c program is the process of loading static files into memory. There are two memory attributes, as shown below:
Static allocated memory: memory that is determined when the program is compiled and linked.
Dynamically allocated memory: memory allocated and recycled when the program is loaded, transferred, and executed. The address of the stack increases downward, and the address of the heap increases upward. Static variables increase the address downward, and global constants increase the address upward\\
The address of a function increases upward from the function to the stack area. The overall address increases gradually from low address to high address.
2. Program in ubuntu system and output information for verification
(1) Open ubuntu and write a .c file. The code is as follows:

#include <stdio.h>
#include <stdlib.h>
int k1 = 1;
int k2;
static int k3 = 2;
static int k4;
int main( )
{ static int m1=2, m2;
int i = 1;
char *p;
char str[10] = "hello";
char *var1 = "123456";
char *var2 = "abcdef";
int *p1=malloc(4);
int *p2=malloc(4);
free(p1);
free(p2);
printf("Stack area-variable address\\
");
printf("i:%p\\
", & amp;i);
printf(" p:%p\\
", & amp;p);
printf(" str:%p\\
", str);
printf("\\
Heap area-dynamic application address\\
");
printf(" %p\\
", p1);
printf(" %p\\
", p2);
printf("\\
.bss section\\
");
printf("Global external no initial value k2: %p\\
", & amp;k2);
printf("Static external no initial value k4: %p\\
", & amp;k4);
printf("Static internal no initial value m2: %p\\
", & amp;m2);
printf("\\
.data section\\
");
printf("There is an initial value k1 outside the global: %p\\
", & amp;k1);
printf("Static external has initial value k3: %p\\
", & amp;k3);
printf("Static internal initial value m1: %p\\
", & amp;m1);
printf("\\
Constant area\\
");
printf("Literal constant address: %p\\
",var1);
printf("Literal constant address: %p\\
",var2);
printf("\\
code area\\
");
printf("Program area address: %p\\
", &main);
return 0;
}

(2) Compilation

The execution results can verify the above conclusion.
3. Programming for stm32 system in Keil

#include “stm32f10x.h”
#include “bsp_usart.h”

char global1[16];
char global2[16];
char global3[16];

int main(void)
{
char part1[16];
char part2[16];
char part3[16];

USART_Config();

printf(“part1: 0x%p\\
”, part1);
printf(“part2: 0x%p\\
”, part2);
printf(“part3: 0x%p\\
”, part3);

printf(“global1: 0x%p\\
”, global1);
printf(“global2: 0x%p\\
”, global2);
printf(“global3: 0x%p\\
”, global3);
while(1)
{

}

}

(2) Compile and burn the HEX file into the chip
(1) Compile and burn

(2) Observe results and verify

part1, part2, and part3 are local variables in the stack, and their addresses gradually decrease. global1, global2, and global3 are global variables in the static area, and their addresses gradually increase.
(3) Modify the code and continue verification
(1) Modify the main.c code as follows:

#include “stm32f10x.h”
#include “bsp_usart.h”
#include <stdlib.h>

int main(void)
{
static char st1[16];
static char st2[16];
static char st3[16];
char *p1;
char *p2;
char *p3;

USART_Config();

printf(“st1: 0x%p\\
”, st1);
printf(“st2: 0x%p\\
”, st2);
printf(“st3: 0x%p\\
”, st3);

p1 = (char *)malloc(sizeof(char) * 16);
p2 = (char *)malloc(sizeof(char) * 16);
p3 = (char *)malloc(sizeof(char) * 16);

printf(“p1: 0x%p\\
”, p1);
printf(“p2: 0x%p\\
”, p2);
printf(“p3: 0x%p\\
”, p3);
while(1)
{

}

}

Define static variables and pointers and return their addresses to the host computer.
(2) Repeat the above operations to continue verification

st1, st2, st3 are all static variables, and their addresses increase sequentially. p1, p2, and p3 are pointers in the heap, and their addresses also increase in sequence.
Summary
The main differences between static libraries and dynamic libraries generated by gcc are as follows:

1. Link method:
Static library (.a): Linked at compile time. After the program links to the static library, the code and data in the static library will be directly copied to the program and become part of the program itself.
Dynamic library (.so): Runtime linking, the dynamic library will be loaded when the program is running. The code and data in the dynamic library will not be added to the program, but will exist separately in the memory.
2. Size:
The static library is larger in size because the code data in it is directly added to the program.
The dynamic library is small in size and only contains function names and reference information.

3. Update:
Static library updates require recompiling and linking the entire program.
Dynamic library updates only need to update the .so file and will not affect compiled programs.
4. Compatibility:
Static libraries are strongly dependent on the compilation environment, and different environments may be incompatible.
Dynamic libraries have good compatibility because they are loaded at runtime. A .so file can run in different environments.
5. Security:
It is difficult to control access to static libraries, and any program with library access rights can call functions in it.
Dynamic libraries can be accessed and controlled, allowing only specific programs to be loaded and called.
So in general, dynamic libraries are more suitable for scenarios where code is modular and frequently updated, while static libraries are more suitable for scenarios where program size is small or security requirements are high. Both have their own advantages and disadvantages, and you need to choose according to the actual project conditions.

?