今天开始学习嵌入式,首先基础知识就不讲了,知道去看书就好。嵌入式下的我们用的最多的就是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)→可执行文件
下面我们来一步一步的走,下面贴出源程序
-
#include <stdio.h>
-
void print_hello1 (char *p_str);
-
void print_hello2 (char *p_str);
-
int main (int argc, char **argv)
-
{
-
double i, sum = 0;
-
char *pstr = "hello in main";
-
int arr[] = { 1, 2, 3, 4, 5 };
-
printf ("%s\n", pstr);
-
print_hello1 ("hello 1");
-
print_hello2 ("hello 2");
-
-
for (i = 1;
-
i <=
-
1020000020.01 * 1020000020.01 * 10100020.01 * 10100020.00202;
-
i = i * 1.0000016)
-
sum = sum / 1.0201809902203 * 1.000102101203 * 1.00006605 +
-
i * 10.01016 / 1.0005;
-
printf ("sum=%f\n", sum);
-
}
-
void print_hello1 (char *p_str)
-
{
-
printf ("%s\n", p_str);
-
}
-
void print_hello2 (char *p_str)
-
{
-
printf ("%s\n", p_str);
-
}
我们来进行第一步:编译预处理
使用-E选项可以使gcc在编译过程中停止在预处理后的过程,预处理的文件后缀为.i文件
gcc -E gcctest.c -o gcctest.i
下面看看gcctest.i文件是什么文件
-
# 1 "gcctest.c"
-
# 1 ""
-
# 1 "<命令行>"
-
# 1 "gcctest.c"
-
# 1 "/usr/include/stdio.h" 1 3 4
-
# 28 "/usr/include/stdio.h" 3 4
-
# 1 "/usr/include/features.h" 1 3 4
-
# 361 "/usr/include/features.h" 3 4
-
# 1 "/usr/include/sys/cdefs.h" 1 3 4
-
# 365 "/usr/include/sys/cdefs.h" 3 4
-
# 1 "/usr/include/bits/wordsize.h" 1 3 4
-
# 366 "/usr/include/sys/cdefs.h" 2 3 4
-
# 362 "/usr/include/features.h" 2 3 4
-
# 385 "/usr/include/features.h" 3 4
-
# 1 "/usr/include/gnu/stubs.h" 1 3 4
-
# 1 "/usr/include/bits/wordsize.h" 1 3 4
-
# 5 "/usr/include/gnu/stubs.h" 2 3 4
-
# 1 "/usr/include/gnu/stubs-32.h" 1 3 4
-
# 8 "/usr/include/gnu/stubs.h" 2 3 4
-
# 386 "/usr/include/features.h" 2 3 4
-
# 29 "/usr/include/stdio.h" 2 3 4
-
# 1 "/usr/lib/gcc/i686-redhat-linux/4.4.4/include/stddef.h" 1 3 4
-
# 211 "/usr/lib/gcc/i686-redhat-linux/4.4.4/include/stddef.h" 3 4
-
-
# 35 "/usr/include/stdio.h" 2 3 4
-
# 1 "/usr/include/bits/types.h" 1 3 4
-
# 28 "/usr/include/bits/types.h" 3 4
-
# 1 "/usr/include/bits/wordsize.h" 1 3 4
-
# 29 "/usr/include/bits/types.h" 2 3 4
-
-
# 131 "/usr/include/bits/types.h" 3 4
-
# 1 "/usr/include/bits/typesizes.h" 1 3 4
-
# 132 "/usr/include/bits/types.h" 2 3 4
-
-
# 37 "/usr/include/stdio.h" 2 3 4
-
# 45 "/usr/include/stdio.h" 3 4
-
struct _IO_FILE;
-
-
# 65 "/usr/include/stdio.h" 3 4
-
-
# 75 "/usr/include/stdio.h" 3 4
-
# 1 "/usr/include/libio.h" 1 3 4
-
# 32 "/usr/include/libio.h" 3 4
-
# 1 "/usr/include/_G_config.h" 1 3 4
-
# 15 "/usr/include/_G_config.h" 3 4
-
# 1 "/usr/lib/gcc/i686-redhat-linux/4.4.4/include/stddef.h" 1 3 4
-
# 16 "/usr/include/_G_config.h" 2 3 4
-
# 1 "/usr/include/wchar.h" 1 3 4
-
# 83 "/usr/include/wchar.h" 3 4
-
-
# 21 "/usr/include/_G_config.h" 2 3 4
-
-
# 53 "/usr/include/_G_config.h" 3 4
-
-
# 33 "/usr/include/libio.h" 2 3 4
-
# 53 "/usr/include/libio.h" 3 4
-
# 1 "/usr/lib/gcc/i686-redhat-linux/4.4.4/include/stdarg.h" 1 3 4
-
# 40 "/usr/lib/gcc/i686-redhat-linux/4.4.4/include/stdarg.h" 3 4
-
# 54 "/usr/include/libio.h" 2 3 4
-
# 170 "/usr/include/libio.h" 3 4
-
-
# 180 "/usr/include/libio.h" 3 4
-
-
# 203 "/usr/include/libio.h" 3 4
-
};
-
-
# 271 "/usr/include/libio.h" 3 4
-
-
-
# 938 "/usr/include/stdio.h" 3 4
-
# 2 "gcctest.c" 2
-
void print_hello1 (char *p_str);
-
void print_hello2 (char *p_str);
-
int main (int argc, char **argv)
-
{
-
double i, sum = 0;
-
char *pstr = "hello in main";
-
int arr[] = { 1, 2, 3, 4, 5 };
-
printf ("%s\n", pstr);
-
print_hello1 ("hello 1");
-
print_hello2 ("hello 2");
-
for (i = 1;
-
i <=
-
1020000020.01 * 1020000020.01 * 10100020.01 * 10100020.00202;
-
i = i * 1.0000016)
-
sum = sum / 1.0201809902203 * 1.000102101203 * 1.00006605 +
-
i * 10.01016 / 1.0005;
-
printf ("sum=%f\n", sum);
-
}
-
void print_hello1 (char *p_str)
-
{
-
printf ("%s\n", p_str);
-
}
-
void
-
print_hello2 (char *p_str)
-
{
-
printf ("%s\n", p_str);
-
}
这个是我剪了一部分代码,实际它很大的有415行的,里面把stdio.h内容插到了文件里,而宏定义也做了处理,
第二步:将gcctest.i编译为汇编语言代码,可以用-S选项完成。
gcc -S gcctest.i -o gcctest.s
插入代码
-
.file "gcctest.c"
-
.section .rodata
-
.LC1:
-
.string "hello in main"
-
.LC2:
-
.string "hello 1"
-
.LC3:
-
.string "hello 2"
-
.LC12:
-
.string "sum=%f\n"
-
.text
-
.globl main
-
.type main, @function
-
main:
-
pushl %ebp
-
movl %esp, %ebp
-
andl $-16, %esp
-
subl $64, %esp
-
fldz
-
fstpl 48(%esp)
-
movl $.LC1, 60(%esp)
-
movl $1, 20(%esp)
-
movl $2, 24(%esp)
-
movl $3, 28(%esp)
-
movl $4, 32(%esp)
-
movl $5, 36(%esp)
-
movl 60(%esp), %eax
-
movl %eax, (%esp)
-
call puts
-
movl $.LC2, (%esp)
-
call print_hello1
-
movl $.LC3, (%esp)
-
call print_hello2
-
fld1
-
fstpl 40(%esp)
-
jmp .L2
-
.L3:
-
fldl 48(%esp)
-
fldl .LC5
-
fdivrp %st, %st(1)
-
fldl .LC6
-
fmulp %st, %st(1)
-
fldl .LC7
-
fmulp %st, %st(1)
-
fldl 40(%esp)
-
fldl .LC8
-
fmulp %st, %st(1)
-
fldl .LC9
-
fdivrp %st, %st(1)
-
faddp %st, %st(1)
-
fstpl 48(%esp)
-
fldl 40(%esp)
-
fldl .LC10
-
fmulp %st, %st(1)
-
fstpl 40(%esp)
-
.L2:
-
fldl 40(%esp)
-
fldl .LC11
-
fucomip %st(1), %st
-
fstp %st(0)
-
setae %al
-
testb %al, %al
-
jne .L3
-
movl $.LC12, %eax
-
fldl 48(%esp)
-
fstpl 4(%esp)
-
movl %eax, (%esp)
-
call printf
-
leave
-
ret
-
.size main, .-main
-
.globl print_hello1
-
.type print_hello1, @function
-
print_hello1:
-
pushl %ebp
-
movl %esp, %ebp
-
subl $24, %esp
-
movl 8(%ebp), %eax
-
movl %eax, (%esp)
-
call puts
-
leave
-
ret
-
.size print_hello1, .-print_hello1
-
.globl print_hello2
-
.type print_hello2, @function
-
print_hello2:
-
pushl %ebp
-
movl %esp, %ebp
-
subl $24, %esp
-
movl 8(%ebp), %eax
-
movl %eax, (%esp)
-
call puts
-
leave
-
ret
-
.size print_hello2, .-print_hello2
-
.section .rodata
-
.align 8
-
.LC5:
-
.long 1297085455
-
.long 1072714409
-
.align 8
-
.LC6:
-
.long 261439113
-
.long 1072693355
-
.align 8
-
.LC7:
-
.long 1110011964
-
.long 1072693317
-
.align 8
-
.LC8:
-
.long -1324911511
-
.long 1076102451
-
.align 8
-
.LC9:
-
.long 1236950581
-
.long 1072693772
-
.align 8
-
.LC10:
-
.long -1384175188
-
.long 1072693249
-
.align 8
-
.LC11:
-
.long 642022389
-
.long 1184165447
-
.ident "GCC: (GNU) 4.4.4 20100726 (Red Hat 4.4.4-13)"
-
.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
-
#include <stdio.h>
-
int main(void)
-
{
-
int sum=0;
-
int i;
-
for(i=0;i<101;i++)
-
{
-
sum=sum+i;
-
-
}
-
printf("%d",sum);
-
return sum;
-
-
}
如果你要进行调试,那么你编译的时候就不要执行gcc sun.c -o sun了,这时候会提示你no debugging symbols found,你应该加一个-g的参数就是
gcc -g sun.c -o sun
-
[root@localhost 桌面]# ls
-
gcctest sun
-
gcctest.c sun.c
-
gcctest.c~ sun.c~
-
gcctestg sun.i~
-
gcctest.i sun.o
-
gcctest.o sun.s
-
gcctest.s 未命名文件夹
-
gcctests.c~ 未命名文件夹 2
-
[root@localhost 桌面]# gcc -g sun.c -o sun
-
[root@localhost 桌面]# gdb
-
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-60.el6_4.1)
-
Copyright (C) 2010 Free Software Foundation, Inc.
-
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
-
This is free software: you are free to change and redistribute it.
-
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
-
and "show warranty" for details.
-
This GDB was configured as "i686-redhat-linux-gnu".
-
For bug reporting instructions, please see:
-
<http://www.gnu.org/software/gdb/bugs/>.
-
(gdb) file sun //file选择你要调试的程序
-
Reading symbols from /root/桌面/sun...done.
-
(gdb) start //开始调试
-
Temporary breakpoint 1 at 0x80483cd: file sun.c, line 4.
-
Starting program: /root/桌面/sun
-
-
Temporary breakpoint 1, main () at sun.c:4
-
4 int sum=0;
-
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.7.el6.i686
-
(gdb) list //默认打印程序的前10行
-
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 }
-
(gdb) //再次按Enter键自动执行上一条命令
-
11 printf("%d",sum);
-
12 return sum;
-
13
-
14 }
-
(gdb) s //执行下一步程序
-
6 for(i=0;i<101;i++)
-
(gdb) info i //显示i的信息
-
Num Description Executable
-
* 1 process 6576 /root/桌面/sun
-
(gdb) i locals //info locals 显示当前变量的值
-
sum = 0
-
i = 8691700
-
(gdb) s
-
8 sum=sum+i;
-
(gdb) i locals
-
sum = 0
-
i = 0
-
(gdb) display i //跟踪显示i的值
-
1: i = 0
-
(gdb) s
-
6 for(i=0;i<101;i++)
-
1: i = 0
-
(gdb) s
-
8 sum=sum+i;
-
1: i = 1
-
(gdb) display sum //跟踪显示sum的值
-
2: sum = 0
-
(gdb) s
-
6 for(i=0;i<101;i++)
-
2: sum = 1
-
1: i = 1
-
(gdb) s
-
8 sum=sum+i;
-
2: sum = 1
-
1: i = 2
-
(gdb) i locals
-
sum = 1
-
i = 2
-
(gdb) p sum //打印sum的值
-
$1 = 1
-
(gdb) s
-
6 for(i=0;i<101;i++)
-
2: sum = 3
-
1: i = 2
-
(gdb) break 8 //在程序的第8行设置断点,你按r执行时就会停在8行处
-
Breakpoint 2 at 0x80483df: file sun.c, line 8.
-
(gdb) r //执行程序到断点,没断点就执行完程序
-
The program being debugged has been started already.
-
Start it from the beginning? (y or n) y
-
Starting program: /root/桌面/sun
-
-
Breakpoint 2, main () at sun.c:8
-
8 sum=sum+i;
-
2: sum = 0
-
1: i = 0
-
(gdb) r
-
The program being debugged has been started already.
-
Start it from the beginning? (y or n) y
-
Starting program: /root/桌面/sun
-
-
Breakpoint 2, main () at sun.c:8
-
8 sum=sum+i;
-
(gdb) delete Breakpoint 2 //删除断点2
-
(gdb) r //这次程序就会执行出结果
-
The program being debugged has been started already.
-
Start it from the beginning? (y or n) y
-
Starting program: /root/桌面/sun
-
5050
-
Program exited with code 0272.
-
(gdb)
-
(gdb) q //退出程序
-
A debugging session is active.
-
-
Inferior 1 [process 6596] will be killed.
-
-
Quit anyway? (y or n) y
-
[root@localhost 桌面]#
gcc工具大概我们就学这么多了,会编译程序,会调试程序就好了。下面我们就该学习编写makefile文件了。
阅读(1682) | 评论(1) | 转发(1) |