gcc编译知识:
form Linux内核完全注释修改v3.0
使用gcc编译c语言程序经历四个阶段:
一、预处理:gcc把c程序传递给cpp,对指示符和宏进行替换处理,输出纯C语言代码。
二、编译:纯.c代码被编译器生成对应的与机器相关的汇编代码.s。
三、汇编:汇编器把汇编代码转换成机器指令,保存在目标文件.o中。
四、链接:最后GNU链接器把所有目标文件链接在一起,生成可执行映像文件。
gcc 命令格式:
gcc [选项] [-o 目标文件] [c语言文件]
例子:
gcc -o hello hello.c //编译生成可执行文件hello
gcc -s -o hello.s hello.c //编译生成对应汇编程序hello.s
gcc -c -o hello.o hello.c //编译生成对应目标文件hello.o不链接
知识点:
圆括号中的组合语句: “({…})” 在GNU C中用作一个表达式使用。
例子:
({
int y= f00();int z;
if(y>0) z=-y;
else z=y;
3+z;})
/*组合语句最后一条跟随一个分号表达式,表达式的值 “3+z” 为整个圆括号括住语句的值。
如果最后一条语句不是表达式,则整个语句表达式就是void类型,因此没有值*/
内核源码:
init/main.c 中读取CMOS时钟信息宏定义:
#define CMOS_READ(add) ({
outb_p(0x80|addr,0x70);\ //首先向IO端口0x70输出像读取的addr。
inb_p(0x71);\ //然后从端口0x71读入该值作为返回值。
})
include/asm/io.h头文件读取IO端口port的宏定义,最后的变量_v的值就是inb()的返回值。
#define inb(port)({
unsigned char _v;
__asm__volatile(“inb %%dx,%%al”:"=a" (_v):“d”(port));
_v;
})
知识点:
内联函数
如果把一个函数声明为内联(inline)函数,那么gcc把函数的代码集成到调用该函数的代码中去,节省函数调用进入/退出的时间。如果编译过程中没有使用"-o",那么内联函数和普通函数一样。
inline int inc(int *a)
{
(*a)++;
}
知识点:(后面自己再看3.5)
目标文件格式:分析a.out文件组成
一共七部分:
文件头、代码区(正文段)、已初始化的数据区(数据段)、重定位信息区、符号表、字符串表
知识点:
Makefile
Makefile编译一个有很多源程序的大型程序。
格式:
目标(target):先决条件(prerequisites)
命令(command)
...
//目标 可以是文件、命令、
//先决条件 是一个或者多个文件,
//命令 是make需要执行的操作,一个规则可以是很多命令
//$@ 表示目标
//$< 表示第一个先决条件
//$^ 表示所有先决条件