zoukankan      html  css  js  c++  java
  • 深入研究C语言 第三篇

    本篇研究TC2.0下其他几个工具。同时看看TC由源代码到exe程序的过程。

    1. 用TCC将下面的程序编为.obj文件

    clip_image001[4]

    我们知道,TCC在默认的编译连接一个C语言的源程序a.c的时候分为以下两步:

    (1).TCC将源程序文件编译成a.obj。

    (2).TCC调用TLINK将c0s.obj,cs.lib,emu.lib,maths.lib中的a.obj中的程序要用到的代码与a.obj的代连接到一起生成.exe文件。

    并且,我们还知道,TCC可选参数有如下:

    clip_image003[4]

    我们看到有这样的选项:Compile only(只编译)。这应该是只编译生成.obj文件的选项。我们验证如下:

    clip_image005[4]

    我们看到,文件夹下确实只生成了.obj文件:

    clip_image006[4]

    2.用C:C cc a.c的方法编译下面程序:

    clip_image007[4]

    我们看源程序,很明显的没有定义和实现f函数。我们看编译连接过程中的错误提示:

    clip_image009[4]

    如我们所料,这里出现了错误提示:在a.c中没有发现f函数。

    我们看错误提示,在a.c中没有发现f函数。我们很容易想到,这里是不是不止从a.c中寻找f函数?或者这里是不是可以不止从a.c中寻找?我们又联想到TCC函数有同时编译连接多个.c文件的选项。我们尝试编写两个文件,并共同编译:

    clip_image010[4]

    编译连接过程:

    clip_image011[4]

    我们看到并没有错误提示。并且在文件夹下生成了A.exe。我们运行查看:

    clip_image012[4]

    我们看到,将同一个程序写在两个文件中,程序也可以正常的编译连接。

    3.TLIB.exe

    我们从书中看到,TC2.0给我们提供了一个工具tlib.exe,可以用tlib.exe将一个.obj文件中的代码加到一个.lib文件中。

    首先我们需要了解TLIB.exe的参数。我们仿照TCC的方法,在cmd中执行TLIB。其参数表如下:

    clip_image013[4]

    我们看到其参数,+是将一个文件添加进lib文件中。我们尝试:

    clip_image014[4]

    clip_image015[4]

    我们看其属性,他确实被修改了。

    clip_image016[4]

    然后我们尝试再次编译a.c。发现没有了错误提示:

    clip_image017[4]

    我们加载进debug,找到程序的main函数和f函数的代码:

    clip_image018[4]

    我们看到main函数中只有一句调用的call指令,根据我们代码的对比,我们知道这里调用的就是f函数。我们查看f函数的代码:

    clip_image019[4]

    我们运行:发现其实a.c调用的f()函数就是4_1.c中的f函数。

    clip_image021[4]

    回顾我们整个过程,我们可以得出这样的结论,虽然我们没有写函数f,但是a.exe中函数f的代码在连接的过程中从cs.lib中得到。

    4.将下面的程序编译为f.obj,将f.obj加入c:ccs.lib。

    程序f.c如下:

    clip_image022[4]

    clip_image024[4]

    下面的程序编译连接为b.exe。

    clip_image025[4]

    我们编译完成后进入debug查看。主函数中代码如下:

    clip_image026[4]

    clip_image027[4]

    看到,在函数调用的部分,都采用了call的方式,并且call的位置离主函数的比较远。也就是说,call部分的函数没有和main连续。我们转跳到其调用的部分。查看其代码。

    clip_image028[4]

    clip_image029[4]

    我们对应f.c查看,我们可以看到,其实这三个子程序就是f1,f2,f3函数实现的语句。并且,虽然在b中没有调用f3,f3的代码也在b中。

    很明显,经过修改cs.lib,我们的程序可以调用f1,f2,这就说明了,b.exe中的代码是在连接的时候从cs.lib中加入的。

    那么,是因为这三个函数在同一个文件中被加入cs.lib中,所以才出现这样同时都被加载进入的结果么?

    我们把f3单独拿出来,加入cs.lib(在此过程中,把cs.lib还原成tc2.0自带的cs.lib)

    clip_image030[4]clip_image031[4]

    这时我们在编译连接b.c,然后进入debug加载:

    clip_image032[4]

    clip_image033[4]

    我们看到,这里没有了f3。那么是不是被放在了其他地方呢?我们看看调用f3的时候它应该再什么地方。

    我们修改一下b.c,使他调用一下f3。

    进入debug加载查看。

    clip_image034[4]

    clip_image035[4]

    clip_image036[4]

    我们看到,f3实现的子函数就在f1,f2的后面。也就是有如下事实:如果f3被调用,那么他的地址就是在f2后面。如果f2后面没有f3,也就是f3没有被调用。这样,就否定了f3在被放在了其他地方的推论。也进而说明了,分别编译,分别加入cs.lib这个方案是可以实现用到哪个函数,装入哪个函数的代码的。

    5.替换printf

    用TLIB.EXE将cs.lib中的printf函数代码变为下面程序的代码:

    clip_image037[4]

    通过前面的几个程序我们知道,cs.lib中也有printf函数对应的代码。那么我们就不能像前面的几个程序那样添加.obj进入cs.lib中了。而应该是替换。我们看TLIB.EXE的参数表,发现-+是替换的。我们尝试:

    clip_image038[4]

    发现无错误提示。我们编写一个程序如下,测试printf是否被替换成功:

    clip_image039[4]

    编译连接后执行:

    clip_image040[4]

    这里证实,printf确实被替换成了我们自己编写的printf。

    6.思考:

    TCC这样做有什么好处呢?首先我们知道,在cs.lib中包含常用的一部分函数,可以使得TCC在编译基本功能的程序时,不需要在包含头文件。其次,我们知道,一般情况下,同一个文件中的函数之间一般是相互关联的。有些是相互调用实现一个共同的功能,有些是实现不同的功能但是是对同一类数据操作的。这些函数写在同一个文件中,包含的时候同时包含进去,这样就减少了由于没有包含而出现错误的情况。另外,可以自定义的替换其中的函数,保证了程序的多样性和能够方便的修改的特性。

  • 相关阅读:
    php文件下载方法收藏(附js下载技巧)
    微信自定义菜单类简单开发样例
    支付宝即时到账以及扫码支付相关注意事项
    ob系列函数归纳
    去除博客园底部图片广告的CSS代码
    TortoiseGit自动记住用户名密码的方法
    推荐分享一个牛X的自定义PHP加密解密类
    自动判断PC端、手机端跳往不同的域名JS实现代码
    unity 中 Tilemap的使用 笔记
    unity 判断平台(安卓,iOS还是编辑器)
  • 原文地址:https://www.cnblogs.com/shandianlongxiao/p/4133633.html
Copyright © 2011-2022 走看看