linux下预处理、编译、汇编、链接及gdb调试

我们知道一个程序需经过预处理、编译、汇编、链接四个过程。下面小小的说一下这几个过程。
预处理:
(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.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值