C编译器剖析_1.4 UCC编译器预览_UCC的使用

C编译器剖析_1.4 UCC编译器预览_UCC驱动 在上一小节,通过以下四条命令,我们有意地给ucc传递不同的参数来依次调用预处理器、编译器、汇编器和连接器。当然实际使用ucc命令时,我们不会绕这么大一个圈子,直接用”ucc  hello .c -o hello”即可得到可执行程序hello。 iron@ubuntu:demo$ ucc -E hello.c -o hello.i iron@ubuntu:demo$ ucc --dump-a 阅读详情

1.4.1  UCC的使用

    通过第1.3节的例子ucc\examples\sc,我们对如何根据语言的文法来编写语法分析器,建立语法树,之后在语法树的基础上生成中间代码有了一个感性的直观认识。当然,光有这些中间代码,C程序员还不能得到其所要的计算结果。C编译器还要由中间代码产生汇编代码。在剖析UCC编译器前,让我们先熟悉一下UCC编译器的使用。UCC编译器的大部分代码都是用标准C语言并调用C标准库来编写,可在Linux或Windows系统上生成32位的x86汇编代码,这些代码需要32位的函数库的支持才能在相应系统中运行。在后续的章节中,为节省篇幅,我们主要以32位Ubuntu系统为例来讨论。在VMware等虚拟机上安装32位Ubuntu系统不算太复杂,这里不再画蛇添足。需要在ucc/makefile第1行和ucc/driver/linux.c第7行配置UCC的安装目录UCCDIR,比如” /home/iron/bin”。如果ucc的源代码被解压到” /home/iron/src/ucc”目录,则经过以下步骤就可构建并安装UCC到” /home/iron/bin”中。

    iron@ubuntu:ucc$ pwd

    /home/iron/src/ucc

    iron@ubuntu:ucc$ make -s

    iron@ubuntu:ucc$ make -s install

    iron@ubuntu:ucc$ make -s test

    为了使用户能方便地使用ucc命令,我们还需要设置一下环境变量PATH,具体的操作如下所示,由” cd ~ ”进入当前用户主目录,在gedit打开的.bashrc文件末尾添加一行”exportPATH=$PATH:/home/iron/bin”, 其中”/home/iron/bin”即为前文所设定的UCCDIR,保存后退出,重新打开一个终端,即可使用ucc命令。

    iron@ubuntu:ucc$  cd ~

    iron@ubuntu:~$  gedit  .bashrc

    接下来,我们用一个简单的例子来解释一下UCC的大致工作流程。编写以下C代码,存为文件”hello.c”。这份代码用于求阶乘,其中有if语句、while语句、库函数调用及递归函数。

#include <stdio.h>

int f(int n){

         if(n < 1){

                   return 1;

         }else{

                   return n *f(n-1);

         }

}

int main(){

         int i = 1;

         while(i <= 10){

                   printf("f(%d)= %d\n",i,f(i));

                   i++;

         }

         return 0;

}

    C源代码hello.c需要先经过预处理器(C  PreProcessor)预处理。预处理器会根据预设的include目录去查找并包含头文件,并对宏定义进行展开,如果找不到对应的头文件,则报错,这类错误是预处理报的错,还未到编译器阶段。

    预处理器后的结果hello.i,才是作为编译器的输入,诚如UCC的原作者在”ucc\doc\UCC User Manual.txt”中所言” Before reporting bugs: ……. , send the prepocessed files towenjunw@yahoo.cn” ,编译器看到的是preprocessed后的文件。有时侯,编译器可能报出数以百计的语法错误,其原因可能仅是宏定义时出了点差错,这时打开预处理后的文件看看,就能很清楚哪里出问题了。

    编译器会对hello.i进行词法分析、语法分析、语义检查和中间代码生成,经过前面几节的准备,我们对这些概念应有点感觉了,这几个阶段被称为编译器的前端,它们与具体的机器无关。C编译器再根据中间代码生成不同硬件平台的汇编语言,这部分工作被称为编译器的后端,与具体的机器相关,因为不同机器的机器指令是各不相同的。当然,编译器还有“优化”这样的重点戏需要完成,这也是编译相关研究的当前热点。而中间代码实际上起到了连结前端和后端的桥梁作用。

    有了汇编代码hello.s后,还需要借助汇编器assembler根据汇编语言来“装配”成机器码,由此产生了目标代码hello.o,其中为.o代表的是object,译为“目标”,与面向对象的object是同一个英文单词。既然不同硬件平台的机器代码是不同的,那能不能定义一套中间代码,我们假设有一个虚拟的机器,其机器代码正好就是我们的中间代码。这样,程序员所编写的高级语言被编译成中间代码,再把这些中间代码送给用软件实现的虚拟机来解释执行,各个平台上预先写好各自的中间代码虚拟机,那生成的中间代码就可以跨平台了。这一定让你想起了Java和” Write Once , RunAnywhere”那让人热血沸腾的Slogan。当然,与运行平台相关的工作及优化的重头戏就交给了Java 虚拟机。”天之道损有余 而补不足”,所以总体而言,上帝是公平的。正如在星际争霸里的人族、神族和虫族一样,如果参数太失衡,就不好玩了。Java得到跨平台的代价是牺牲了一部分的运行效率,但在程序员比CPU和内存贵的今天,这种牺牲还是有经济上的意义的。生成中间代码之后解释执行,比”生成机器代码之后直接运行速度更低”的原因,就好比有一本英语原版书,翻译的方法可以有口译和笔译,口译的方式每次都要找口译员帮你解释一下,讲完你可能就忘了;而笔译的好处是笔译员翻译一遍后,你就有了一份中文版的书,以后就不用再麻烦笔译员了。Java虚拟机采取的加速方案有即时编译Just InTime,如果运行时发现有些中间代码要被多次解释执行,那我们干脆就在动态运行时,把相应的中间代码翻译成机器代码吧,这就是所谓的”即时”。当然,道理很简单,做起来很难。

     目标模块hello.o还需要携手函数库和其他的目标代码才能得到可执行程序hello,这个工作被称为Linking,即连接,也有写为链接的,哪个是错误字,已经傻傻分不清楚了,权当IT世界的通假字吧,这个工作由连接器Linker完成。在此阶段出现的错误有,全局变量(或函数)重复定义,全局变量(或函数)未定义等。

C编译器剖析_4.2 语义检查_表达式的语义检查(4)_函数调用 4.2.4 函数调用的语义检查      在这一小节中,我们来讨论一下函数调用的语义检查,语法上,函数调用对应的表达式属于后缀表达式PostfixExpression,UCC编译器exprchk.c的函数CheckFunctionCall()完成了对函数调用的语义检查,如图4.2.18所示。在阅读这份代码时,需要对语法分析后为函数调用构造的语法树有较好认识,请先参照”图3.1.21后缀运算符对应 阅读详情

相关推荐

C编译器剖析_5.1 中间代码生成及优化_简介

本节对UCC编译器的中间代码生成及优化进行简介,给出基本块BasicBlock、三地址码、控制流图CFG的相应数据结构,介绍有条件跳转、无条件跳转和间接跳转等概念。

SheIsC的专栏 4907

C编译器剖析_2.5 UCC编译器的符号表管理

这一节,我们准备初步讨论一下UCC编译器的符号表管理,与符号表管理相关的代码主要在ucl\symbol.h和ucl\symbol.c中。UCC编译器内部需要对用到的所有符号进行分类,并建立相应的数据结构来记录与符号相关的信息。图2.5.1第25行的结构体struct symbol用于记录与符号相关的信息,这些信息如图第7至23行所示。第8行的kind用于区别不同类别的符号,其取值范围如图第1至5行

SheIsC的专栏 3111

Ucc: Unicorn系统静态文件编译器实战指南

本文还有配套的精品资源,点击获取 简介:Unicorn系统的静态文件编译器Ucc是一个高效的工具,专门用于优化JavaScript代码,提升性能、减少资源消耗、增强安全性和简化部署。它包括源代码、文档、测试套件、示例和构建脚本等部分,是一个完整的设计用于编译和压缩JavaScript资源的系统。通过Ucc,开发者可以实现性能提升、资源减少、安全性增强和部署简化。 ...

weixin_36078669的博客 1430

掌握UCC开源C编译器源代码精髓

编译器是一种特殊的软件,它负责将一种语言编写的源代码转换成另一种形式。在计算机科学中,最常见的转换是从高级编程语言到机器语言。编译器的核心功能是实现编程语言的语义规定,保证从源代码到目标代码的正确转换。

weixin_42405592的博客 1205

ucc-c-compiler:用C实现的C编译器

用C语言编写的AC编译器 依存关系 C标准库 as (使用gnu-as和darwin-as [现在clang-as]进行了测试,但是任何都可以) ld (任何都可以) 使用C89编译器来构建该编译器 特征 编译器实现C89,C99和C11(可通过-std=c89/c99/c11 )。 完全支持系统库,包括与va_list结构的ABI兼容性。 以下列出了一些主要的新增功能: 增加的功能: Microsoft / Plan 9结构扩展 Lambda / Objective-C样式块 函数的尾随返回类型 命名空间检查 标准支持(并非详尽无遗): C89,C99 C11 _Bool , _Noreturn , _Alignof , _Alignas _Generic , _Static_assert 功能支持: 浮点类型 无符号整数 char , short , long和(仅在6

中文编译器 ucc

UCC是由清华学生开发的一块简单c语言编译器,结构清晰,方便学习!

C编译器剖析PDF文档_UCC162.3源代码

包含C编译器剖析PDF文档,及修改少量BUG后的编译器源代码UCC162.3, 欢迎访问对应博客http://blog.csdn.net/sheisc

UCC开源C编译器源代码

UCC是一款小巧并且优秀的开源C编译器代码,可将C源代码直接编译成给予LINUX或WIN平台的可执行程序.

UCC28019中文资料

UCC28019中文资料,翻译绝对准确,花了RMB买来的

WOFOST模型参数调优实战:从‘跑不通’到‘预测准’的避坑指南

本文详细介绍了WOFOST模型参数调优的实战技巧,帮助用户从模型报错诊断到参数敏感性分析,再到土壤-作物参数联调策略,逐步解决‘跑不通’到‘预测准’的问题。通过Python和PCSE工具,提供参数扰动测试模板和关键参数优先级矩阵,助力作物模型的高效校准与预测。

weixin_32597009的博客 622

基于相位检测与锁相环的DIY超声波风速仪设计与实现

相位检测是信号处理中的一项基础技术,它通过测量两个周期信号之间的相位差来获取信息。其核心原理在于,当信号在介质中传播时,外部因素(如风速)会改变其传播速度,从而导致接收端信号的相位发生偏移。锁相环(PLL)是实现高精度相位检测的关键电路,它能动态调整本地振荡器的频率,以跟踪并锁定输入信号的相位,从而将微小的相位变化转换为易于测量的电压信号。这项技术的工程价值在于其对电路精度要求相对较低,鲁棒性好,非常适合低成本、高灵敏度的测量应用。在气象监测、工业传感和消费电子等领域,相位检测技术被广泛用于风速风向测量、位

weixin_29540599的博客 387

欧姆龙多PLC串行链接模式的应用

欧姆龙多PLC串行链接模式的应用 一、如何将两台CP1H进行串行PLC连接(PLC串行链接) 主机侧设定 从机侧设定 二、 如何实现编程通信 主机侧的【PC连接模式】为【全部】的时候 ① 主机会把自己的地址从3100开始,按照【链接字】设定的字数个数发送到每个从机的3100开始进行存储。 ② 从机会把自己的地址从31n0开始,按照主机侧参数【链接字】设定的字数个数发送到主机的31n0开始进行存储。 注:(n为从机的地址号,若从机号不连续,则该编号的地址将不被定义..

u014202847的博客 3087

别再折腾虚拟机了!手把手教你用WSL2在Windows 11上安装Kali Linux(含汉化与图形界面)

本文详细介绍了如何在Windows 11上通过WSL2安装和配置Kali Linux,包括汉化与图形界面设置。通过WSL2,用户可以享受接近原生性能的Linux体验,同时保持与Windows系统的无缝集成,特别适合网络安全爱好者和开发者。文章还提供了常见问题解决和性能优化建议,帮助用户高效使用Kali工具集。

weixin_42525369的博客 322

FPGA实现PCIe接口

PCI Express(PCIe)是一种高速串行计算机扩展总线标准,在FPGA中实现PCIe接口可以实现与主机系统的高速数据通信。以下是FPGA实现PCIe接口的关键技术要点。

whm128的博客 1462

Vue - 解决 Property or method “__v_isRef“ is not defined on the instance but referenced(浏览器控制台报错,代码没错)

vue,vue2控制台报错,vue报错Propertyormethod"__v_isRef"isnotdefinedontheinstancebutreferenced,vue代码没问题,但是报错Propertyormethod"__v_isRef"isnotdefinedontheinstancebutreferenced,vue2如何解决报错,vue怎么解决报错问题,vue2Propertyormethod"__v_isRef"isnotdefi

🏆 前端领域优质创作者 4503

Python爬虫实战:使用Scrapy+Playwright高效爬取全球专利数据库

本文将详细介绍如何使用Python最新技术栈(Scrapy+Playwright)构建一个高效的专利数据库爬虫系统。我们将从爬虫基础知识讲起,逐步深入到反爬应对策略、分布式爬虫架构以及数据存储方案,最终实现一个完整的专利数据采集系统。专利数据是技术创新领域的重要信息资源,包含技术描述、权利要求、申请人信息等宝贵数据。中国国家知识产权局(CNIPA)美国专利商标局(USPTO)欧洲专利局(EPO)世界知识产权组织(WIPO)

2201_76125261的博客 1384

【温室气体数据集】CAMS 发布的温室气体(GHG)数据集总结

【温室气体数据集】CAMS 发布的温室气体(GHG)数据集总结

WW、forever的博客 555

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

上一篇: C编译器剖析_1.3 由文法到分析器_语句Statement
下一篇: C编译器剖析_1.4 UCC编译器预览_UCC驱动
SheIsC
博客等级 码龄12年 224粉丝 64原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值