linux打开obj文件怎么打开,obj文件的连接问题以及tlib的基本用法

1、基础研究

69629984bd592ba0f4fbd4bc1345c0c5.png

用tcc将程序编译为.obj文件。

6030c5443d343b66ce93e4cffe91be8b.png

93818702485b7e95663679b8dc2a8305.png

这里也可以使用tcc -linclude run.c来将run.c文件编译成run.obj文件。

再用tcc对下面的程序进行编译链接,发现提示错误:

af6f6884d311560b82873902865b1b2a.png

4f3aed3099fee1acdbde217399f354e9.png

提示标志f在程序中未定义。这说明如果程序里出现未定义的变量或函数,编译器能够正常将原文件编译成.obj文件,只是会提示而已。

要怎么生成正确的exe文件呢,我们要把run1.c中未定义的f函数链接进来,但是我们之前的链接都是链接的系统提供的相关文件,怎么链接自带文件呢?我们先研究一下tlib.exe。

tlib.exe使用方法如下;

d8c4a6141b0ee5c5ac9bd0de026f2208.png

即使用tlib的格式为tlib libname [/C] [/E] commands, listfile

libname:要建立的用户目标模块库,缺省的扩展名为.LIB

/C:大小写敏感标志。该选项不常用。

/E:建立扩展字典。建立扩展字典可以加速大的库文件的连接过程。

commands: 操作列表,由若干个动作符以及每个动作符后面的文件名或模块名组成。TILB支持的动作符有5种:“+"、“-"、“*"、“-*"或“*-"、“-+"或“+-"。“+"是把指定的文件加到指定的库中; “-"从库中删除指定的模块;“*"将相应的模块从库中抽取并写到指定的文件中,原库不变;“-*"或“*-"是将库中指定的模块拷贝到指定的文件中,然后把该模块从库中删除;“-+"或“+-"是将指定的模块用指定的文件或模块代替。

Listfile:建立列表文件。列表文件按字母顺序将库中各模块列表,为文本文件,可用DOS的TYPE命令查看。

那么将含有f函数的run.obj添加到cs.lib里的语句如下:

86e7a5fa4f927da283f039af9371d687.png

之后用tcc编译链接文件run1.c,没有出现错误提示。用debug加载生成的exe文件:

ecb377b18417a6f742095657e43fc0ea.png这是main函数的代码

d2ce22c40522644240e2c0af61a082f4.png这是f函数的代码

所以,我们将函数f写在程序run.c中,编译成run.obj,再将run.obj用tlib链接入cs.lib,这样tcc编译时发现原文件中没有定义函数f,就会在c语言默认的函数库cs.lib中寻找,找到后将其链接,生成run1.exe文件,所以我们在run1.exe文件中可以看到函数f的代码,它是在tlink连接时加入的。

用tlib cs.lib cs.txt可以在cs.txt或者cs.lst文件中导入cs.lib的函数的目录。

85fc756a5f7071fae69123e2672975ad.png

将此程序编译成f.obj,并加入cs.lib中。

bcaaa6facd178157bca503d0a3981ea9.png

8dd8502940672a819747bbbf99f8c9fd.png

将上面的程序编译链接成b.exe,用debug加载:

Main函数的内容为:

23d435f41da024480796eaf8a797cdab.png

73cc87dce7426b8a621cec107379f3eb.png

f1函数的内容为:

e81e3bf3168a50c30ff6af61e81322c7.png

f2函数的内容为:

c80a0929117844920f692e41f3aed2a2.png

函数func的内容为;

260a43d65276efa66ff68371d5c17186.png

程序b.c中并没有写f1、f2和printf函数,这些函数的代码同样是在连接的时候加入的。

b.exe中有f3的代码,因为f3和f1、f2一起被加入了cs.lib中,而cs.lib被连接入了b.exe,所以b.exe含有它的全部函数,只是main函数中只调用了f1、f2、printf函数而已。

ae1df9f3eb1d2b41f6f2935e801083fe.png

函数f3的代码紧接着函数f2的代码,地址为1056.

那么有没有一种方案,使得在编译连接时能够动态地装入函数的代码,而不是将库函数全部装入exe文件呢?

我们看题目要求的是f.c中的三个函数要装入cs.lib,在编译连接时动态载入代码。但是如果我们用tcc原来的连接方式,就会把cs.lib整个载入代码中。那应该怎么样才不会出现这种情况呢?我觉得应该是改变tlink的连接方式,查看tlink连接选项:

94e38c309078870cdc448f1d5579e63a.png

我用tcc将b.c编译成obj文件,再用tlink b.obj/n进行连接,结果出现如下错误:

13f4fd476742a94a1b8674e186f1e9cf.png

很显然是没有连接cs.lib所致,但是为什么先用tcc编译再用tlink连接会出错呢?

经过查找资料和实验,tlink连接obj文件生成exe文件的正确指令如下:

34343258bbd7b76908d68974e0936184.png

第一个意思是用小模式连接b.obj,第二个是指生成的目标文件是b.exe,第三个是指没有使用到映像文件,第四个是指连接需要用到的库文件有cs.lib、emu.lib、maths.lib。

函数f3包含在f.obj里,而后者被载入了cs.lib文件,cs.lib在连接时被载入b.exe文件,那么是不是cs.lib里的所有函数都载入了b.exe文件呢?查找资料有这么一段话:

不会。当启动连接程序时,它会寻找“未定义的外部函数”,也就是说,它将在每一个库文件中查找源代码文件中未定义的函数。当它找到一个未定义的外部函数后,它会引入包含该函数定义的目标代码(obj)。不幸的是,如果这个函数是在一个包含其它函数定义的源文件中被编译的话,那么这些函数也会被包含进来,你的可执行代码中将包含一些不需要的代码。因此,将库函数放到各自的源文件中是很重要的——否则会浪费宝贵的程序空间。有些编译程序包含特殊的“精明的”连接程序,这些连接程序能查出不需要的函数并去掉它们,从而使这些函数不再进入你的程序。

很显然tlink并不是上面资料里所说的“精明的”连接程序,它会将和源代码中未定义函数一起编译的所有函数都载入exe文件中,所以f3会被载入b.exe中。

那么我们的问题就很好解决了,我们可以将f1、f2函数写在一个程序里编译成obj文件,将f3写在一个程序里编译成obj文件,再将这两个文件加入cs.lib中,然后进行下面的连接,b.exe文件中就不会出现f3函数的代码了。实验结果发现,原来紧跟在f2的代码后面的f3的代码现在没有了:

6cdd3a47561180797adb170b5e9fa0f5.png

所以其实是我之前的思路重点错了,只觉得函数f1、f2、f3都在cs.lib里面不管怎么放都是一样的,但是其实它们编译的方法不同,在cs.lib里面存放的位置或机制也应该不同,我们思考时,应该更加全面地想问题。

用下面的函数替换cs.lib里的printf函数:

47656548f5ffa0de59ada9b1fe4cf24e.png

将函数编译成obj文件,再用如下语句替换:

31286dfb39c57fae2e0ccaab877a5885.png

这样再使用printf函数就会输出“Do you want to use printf?No printf here.”

如下图程序:

cc0ac40c4b7ed88622e42375f470c048.png

在正常情况下应该输出3,但是用更改后的cs.lib连接后,输出结果如下:

e0b27307d22e85f1245ab9fa22cb4712.png

这时printf函数是一个不接受参数、只输出固定语句的函数。

2、拓展研究

1、我们在本章研究里是把要添加的obj文件插入cs.lib中再连接,那么能否自己建立lib库,并使tcc编译时对它进行连接呢?

2、我们知道cs.lib里在被连接时是将源文件中未被定义的函数及其一起编译的函数全部加入生成的exe文件中,那么cs.lib里的其他文件是怎么编译的?都是单独编译的吗?

3、Printf和put函数有什么区别?

4、obj文件给出的是偏移地址,exe文件给出了段地址和偏移地址?

5、include头文件在预编译过程中把其他文件合成一个文件。尝试#include也是可以正确运行的,看汇编代码这种和加入cs.lib有什么不一样。

6、加入obj文件后之后cs.lib的大小减小了,这是为什么?

3、研究总结

本章研究了obj文件的连接问题,掌握了将obj文件加入cs.lib从而连接进文件的方法,熟悉了tlib.exe的基本用法。

0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值