1、Professional Programming,-Secrets behind the code,TA:毛先领,上机时常问的问题,为什么要先点击“编译”,再“运行”?为什么局部变量和全局变量有不同的生命周期?(或为什么这个变量只能在这个函数内引用?)为什么VB不用编译直接运行即可?为什么我的程序编译不了? . 为什么 ,编程不仅仅是只知道语法规则,必须了解程序背后的秘密 -计算机的系统结构 -计算机程序的运行方式 -编译原理 .,Niubility!,outline,程序的编译流程程序与计算机体系结构程序的运行方式程序的调试(GDB)POJ 例子Q&A,outline,程序的编译流程程序与计
2、算机体系结构程序的运行方式程序的调试(GDB)POJ 例子Q&A,程序的编译流程,.c文件经过预处理(gcc 时带上 -E选项)产生.i文件 预处理 编译 汇编 连接.c-.i-.s-.o-a.out -E -S -c,Pre-processor(cpp),hello.i,Compiler(cc1),hello.s,Assembler(as),hello.o,Linker(ld),hello,hello.c,Sourceprogram(text),Modifiedsourceprogram(text),Assemblyprogram(text),Relocatableobjectprogram
3、s(binary),Executableobjectprogram(binary),printf.o,A Example,源程序,1、预处理,预处理:使用-E参数输出文件的后缀为“.cpp”gcc E o gcctest.cpp gcctest.c使用wc命令比较预处理后的文件与源文件,可以看到两个文件的差异,行数 单词数 字节数,预编译,预处理文件汇编代码1)使用-x参数说明根据指定的步骤进行工作,cpp-output指明从预处理得到的文件开始编译2)使用-S说明生成汇编代码后停止工作gcc x cpp-output S o gcctest.s gcctest.cpp也可以直接编译到汇编代码
4、gcc S gcctest.c,2、编译成汇编代码,预处理文件汇编代码,直接编译到汇编代码,3、编译成目标代码,汇编代码目标代码gcc x assembler c gcctest.s直接编译成目标代码gcc c gcctest.c使用汇编器生成目标代码as o gcctest.o gcctest.s,汇编代码目标代码,直接编译成目标代码,使用汇编器,4、编译成执行代码,目标代码执行代码gcc o gcctest gcctest.o直接生成执行代码gcc o gcctest gcctest.c,目标代码执行代码,直接生成执行代码,outline,程序的编译流程程序与计算机体系结构程序的运行方式程
5、序的调试(GDB)POJ 例子Q&A,程序与计算机体系结构,图灵机 磁带、控制器以及读写磁头三部分组成,Registers,On-chip L1cache (SRAM),Main memory(DRAM),Local secondary storage(local disks),Larger, slower, and cheaper (per byte)storagedevices,Remote secondary storage(distributed file systems, Web servers),Off-chip L2cache (SRAM),CPU registers hold
6、words retrieved from cache memory.,L0:,L1:,L2:,L3:,L4:,L5:,Smaller,faster,and costlier(per byte)storage devices,Mainmemory,I/O bridge,Bus interface,ALU,Register file,CPU,System bus,Memory bus,Disk controller,Graphicsadapter,USBcontroller,Mouse,Keyboard,Display,Disk,I/O bus,Expansion slots forother d
7、evices suchas network adapters,hello executable stored on disk,PC,Mainmemory,I/O bridge,Bus interface,ALU,Register file,CPU,System bus,Memory bus,Disk controller,Graphicsadapter,USBcontroller,Mouse,Keyboard,Display,Disk,I/O bus,Expansion slots forother devices suchas network adapters,PC,hello,Userty
8、peshello,Mainmemory,I/O bridge,Bus interface,ALU,Register file,CPU,System bus,Memory bus,Disk controller,Graphicsadapter,USBcontroller,Mouse,Keyboard,Display,Disk,I/O bus,Expansion slots forother devices suchas network adapters,hello executable stored on disk,PC,hello code,hello,worldn,outline,程序的编译
9、流程程序与计算机体系结构程序的运行方式程序的调试(GDB)POJ 例子Q&A,程序的运行方式,以汇编代码为例 gcc S gcctest.s gcctest.c,.file gcctest.c .section .rodata.LC0: .string Hello World!.LC1: .string i=j+1=%dn .text.globl main .type main, functionmain: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx subl $
10、36, %esp movl $0, -12(%ebp) movl $0, -8(%ebp) movl -8(%ebp), %eax addl $1, %eax movl %eax, -12(%ebp) movl $.LC0, (%esp) call puts movl -12(%ebp), %eax movl %eax, 4(%esp) movl $.LC1, (%esp) call printf movl $0, %eax addl $36, %esp popl %ecx popl %ebp leal -4(%ecx), %esp ret .size main, .-main .ident
11、GCC: (GNU) 4.1.2 (Ubuntu 4.1.2-0ubuntu4) .section .note.GNU-stack,progbits,Kernel virtual memory,Memory mapped region forshared libraries,Run-time heap(created at runtime by malloc),User stack(created at runtime),Unused,0,Memoryinvisible touser code,0xc0000000,0x08048000,0x40000000,Read/write data,R
12、ead-only code and data,Loaded from the hello executable file,printf() function,0xffffffff,outline,程序的编译流程程序与计算机体系结构程序的运行方式程序的调试(GDB)POJ 例子Q&A,程序的调试(GDB),Gcc 编译代码时必须加上-g选项,同时也可以打开-Wall选项查看所有的警告信息,gcc的高级选项,-Wall:打开所有的警告信息,根据警告信息检查源程序,Main函数的返回值为int,在函数的末尾应当返回一个值,修改源程序,gdb,Gdb = GNU debugerGNU tools中的调
13、试器,功能强大设置断点监视、修改变量单步执行显示/修改寄存器的值堆栈查看远程调试,gdb使用举例,源代码如下,编译:gcc o bug bug.c,编译并运行,?,编译,使用gdb调试bug,运行bug,输入字符串hello,显示出错位置,能不能看到源代码呢?,使用gcc的-g参数,gcc g o bug bug.c重新调试,列出源代码,?怎么修改前面的源代码呢?,设置断点,outline,程序的编译流程程序与计算机体系结构程序的运行方式程序的调试(GDB)POJ 例子Q&A,POJ 2750鸡兔同笼,Description一个笼子里面关了鸡和兔子(鸡有2只脚,兔子有4只脚,没有例外)。已经知道了笼子里面脚的总数a,问笼子里面至少有多少只动物,至多有多少只动物Input第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,每行一个正整数a (a nlines; while (nlines-) int legs; cin legs; if (legs % 2 = 1) cout 0 0 endl; else if (legs % 4 = 0) cout legs/4 legs/2 endl; else cout legs/4 + 1 legs/2 endl; ,Q&A,?,