附录三 嵌入式C程序的编译与调试

               课程回顾

C语言库的特性和发展 C语言库的常用库函数 标准库函数的特色应用

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

            附录三

附录三

嵌入式C程序的编译与调试 嵌入式C程序的编译与调试

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

               预习检查

C语言的编译过程分哪几个阶段 嵌入式系统的编译过程分几个阶段 程序中具体有哪几个重要的段

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                                                    课程目标

本章概述

重点

难点

主要描述从源代码编译成可执行文件的过程,以及在操作系统是怎

么运行的

本章目标

掌握C编译的预处理过程,

了解编译,链接的过程 了解程序是如何执行的,以及函数调用时发生了什么

编译的流程

函数调用的深入分析

操作系统是如何执行程序的

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                 本章结构

C语言的编译与运行 C语言的编译与运行

嵌入式编译过程

嵌入式编译过程

C语言编译过程 C语言编译过程

C语言程序的运行 C语言程序的运行

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

               3.1 C语言编译

C语言编译器 C语言编译过程 Makefile

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                               3.1.1 C语言编译器 C语言是在70年代初问世的。一九七八年由美国电话

电报公司(AT&T)贝尔实验室正式发表了C语言。

早期的C语言主要是用于UNIX系统

目前最流行的C语言编译器有以下几种: GNU Compiler Collection 或称 GCC

Microsoft C 或称 MS C Borland Turbo C 或称 Turbo C

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                                       3.1.2 C语言编译过程

编译:编译程序读取源程序(字符流),对之进行词法和语法的

分析,将高级语言指令转换为功能等效的汇编代码,再由汇编程

序转换为机器语言,并且按照操作系统对可执行文件格式的要求

链接生成可执行程序。

C源程序头文件-->预编译处理(cpp)-->编译程序本身--> 优化程序-->汇编程序-->链接程序-->可执行文件

预处理

编译阶段

优化阶段

汇编过程

连接程序

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                                                     3.1.2.1 编译预处理 预处理:读取c源程序,对其中的伪指令(以#开头的指令)和特殊

符号进行处理。

伪指令主要包括以下四个方面:

宏定义指令

如 #define Name #undef

条件编译指令 如#ifdef,#ifndef,#else,#elif,#endif,

头文件包含指令

如#include "FileName"或者#include <FileName>等

特殊符号

如 LINE FILE

预编译程序所完成的基本上是对源程序的“替代”工作。经过此种替代 ,生成一个没有宏定义、没有条件编译指令、没有特殊符号的输出 文件。

这个文件的含义同没有经过预处理的源文件是相同的,但内容有所

不同。

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                             3.1.2.2 编译阶段 预编译程序所要作得工作:

词法分析

语法分析,

翻译成等价的中间代码表示或汇编代码。

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                                           3.1.2.3 优化阶段 优化处理是编译系统中一项比较艰深的技术。它涉及到的问题不仅

同编译技术本身有关,而且同机器的硬件环境也有很大的关系

中间代码的优化

不依赖于具体的计算机

主要的工作是删除公共表达式、循环优化(代码外提、强度削弱、变换循环控制 条件、已知量的合并等)、复写传播,以及无用赋值的删除,

目标代码的生成优化

依赖于具体的计算机

充分利用机器的各个硬件寄存器存放的有关变量的值,以减少对于内存的访问次 数

对指令进行一些调整使目标代码比较短,执行的效率比较高

经过优化得到的汇编代码必须经过汇编程序的汇编转换成相应的机器 指令,方可能被机器执行

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                        3.1.2.4 汇编阶段 汇编过程实际上指把汇编语言代码翻译成目标机器指令

的过程

目标文件中所存放的也就是与源程序等效的目标的机器

语言代码。

目标文件由段组成

代码段 该段中所包含的主要是程序的指令。该段一般是可读和可执 行的,但一般却不可写。

数据段 主要存放程序中要用到的各种全局变量或静态的数据。一般 数据段都是可读,可写,可执行的。

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                             3.1.2.4 汇编阶段 UNIX环境下主要有三种类型的目标文件:

可重定位文件 其中包含有适合于其它目标文件链接来创建一个可执 行的或者共享的目标文件的代码和数据。

共享的目标文件 这种文件存放了适合于在两种上下文里链接的代码 和数据。第一种事链接程序可把它与其它可重定位文件及共享的目标文 件一起处理来创建另一个目标文件;第二种是动态链接程序将它与另一 个可执行文件及其它的共享目标文件结合到一起,创建一个进程映象。

可执行文件 它包含了一个可以被操作系统创建一个进程来执行之 的文件。

汇编程序生成的实际上是第一种类型的目标文件。对于

后两种还需要其他的一些处理方能得到,这个就是链接

程序的工作了。

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                        3.1.2.5 链接阶段

链接程序是将有关的目标文件彼此相连接,使得所有的

这些目标文件成为一个能够被操作系统装入执行的统一

整体。目标文件由段组成

链接处理可分为两种 :

静态链接 动态链接

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

              3.1.3 Makefile

makefile是用于自动编译和链接的 makefile能够纪录文件的信息,决定在链接的时候需要

重新编译哪些文件

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                3.2 嵌入式C程序的编译过程

创建过程 编译 链接 定址

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                            3.2.1 创建过程 源代码转换为可执行的二进制映像的过程

源文件都被编译或汇编到一个目标文件(object file) 可重定位程序(relocatable program) 重定址(relocation)的过程

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

             3.2.2 编译 编译器的工作主要是把用人可读的语言所书写

的程序,翻译为特定的处理器上等效的一系列

操作码。

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                3.2.3 链接

创建过程 编译 链接 定址

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                3.2.4 定址

创建过程 编译 链接 定址

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                    3.3 程序运行 A.out及其传说

段 操作系统在a.out里干了什么 C语言运行在a.out里干了什么 函数调用时发生了什么 Auto和static关键字 Unix/Linux的堆栈段 MS-DOS的堆栈段

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                                                       3.3.1 A.out及其传说

A.out -----“assembler output(汇编程序输出)”的缩写形式

a.out文件格式分析

a.out 文件包含7 个section,格式如下: exec header(执行头部,也可理解为文件头部)

text segment(文本段)

data segment(数据段)

text relocations(文本重定位段) data relocations(数据重定位段) symbol table(符号表)

string table(字符串表)

a.out 是早期UNIX系统使用的可执行文件格式,由 AT&T 设计,现在基本上已被 ELF 文件格式代替

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

               3.3.2

段(segments) :是二进制文件中简单的区域,里面保存了

和某种特定类型(如符号表条目)相关的所有信息 段可以方便地映射到链接器在运行时可以直接载入的对

象中

段在正在执行的程序中是一块内存区域,每个区域都有

特定的目的

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                                     3.3.3 操作系统在a.out里干了什么

为什么a.out要以段的形式组织 段可以方便地映射到链接器在运行时可以直接载入的对象中! 段在正在执行的程序中是一块内存区域,每个区域都有特定的目的

段特点

文本段包含序的指令

数据段包含经过初始化的全局和静态变量以及它们的值

堆栈段用于保存局部变量、临时数据、传递到函数中的参数

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                                   3.3.4 C语言运行在a.out里干了什么 运行时数据结构种类

堆栈

活动记录(activation record)

数据 堆

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                                                3.3.4 C语言运行在a.out里干了什么 堆栈段

堆栈段包含一种单一的数据结构——堆栈 一块动态内存区域,实现了一种“后进先出”的结构 sp,用于提示堆栈当前的顶部位置

堆栈段作用

堆栈为函数内部声明的局部变量提供存储空间

进行函数调用时,堆栈存储与此有关的一些维护性信息

堆栈也可以被用作暂时存储区

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                        3.3.4 C语言运行在a.out里干了什么

如何找到段的地址

例:

声明位于这些段的变量,并打印它们的地址

在不同的计算机架构和不同的操作系统中,堆栈的位置可能各不

相同

#include<stdio.h> main()

{

}

int i;

printf(”The stack top is near %p\n”,&i); return 0;

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                                        3.3.5函数调用时发生了什么

跟踪调用链

C语言自动提供的服务 哪些函数调用了哪些函数 实现机制:堆栈中的过程活动记录

过程活动记录

是一种数据结构

支持过程调用

记录调用结束以后返回调用点所需要的全部信息

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                    3.3.6 Autostatic关键字 A.out及其传说

段 操作系统在a.out里干了什么 C语言运行在a.out里干了什么 函数调用时发生了什么 Auto和static关键字 Unix/Linux的堆栈段 MS-DOS的堆栈段

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                          3.3.7 Unix/Linux的堆栈段 堆栈会自动生长

堆栈段(stack segment)包括两部分:

堆(heap):供动态内存(通过malloc申请的)。堆在BSS区域的上方 ,随着程序不断申请内存,堆会向上增长,ps命令显示的进程占用内存 的大小也会随之变化。

栈(stack):就是维护函数调用的系统栈,函数的参数和本地变量( 除去静态变量)储存在这里。栈位于进程内存空间的最高段,并随着函 数的调用向下增长。函数回调时,栈向上收回,其中的参数和变量数据 作废。

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                                3.3.8 MS-DOS的堆栈段 在DOS中,在建立可执行文件时,堆栈的大小必须同时

确定,而且它不能在运行时增长。

确定堆栈大小的方法根据所使用的不同编译器而不同

在Microsoft编译器中,程序员可以把堆栈的大小作为一个链接器参数来 确定。

STACK: nnn 这个参数告诉Microsoft链接器为堆栈分配nnn字节。

Borland编译器则使用一个特殊名字的变量: unsigned int _stklen = 0x4000;/★16K堆栈+/

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

                       本章总结

C语言的编译与运行 C语言的编译与运行

嵌入式编译过程

嵌入式编译过程

C语言编译过程 C语言编译过程

C语言程序的运行 C语言程序的运行

git@github.com:Kevin-Dfg/Data-Structures-and-Algorithm-Analysis-in-C.git

描述C语言的编译过程

讲述嵌入式编译的过程,深

 入讲述定址链接和定址

简单讲述C程序的运行特性

 

转载于:https://www.cnblogs.com/askDing/p/5443738.html

附录c 编译程序实验 实验目的:用c语言对一个简单语言的子集编制一个一遍扫描的编译程序,以加深对编译原理的理解,掌握编译程序的实现方法和技术。 语法分析 C2.1 实验目的 编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析. C2.2 实验要求 利用C语言编制递归下降分析程序,并对简单语言进行语法分析. C2.2.1待分析的简单语言的语法 实验目的 通过上机实习,加深对语法制导翻译原理的理解,掌握将语法分析所识别的语法成分变换为中间代码的语义翻译方法. 实验要求 采用递归下降语法制导翻译法,对算术表达式、赋值语句进行语义分析并生成四元式序列。 实验的输入和输出 输入是语法分析提供的正确的单词串,输出为地址指令形式的四元式序列。 例如:对于语句串 begin a:=2+3*4;x:=(a+b)/c end# 输出的地址指令如下: (1) t1=3*4 (2) t2=2+t1 (3) a=t2 (4) t3=a+b (5) t4=t3/c (6) x=t4 算法思想 1设置语义过程 (1) emit(char *result,char *arg1,char *op,char *ag2) 该函数功能是生成一个地址语句送到四元式表中。 四元式表的结构如下: struct {char result[8]; char ag1[8]; char op[8]; char ag2[8]; }quad[20]; (2)char *newtemp() 该函数回送一个新的临时变量名,临时变量名产生的顺序为T1,T2,…. Char *newtemp(void) { char *p; char m[8]; p=(char *)malloc(8); k++; itoa(k,m,10); strcpy(p+1,m); p[0]=’t’; return(p); } (2)主程序示意图如图c.10所示。 (2) 函数lrparser在原来语法分析的基础上插入相应的语义动作:将输入串翻译成四元式序列。在实验中我们只对表达式、赋值语句进行翻译。 语义分析程序的C语言程序框架 int lrparser() { int schain=0; kk=0; if(syn=1) { 读下一个单词符号; schain=yucu; /调用语句串分析函数进行分析/ if(syn=6) { 读下一个单词符号; if(syn=0 && (kk==0)) 输出(“success”); } else { if(kk!=1 ) 输出 ‘缺end’ 错误;kk=1;} else{输出’begin’错误;kk=1;} } return(schain); int yucu() { int schain=0; schain=statement();/调用语句分析函数进行分析/ while(syn=26) {读下一个单词符号; schain=statement(); /调用语句分析函数进行分析/ } return(schain); } int statement() { char tt[8],eplace[8]; int schain=0; {switch(syn) {case 10: strcpy(tt,token); scanner(); if(syn=18) {读下一个单词符号; strcpy(eplace,expression()); emit(tt,eplace,””,””); schain=0; } else {输出’缺少赋值号’的错误;kk=1; } return(schain); break; } } char *expression(void) {char *tp,*ep2,*eplace,*tt; tp=(char *)malloc(12);/分配空间/ ep2=(char *)malloc(12); eplace=(char *)malloc(12); tt =(char )malloc(12); strcpy(eplace,term ());/调用term分析产生表达式计算的第一项eplace/ while(syn=13 or 14) { 操作符 tt= ‘+’或者‘—’; 读下一个单词符号; strcpy(ep2,term());/调用term分析产生表达式计算的第二项ep2/ strcpy(tp,newtemp());/调用newtemp产生临时变量tp存储计算结果/ emit(tp,eplace,tt,ep2);/生成四元式送入四元式表/ strcpy(eplace,tp); } return(eplace); } char *term(void)/仿照函数expression编写/ char *factor(void) {char *fplace; fplace=(char *)malloc(12); strcpy(fplace, “ ”); if(syn=10) {strcpy(fplace,,token);/将标识符token的值赋给fplace/ 读下一个单词符号; } else if(syn=11) {itoa(sum,fplace,10); 读下一个单词符号; } else if (syn=27) {读下一个单词符号; fplace=expression();/调用expression分析返回表达式的值/ if(syn=28) 读下一个单词符号; else{输出‘}’错误;kk=1; } } else{输出‘(’错误;kk=1; } return(fplace); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值