linux命令
统计相关
find . -name *.c | wc -l //查找并统计c程序文件的个数
find . -name *.c -exec wc {} -l \; //查找并统计每个C程序的行数
find . -name *.c -exec cat {} \; | wc -l //查找并统计所有c程序的总行数
编译分析
gcc simple.c -o simple //编译生成为指定文件,默认为a.out
gcc -S simple.c //生成 simple.s 的汇编程序
gcc -E print.c > print.i //预处理,头文件的引入与处理
gcc -v print.c //生成编译链接过程,libc.a
cc1 //编译器
as //汇编器
collect2 //链接器
objdump -d a.out //得到所有机器指令(反汇编)
echo $? //上一个程序执行后的返回值
objcopy -O binary -j .text a.out text.bin //提取可执行文件的代码
objcopy -O binary -j .data a.out data.bin //提取可执行文件的数据
file a.out //文件格式(类型)信息
hexdump -C a.out //查看二进制文件的内容
readelf -a a.out //分析ELF文件
ps aux | grep a.out
C语言知识
代码段和数据段
局部变量的数据分配在栈上,且赋值操作会被解析成指令;全局变量分配在数据区,赋初值的等号相当于冒号,并不解析成指令。
物理地址与虚拟地址
&local = 0xbfb8948c
&global = 0x804a018
main = 0x8048414
_start is 0x8048360 //c语言真正的入口
直观映像,内存跨度 128M ~ 3G 。
操作系统管理物理内存,每个进行都有独立的内存空间,程序打印的地址都是虚拟地址,其对应关系由操作系统内核管理。
extern _start; //由链接器生成的
...
printf("_start is %p\n", &_start);
调试宏
#define PRINT(x) printf("<debug>" #x "= %d\n", x)
//#define PRINT(x)
条件编译;-lm 链接时加入数学库
#if DEGUG
…
#endif
$ gcc t.c -lm -DDEBUG //定义
$ gcc t.c -lm -UDEBUG //不定义
用来交换变量的宏,do...while的经典应用,注意两个关键点
#define SWAP(a,b) \
do{ \
char tmp; \
tmp = b; \
b = a; \
a = tmp; \
}while(0) //故意不要语法要求的分号
if(j >= 0)
SWAP(x, y);
else //else前面原本是不应该有分号的
print("error\n");