我们知道一个程序需经过预处理、编译、汇编、链接四个过程。下面小小的说一下这几个过程。
预处理:
(1)、头文件的包含
(2)、#define定义的标识符转换
(3)、宏替换(不可递归)
(4)、注释的删除
编译:
(1)、语法分析
(2)、词法分析
(3)、语义分析
(4)、优化
汇编:
(1)、形成符号表
(2)、汇编指令—>二进制指令
链接:
(1)、合并段表
(2)、符号表的合并和符号表的重定义,最终形成“.exe”。
先看一段简单的代码:
、
进入hello.i文件中我们可以看到如下的代码:
extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__)) ;
extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__));
# 938 "/usr/include/stdio.h" 3 4
# 2 "hello.c" 2
int main()
{
#pragma massage("this is maomaochong")
printf("hello linux\n");
}
不难看出所有的注释部分全部被处理掉了,而且define定义的标识符也被替换了。
另外#pragma massage(“this is maomaochong”)其在预处理时不进行处理。
即#pragma 的部分不会进行预处理。
编译:hello.s
gcc -S hello.i:表示其进行编译
其会形成编译文件,即为hello.s
系统内的此法分析其:lex
进入到hello.s文件中可以看到如下代码:
.file "hello.c"
.section .rodata
.LC0:
.string "hello linux"
.text
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $16, %esp
movl $.LC0, (%esp)
call puts
leave
ret
.size main, .-main
.ident "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-18)"
.section .note.GNU-stack,"",@progbits
汇编
hello.o文件
gcc -c hello.s表示其进行汇编,其会形成文件hello.o
gcc -c hello.s -m32:表示在32位下进行汇编
链接
把每个源代码独立的编译,然后按照将它们组装。
下面介绍gdb:
linux gcc/g++ 出来的二进制程序,默认是release形式。
要使用gdb调试,必须在源代码生成二进制程序的时候,加上-g。
下面看一个程序代码:
#include<stdio.h>
#if 1
#define swap(a,b)\
{\
typeof(a)tmp=a;\
a=b;\
b=tmp;\
}
#endif
void bubble_sort(int *arr,int len)
{
int i,j;
for(i=0;i<len;i++)
{
for(j=len-1;j>i;j--){
if(arr[j]<arr[j-1]){
swap(arr[j],arr[j-1]);
}
}
}
}
void show(int arr[],int len)
{
if(len==0){
printf("\n");
}else{
show(arr,len-1);
printf("%d",arr[len-1]);
}
}
int main(void)
{
int add[5]={33,22,44,66,55};
show(add,5);
bubble_sort(add,5);
show(add,5);
}
下面使用gdb调试:
进入之后可以看到:
(gdb) l 1-------------------------------------------->表示list 1 从第一行开始列出源码
1 #include<stdio.h>
2 #if 1
3 #define swap(a,b)\
4 {\
5 typeof(a)tmp=a;\
6 a=b;\
7 b=tmp;\
8 }
9 #endif
10 void bubble_sort(int *arr,int len)
(gdb) <-------------------- 直接回车表示,重复上一次命令
11 {
12 int i,j;
13 for(i=0;i<len;i++)
14 {
15 for(j=len-1;j>i;j--){
16 if(arr[j]<arr[j-1]){
17 swap(arr[j],arr[j-1]);
18 }
19 }
20 }
l show--------------------------------------->表示列出某一个函数,l 函数名
18 }
19 }
20 }
21 }
22 void show(int arr[],int len)
23 {
24 if(len==0){
25 printf("\n");
26 }else{
27 show(arr,len-1);
(gdb) b 16----------------------------------------->break 16表示在第16行设置断点
Breakpoint 1 at 0x804840e: file 1.c, line 16.
(gdb) i b------------------------------------------->info break 表示查看断点
Num Type Disp Enb Address What
1 breakpoint keep y 0x0804840e in bubble_sort at 1.c:16
(gdb) l 1
1 #include<stdio.h>
2 #if 1
3 #define swap(a,b)\
4 {\
5 typeof(a)tmp=a;\
6 a=b;\
7 b=tmp;\
8 }
9 #endif
10 void bubble_sort(int *arr,int len)
(gdb)
11 {
12 int i,j;
13 for(i=0;i<len;i++)
14 {
15 for(j=len-1;j>i;j--){
16 if(arr[j]<arr[j-1]){
17 swap(arr[j],arr[j-1]);
18 }
19 }
20 }
(gdb)
21 }
22 void show(int arr[],int len)
23 {
24 if(len==0){
25 printf("\n");
26 }else{
27 show(arr,len-1);
28 printf("%d",arr[len-1]);
29 }
30 }
(gdb)
31
32 int main(void)
33 {
34 int add[5]={33,22,44,66,55};
35 show(add,5);
36 bubble_sort(add,5);
37 show(add,5);
38 }
(gdb) b 10 <-------------------- 设置断点,在源程序第 10行。
Breakpoint 1 at 0x80483fa: file 1.c, line 10.
(gdb) i b <--------------------info break 查看断点信息。
Num Type Disp Enb Address What
1 breakpoint keep y 0x080483fa in bubble_sort at 1.c:10
(gdb) r
Starting program: /home/admin/a.out
Breakpoint 1, bubble_sort (arr=0xbffff3dc, len=5) at 1.c:13
13 for(i=0;i<len;i++)
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.i686
(gdb) n <--------------------- 单条语句执行, next 命令简写。相当于vs下的f10
15 for(j=len-1;j>i;j--){
(gdb) n
16 if(arr[j]<arr[j-1]){
(gdb) n
17 swap(arr[j],arr[j-1]);
(gdb) n
15 for(j=len-1;j>i;j--){
(gdb) n
16 if(arr[j]<arr[j-1]){
(gdb) n
15 for(j=len-1;j>i;j--){
(gdb) n
16 if(arr[j]<arr[j-1]){
(gdb) n
15 for(j=len-1;j>i;j--){
(gdb) n
16 if(arr[j]<arr[j-1]){
(gdb) n
17 swap(arr[j],arr[j-1]);
(gdb) n
15 for(j=len-1;j>i;j--){
(gdb) n
13 for(i=0;i<len;i++)
(gdb) n
15 for(j=len-1;j>i;j--){
(gdb) n
16 if(arr[j]<arr[j-1]){
(gdb) n
15 for(j=len-1;j>i;j--){
(gdb) n
16 if(arr[j]<arr[j-1]){
(gdb) n
15 for(j=len-1;j>i;j--){
(gdb) n
16 if(arr[j]<arr[j-1]){
(gdb) n
15 for(j=len-1;j>i;j--){
(gdb) n
13 for(i=0;i<len;i++)
(gdb) n
15 for(j=len-1;j>i;j--){
(gdb) n
16 if(arr[j]<arr[j-1]){
(gdb) n
15 for(j=len-1;j>i;j--){
(gdb) n
16 if(arr[j]<arr[j-1]){
(gdb) n
15 for(j=len-1;j>i;j--){
(gdb) n
13 for(i=0;i<len;i++)
(gdb) n
15 for(j=len-1;j>i;j--){
(gdb) n
16 if(arr[j]<arr[j-1]){
(gdb) n
15 for(j=len-1;j>i;j--){
(gdb) n
13 for(i=0;i<len;i++)
(gdb)
15 for(j=len-1;j>i;j--){
(gdb) n
13 for(i=0;i<len;i++)
(gdb) n
21 }
(gdb) n
main () at 1.c:37
37 show(add,5);
(gdb) n
3322446655
38 }
(gdb) n
0x003d0d26 in __libc_start_main () from /lib/libc.so.6
(gdb) n
Single stepping until exit from function __libc_start_main,
which has no line number information.
2233445566
Program exited with code 02.