Chinaunix首页 | 论坛 | 博客
  • 博客访问: 133024
  • 博文数量: 30
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 550
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-08 20:28
个人简介

永远不要放弃学习,放弃学习就是放弃了勇敢生活下去的动力!

文章分类

全部博文(30)

文章存档

2014年(30)

我的朋友

分类: 嵌入式

2014-03-09 13:11:28

        今天开始学习嵌入式,首先基础知识就不讲了,知道去看书就好。嵌入式下的我们用的最多的就是gcc make 编译器,下面我先把自己学习gcc的过程和大家分享一下。
首先,在linux下面,当我们想很快测试时,看到一些代码想复制过来的时候,发现复制过来的都有行号,我们不会一行一行的去消吧,那你要花多少时间在无用功上,记得使用cut命令。
            cut -c 3- gcctest.c >> sun.c 代表的意思就是从每行的第3个字符串开始剪切,一直到最后。然后把剪切结果输入到sun.c中,或者你也可以直接覆盖源文件。然后我们使用indent命令处理.c文件,让源程序看起来比较规矩。indent -kr -i8 sun.c 就是处理源程序的。
           学习怎么快速建立测试文件后下面我们来学习gcc编译过程。我参照的是张同光老师的书,测试程序和知识都是我在上面学到的。程序的编译过程详细的可以分成以下步骤
源程序→预处理器(cpp)→编译器(ccl)→汇编器(as)→链接器(ld)→可执行文件
下面我们来一步一步的走,下面贴出源程序

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. void print_hello1 (char *p_str);
  3. void print_hello2 (char *p_str);
  4. int main (int argc, char **argv)
  5. {
  6.     double i, sum = 0;
  7.     char *pstr = "hello in main";
  8.     int arr[] = { 1, 2, 3, 4, 5 };
  9.     printf ("%s\n", pstr);
  10.     print_hello1 ("hello 1");
  11.     print_hello2 ("hello 2");

  12.     for (i = 1;
  13.      i <=
  14.      1020000020.01 * 1020000020.01 * 10100020.01 * 10100020.00202;
  15.      i = i * 1.0000016)
  16.         sum = sum / 1.0201809902203 * 1.000102101203 * 1.00006605 +
  17.             i * 10.01016 / 1.0005;
  18.     printf ("sum=%f\n", sum);
  19. }
  20. void print_hello1 (char *p_str)
  21. {
  22.     printf ("%s\n", p_str);
  23. }
  24. void print_hello2 (char *p_str)
  25. {
  26.     printf ("%s\n", p_str);
  27. }

我们来进行第一步:编译预处理
使用-E选项可以使gcc在编译过程中停止在预处理后的过程,预处理的文件后缀为.i文件
gcc -E gcctest.c -o gcctest.i
下面看看gcctest.i文件是什么文件

点击(此处)折叠或打开

  1. # 1 "gcctest.c"
  2. # 1 ""
  3. # 1 "<命令行>"
  4. # 1 "gcctest.c"
  5. # 1 "/usr/include/stdio.h" 1 3 4
  6. # 28 "/usr/include/stdio.h" 3 4
  7. # 1 "/usr/include/features.h" 1 3 4
  8. # 361 "/usr/include/features.h" 3 4
  9. # 1 "/usr/include/sys/cdefs.h" 1 3 4
  10. # 365 "/usr/include/sys/cdefs.h" 3 4
  11. # 1 "/usr/include/bits/wordsize.h" 1 3 4
  12. # 366 "/usr/include/sys/cdefs.h" 2 3 4
  13. # 362 "/usr/include/features.h" 2 3 4
  14. # 385 "/usr/include/features.h" 3 4
  15. # 1 "/usr/include/gnu/stubs.h" 1 3 4
  16. # 1 "/usr/include/bits/wordsize.h" 1 3 4
  17. # 5 "/usr/include/gnu/stubs.h" 2 3 4
  18. # 1 "/usr/include/gnu/stubs-32.h" 1 3 4
  19. # 8 "/usr/include/gnu/stubs.h" 2 3 4
  20. # 386 "/usr/include/features.h" 2 3 4
  21. # 29 "/usr/include/stdio.h" 2 3 4
  22. # 1 "/usr/lib/gcc/i686-redhat-linux/4.4.4/include/stddef.h" 1 3 4
  23. # 211 "/usr/lib/gcc/i686-redhat-linux/4.4.4/include/stddef.h" 3 4

  24. # 35 "/usr/include/stdio.h" 2 3 4
  25. # 1 "/usr/include/bits/types.h" 1 3 4
  26. # 28 "/usr/include/bits/types.h" 3 4
  27. # 1 "/usr/include/bits/wordsize.h" 1 3 4
  28. # 29 "/usr/include/bits/types.h" 2 3 4

  29. # 131 "/usr/include/bits/types.h" 3 4
  30. # 1 "/usr/include/bits/typesizes.h" 1 3 4
  31. # 132 "/usr/include/bits/types.h" 2 3 4

  32. # 37 "/usr/include/stdio.h" 2 3 4
  33. # 45 "/usr/include/stdio.h" 3 4
  34. struct _IO_FILE;

  35. # 65 "/usr/include/stdio.h" 3 4

  36. # 75 "/usr/include/stdio.h" 3 4
  37. # 1 "/usr/include/libio.h" 1 3 4
  38. # 32 "/usr/include/libio.h" 3 4
  39. # 1 "/usr/include/_G_config.h" 1 3 4
  40. # 15 "/usr/include/_G_config.h" 3 4
  41. # 1 "/usr/lib/gcc/i686-redhat-linux/4.4.4/include/stddef.h" 1 3 4
  42. # 16 "/usr/include/_G_config.h" 2 3 4
  43. # 1 "/usr/include/wchar.h" 1 3 4
  44. # 83 "/usr/include/wchar.h" 3 4

  45. # 21 "/usr/include/_G_config.h" 2 3 4

  46. # 53 "/usr/include/_G_config.h" 3 4

  47. # 33 "/usr/include/libio.h" 2 3 4
  48. # 53 "/usr/include/libio.h" 3 4
  49. # 1 "/usr/lib/gcc/i686-redhat-linux/4.4.4/include/stdarg.h" 1 3 4
  50. # 40 "/usr/lib/gcc/i686-redhat-linux/4.4.4/include/stdarg.h" 3 4
  51. # 54 "/usr/include/libio.h" 2 3 4
  52. # 170 "/usr/include/libio.h" 3 4

  53. # 180 "/usr/include/libio.h" 3 4

  54. # 203 "/usr/include/libio.h" 3 4
  55. };

  56. # 271 "/usr/include/libio.h" 3 4


  57. # 938 "/usr/include/stdio.h" 3 4
  58. # 2 "gcctest.c" 2
  59. void print_hello1 (char *p_str);
  60. void print_hello2 (char *p_str);
  61. int main (int argc, char **argv)
  62. {
  63.  double i, sum = 0;
  64.  char *pstr = "hello in main";
  65.  int arr[] = { 1, 2, 3, 4, 5 };
  66.  printf ("%s\n", pstr);
  67.  print_hello1 ("hello 1");
  68.  print_hello2 ("hello 2");
  69.  for (i = 1;
  70.       i <=
  71.       1020000020.01 * 1020000020.01 * 10100020.01 * 10100020.00202;
  72.       i = i * 1.0000016)
  73.   sum = sum / 1.0201809902203 * 1.000102101203 * 1.00006605 +
  74.    i * 10.01016 / 1.0005;
  75.  printf ("sum=%f\n", sum);
  76. }
  77. void print_hello1 (char *p_str)
  78. {
  79.  printf ("%s\n", p_str);
  80. }
  81. void
  82. print_hello2 (char *p_str)
  83. {
  84.  printf ("%s\n", p_str);
  85. }
这个是我剪了一部分代码,实际它很大的有415行的,里面把stdio.h内容插到了文件里,而宏定义也做了处理,
第二步:将gcctest.i编译为汇编语言代码,可以用-S选项完成。
gcc -S gcctest.i -o gcctest.s 
插入代码

点击(此处)折叠或打开

  1. .file    "gcctest.c"
  2.     .section    .rodata
  3. .LC1:
  4.     .string    "hello in main"
  5. .LC2:
  6.     .string    "hello 1"
  7. .LC3:
  8.     .string    "hello 2"
  9. .LC12:
  10.     .string    "sum=%f\n"
  11.     .text
  12. .globl main
  13.     .type    main, @function
  14. main:
  15.     pushl    %ebp
  16.     movl    %esp, %ebp
  17.     andl    $-16, %esp
  18.     subl    $64, %esp
  19.     fldz
  20.     fstpl    48(%esp)
  21.     movl    $.LC1, 60(%esp)
  22.     movl    $1, 20(%esp)
  23.     movl    $2, 24(%esp)
  24.     movl    $3, 28(%esp)
  25.     movl    $4, 32(%esp)
  26.     movl    $5, 36(%esp)
  27.     movl    60(%esp), %eax
  28.     movl    %eax, (%esp)
  29.     call    puts
  30.     movl    $.LC2, (%esp)
  31.     call    print_hello1
  32.     movl    $.LC3, (%esp)
  33.     call    print_hello2
  34.     fld1
  35.     fstpl    40(%esp)
  36.     jmp    .L2
  37. .L3:
  38.     fldl    48(%esp)
  39.     fldl    .LC5
  40.     fdivrp    %st, %st(1)
  41.     fldl    .LC6
  42.     fmulp    %st, %st(1)
  43.     fldl    .LC7
  44.     fmulp    %st, %st(1)
  45.     fldl    40(%esp)
  46.     fldl    .LC8
  47.     fmulp    %st, %st(1)
  48.     fldl    .LC9
  49.     fdivrp    %st, %st(1)
  50.     faddp    %st, %st(1)
  51.     fstpl    48(%esp)
  52.     fldl    40(%esp)
  53.     fldl    .LC10
  54.     fmulp    %st, %st(1)
  55.     fstpl    40(%esp)
  56. .L2:
  57.     fldl    40(%esp)
  58.     fldl    .LC11
  59.     fucomip    %st(1), %st
  60.     fstp    %st(0)
  61.     setae    %al
  62.     testb    %al, %al
  63.     jne    .L3
  64.     movl    $.LC12, %eax
  65.     fldl    48(%esp)
  66.     fstpl    4(%esp)
  67.     movl    %eax, (%esp)
  68.     call    printf
  69.     leave
  70.     ret
  71.     .size    main, .-main
  72. .globl print_hello1
  73.     .type    print_hello1, @function
  74. print_hello1:
  75.     pushl    %ebp
  76.     movl    %esp, %ebp
  77.     subl    $24, %esp
  78.     movl    8(%ebp), %eax
  79.     movl    %eax, (%esp)
  80.     call    puts
  81.     leave
  82.     ret
  83.     .size    print_hello1, .-print_hello1
  84. .globl print_hello2
  85.     .type    print_hello2, @function
  86. print_hello2:
  87.     pushl    %ebp
  88.     movl    %esp, %ebp
  89.     subl    $24, %esp
  90.     movl    8(%ebp), %eax
  91.     movl    %eax, (%esp)
  92.     call    puts
  93.     leave
  94.     ret
  95.     .size    print_hello2, .-print_hello2
  96.     .section    .rodata
  97.     .align 8
  98. .LC5:
  99.     .long    1297085455
  100.     .long    1072714409
  101.     .align 8
  102. .LC6:
  103.     .long    261439113
  104.     .long    1072693355
  105.     .align 8
  106. .LC7:
  107.     .long    1110011964
  108.     .long    1072693317
  109.     .align 8
  110. .LC8:
  111.     .long    -1324911511
  112.     .long    1076102451
  113.     .align 8
  114. .LC9:
  115.     .long    1236950581
  116.     .long    1072693772
  117.     .align 8
  118. .LC10:
  119.     .long    -1384175188
  120.     .long    1072693249
  121.     .align 8
  122. .LC11:
  123.     .long    642022389
  124.     .long    1184165447
  125.     .ident    "GCC: (GNU) 4.4.4 20100726 (Red Hat 4.4.4-13)"
  126.     .section    .note.GNU-stack,"",@progbits
这个就是gcc汇编后的汇编源码。
第三步:将gcctest.s汇编为目标代码,可以通过-c选项来完成。
gcc -c gcctest.s -o gcctest.o
第四步:最后就是把目标文件与相关库文件一起链接成一个可执行文件
gcc gcctest.o -o gcctest
#./gcctest
就可以看到你的结果。就这样一个程序就产生了。
gcc 编译的过程中使用-Wall和-Werror 选项可以提示你详细错误信息。
通过gcc -pipe gcctest.c -o gcctest 可以加速处理

下面我们学习gcc编译器的调试gdb,直接贴我的调试过程吧,下面是我写一个从1加到100的 c程序sun.c

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4.     int sum=0;
  5.     int i;
  6.     for(i=0;i<101;i++)
  7.     {
  8.         sum=sum+i;
  9.         
  10.     }
  11.     printf("%d",sum);
  12.     return sum;
  13.     
  14. }
如果你要进行调试,那么你编译的时候就不要执行gcc sun.c -o sun了,这时候会提示你no debugging symbols found,你应该加一个-g的参数就是
gcc -g sun.c -o sun

点击(此处)折叠或打开

  1. [root@localhost 桌面]# ls
  2. gcctest sun
  3. gcctest.c sun.c
  4. gcctest.c~ sun.c~
  5. gcctestg sun.i~
  6. gcctest.i sun.o
  7. gcctest.o sun.s
  8. gcctest.s 未命名文件夹
  9. gcctests.c~ 未命名文件夹 2
  10. [root@localhost 桌面]# gcc -g sun.c -o sun
  11. [root@localhost 桌面]# gdb
  12. GNU gdb (GDB) Red Hat Enterprise Linux (7.2-60.el6_4.1)
  13. Copyright (C) 2010 Free Software Foundation, Inc.
  14. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
  15. This is free software: you are free to change and redistribute it.
  16. There is NO WARRANTY, to the extent permitted by law. Type "show copying"
  17. and "show warranty" for details.
  18. This GDB was configured as "i686-redhat-linux-gnu".
  19. For bug reporting instructions, please see:
  20. <http://www.gnu.org/software/gdb/bugs/>.
  21. (gdb) file sun //file选择你要调试的程序
  22. Reading symbols from /root/桌面/sun...done.
  23. (gdb) start                //开始调试
  24. Temporary breakpoint 1 at 0x80483cd: file sun.c, line 4.
  25. Starting program: /root/桌面/sun

  26. Temporary breakpoint 1, main () at sun.c:4
  27. 4 int sum=0;
  28. Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.7.el6.i686
  29. (gdb) list            //默认打印程序的前10行
  30. 1 #include <stdio.h>
  31. 2 int main(void)
  32. 3 {
  33. 4 int sum=0;
  34. 5 int i;
  35. 6 for(i=0;i<101;i++)
  36. 7 {
  37. 8 sum=sum+i;
  38. 9
  39. 10 }
  40. (gdb)                        //再次按Enter键自动执行上一条命令
  41. 11 printf("%d",sum);
  42. 12 return sum;
  43. 13
  44. 14 }
  45. (gdb) s                        //执行下一步程序
  46. 6 for(i=0;i<101;i++)
  47. (gdb) info i                //显示i的信息
  48.   Num Description Executable
  49. * 1 process 6576 /root/桌面/sun
  50. (gdb) i locals                    //info locals 显示当前变量的值
  51. sum = 0
  52. i = 8691700
  53. (gdb) s
  54. 8 sum=sum+i;
  55. (gdb) i locals
  56. sum = 0
  57. i = 0
  58. (gdb) display i                    //跟踪显示i的值
  59. 1: i = 0
  60. (gdb) s
  61. 6 for(i=0;i<101;i++)
  62. 1: i = 0
  63. (gdb) s
  64. 8 sum=sum+i;
  65. 1: i = 1
  66. (gdb) display sum            //跟踪显示sum的值
  67. 2: sum = 0
  68. (gdb) s
  69. 6 for(i=0;i<101;i++)
  70. 2: sum = 1
  71. 1: i = 1
  72. (gdb) s
  73. 8 sum=sum+i;
  74. 2: sum = 1
  75. 1: i = 2
  76. (gdb) i locals
  77. sum = 1
  78. i = 2
  79. (gdb) p sum                //打印sum的值
  80. $1 = 1
  81. (gdb) s
  82. 6 for(i=0;i<101;i++)
  83. 2: sum = 3
  84. 1: i = 2
  85. (gdb) break 8    //在程序的第8行设置断点,你按r执行时就会停在8行处
  86. Breakpoint 2 at 0x80483df: file sun.c, line 8.
  87. (gdb) r                //执行程序到断点,没断点就执行完程序
  88. The program being debugged has been started already.
  89. Start it from the beginning? (y or n) y
  90. Starting program: /root/桌面/sun

  91. Breakpoint 2, main () at sun.c:8
  92. 8 sum=sum+i;
  93. 2: sum = 0
  94. 1: i = 0
  95. (gdb) r
  96. The program being debugged has been started already.
  97. Start it from the beginning? (y or n) y
  98. Starting program: /root/桌面/sun

  99. Breakpoint 2, main () at sun.c:8
  100. 8 sum=sum+i;
  101. (gdb) delete Breakpoint 2        //删除断点2
  102. (gdb) r                    //这次程序就会执行出结果
  103. The program being debugged has been started already.
  104. Start it from the beginning? (y or n) y
  105. Starting program: /root/桌面/sun
  106. 5050
  107. Program exited with code 0272.
  108. (gdb)
  109. (gdb) q            //退出程序
  110. A debugging session is active.

  111.         Inferior 1 [process 6596] will be killed.

  112. Quit anyway? (y or n) y
  113. [root@localhost 桌面]#
gcc工具大概我们就学这么多了,会编译程序,会调试程序就好了。下面我们就该学习编写makefile文件了。

阅读(1639) | 评论(1) | 转发(1) |
给主人留下些什么吧!~~