实现一个基于tcc/tlink的简单的编译链接工具

实现一个基于tcc/tlink的简单的编译链接工具

一、基础研究

在这里我们需要提供一套新的c语言开发工具cc,它支持的c程序不是从main开始运行而是从CMain开始运行。

书上已经对该工具程序进行了需求分析:(1)要在屏幕中间显示彩色的字符串;(2)等待用户输入,按下任意键后开始运行程序员写的程序。

也给出了由需求分析进行的功能分析:代码文件main.obj实现打印字符串、等待输入、调用程序的功能。编译链接文件cc.exe实现调用tcc编译文件、调用tlink连接文件的功能。

新建文件夹,在其中实现main.c如图:

 实现一个基于tcc/tlink的简单的编译链接工具

main.c编译成main.obj文件,并将tcc.exetlink.exe以及编译连接所需文件都拷贝到文件夹中。

这里我们要实现一个编译连接程序cc.cc.bat功能相同。

那么首先来看看什么是批处理文件:批处理就是对某对象进行批量的处理。批处理文件的扩展名为.bat。在“命令提示”下键入批处理文件的名称,或者双击该批处理文件,系统就会调用Cmd.exe运行该批处理程序。我们来看看c.bat的内容:

 实现一个基于tcc/tlink的简单的编译链接工具

这里@表示不显示@后面的命令,echo是一条批处理指令,echo off是关闭回显功能,即后面的语句执行时都不会在屏幕上显示。%1表示传过来的参数。

但是这里批处理使用了dos命令tcc和tlink,而dos命令是不能直接写在c程序里的,能否在c程序里使用dos命令呢?我们来看system函数的功能,它可以发出一个dos命令,如我们要在c程序里使用命令tcc main,可以用system(“tcc main”);来实现。这里还要用到的一个函数strcat,可以把一个字符串添加到另一个字符串结尾处,覆盖另一个字符串结尾处的‘\0’)并添加‘\0’,合成一个完整的字符串。

一个参考程序putarg.c,我们来看看它的内容:

 实现一个基于tcc/tlink的简单的编译链接工具

这个程序的作用是将arg字符数组的值作为一个字符串输出,而且我们要注意这里的参数arg是一个二阶指针,它的作用是什么呢?我们来运行一下:

 实现一个基于tcc/tlink的简单的编译链接工具

 

首先输出了当前的绝对路径,然后输出了我们加在后面的参数,这说明程序是将命令行的参数名作为字符串即字符数组的形式来处理的,*arg的值为参数的字符串的首地址,而**arg的值是字符串的每一个字符。为什么这里n代表命令行参数的个数,arg指向参数的首地址呢?查找资料可知这是main函数不是作为普通函数来使用的,所以它的参数是有特殊用途的。main函数如果带参有两个参数,那么第一个表示参数的个数;第二个参数中argv[0]为自身运行目录路径和程序名,argv[1]指向第一个参数、argv[2]指向第二个参数、等等。

那么我们就可以通过使用带参数的main函数接收我们要编译连接的c文件名,然后将它用strcat进行处理,在用system执行进行编译连接。

编写程序如下:

 实现一个基于tcc/tlink的简单的编译链接工具

这里用数组abcd存储批处理文件里不用改的部分字符串。在开始进行判断,如果n小于2,说明在命令行没有输入要编译的文件名,则提示错误信息并返回。

之后将要编译的文件名加在数组a的后面,形成一句完整的tcc编译语句,将目标文件编译成obj文件。因为arg指针指向的第一个值是本程序的绝对路径,即arg[0]的值是本程序的绝对路径,而arg[1]是存储要编译的文件的字符串的首地址。然后用system执行数组a存放的tcc编译语句。

之后要判断字符串是否结束,如果未结束,则判断字符是否为’.’,因为我们如果在命令行输入的参数是XXX.c,那么tcc时后面加XXX.c是正确的,但是在tlink语句里面加XXX.c是错误的,应该用XXX或者XXX.obj,为了简便我们就使用名字。然后将“.”改成转义字符“\0”表示字符串已经结束。

之后再用strcattlink连接语句拼接好用system执行。

执行结果如下:

 实现一个基于tcc/tlink的简单的编译链接工具

如果不输入文件名则提示错误。如果输入则正确编译连接。运行编译连接生成的exe文件如图:

 实现一个基于tcc/tlink的简单的编译链接工具

 

先在屏幕中间显示显示彩色字符串,再执行CMain函数“welcome to c”,输出字符串“hello world!”。

二、扩展研究

(1)为什么main函数的参数是参数的个数和命令行参数字符串?

答:我认为是参数是在程序跳转到main函数之前初始化时将命令行的参数的字符串地址传递到栈里,再在main函数里通过栈调用。

三、研究总结

今天我们自己基于tcctlink实现了一个编译连接工具cc,它的功能与tcc相似,都是编译连接程序,只是多出了显示欢迎字符串和等待输入再执行程序的功能。向下看,其本质还是tcc的功能,我们并没有真正地实现一个编译器和连接器,向上看,这个程序的实现是一个不断集成的过程,再加上别的功能的obj文件可以组合成更大更丰富的程序。

这一章对共性和个性的分离和封装更加清晰了:共性被封装在编译工具里,个性由要编译的程序实现,按照这个思路,我们可以开发出功能更强大的编译连接工具。

这一张我觉得学习了一个很重要的函数system,我们可以通过程序来调用操作系统的功能,它与我们传统的思维是不同的,我觉得操作系统打开软件执行,软件实现功能后返回操作系统,而这里软件可以调用操作系统的功能,这使我们写的程序可以实现更强大的功能。这种操作是由顶层向底层的调用。

转载于:https://www.cnblogs.com/stormpeach/p/4364007.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/109507.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 看完了aspnetmvc nerdinner项目

    看完了aspnetmvc nerdinner项目这几天一直在看aspnetmvc-nerdinner这本书中的Nerdinner代码编写的全过程。其实觉得用最原始的办法:动手敲代码带给我们的好处比单纯的看然后Copy代码再运行要好的多,最起码加深了我们的记忆。前段时间看了ASP.NET网站上关于ASP.NETMVC编程的培训文章,觉得MVC挺强大的,然后就试着自己做了一个小项目,可是在做的过程中,很多东西确实见多人家怎么做,也知道大概…

    2022年9月29日
    4
  • laravel模版共用数据解决方法

    laravel模版共用数据解决方法

    2021年7月6日
    72
  • 女友:啥,识别个文字还要付费?我立马用Python实现了一款免费版文字识别工具[通俗易懂]

    女友:啥,识别个文字还要付费?我立马用Python实现了一款免费版文字识别工具[通俗易懂]导语有一天和女朋友聊天,翻着手机上的软件,看电影、看编程网站,她说到:“这么多APP,怎么就没一个做文字识别很方便的呢?我经常读书读到一段话想把它摘抄下来,可是这些软件不是打开进入文字识别步骤很复杂,就是限制识别次数,要么就是限制编辑,很多识别软件还都是付费的,好烦“。然后程序员小哥说:“要不我给你做一个免费版本文字识别小程序?”话不多话,对象第一,开干~~~​​​正文程序原理简介:python利用百度文字识别功能,实现对上传的图片进行扫描,获取图片的文字信…

    2022年5月27日
    37
  • centos在设置时区

    centos在设置时区

    2022年1月15日
    45
  • 国内常用NTP服务器地址及IP(阿里云时间服务器)

    国内常用NTP服务器地址及IP(阿里云时间服务器)210.72.145.44(国家授时中心服务器IP地址)133.100.11.8日本福冈大学time-a.nist.gov129.6.15.28NIST,Gaithersburg,Marylandtime-b.nist.gov129.6.15.29NIST,Gaithersburg,Marylandtime-a.timefreq.bldrdoc.gov132.

    2022年5月3日
    71
  • url加时间戳避免再次请求当前路径出现的缓存问题[通俗易懂]

    url加时间戳避免再次请求当前路径出现的缓存问题[通俗易懂]1.先解释一下,为什么要加时间戳: URL后面添加随机数通常用于防止客户端(浏览器)缓存页面。浏览器缓存是基于url进行缓存的,如果页面允许缓存,则在一定时间内(缓存时效时间前)再次访问相同的URL,浏览器就不会再次发送请求到服务器端,而是直接从缓存中获取指定资源。2.加时间戳的方法:[javascript] viewplain copy

    2022年5月1日
    223

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号