(4)用tcc hello.c生成的文件可有两个段,一个为代码段,一个为栈和数据段。所以子函数和主函数都要在同一个代码段里。那么如果代码量超过64kb,一个段存放不下,怎么办?
答:那应该使用别的内存编译模式,TC下默认的模式是小模式,只支持64kb以下的代码和数据,若代码和数据超过64kb,可以使用大模式或者巨模式。
3、研讨会解决的问题
(1)如果缺少相关文件,tcc.exe会调用tlink.exe吗?生成的obj文件是含有其他相关文件吗?
答:根据讨论,如果缺少相关文件,tcc.exe调用了tlink.exe但是无法找到文件,需要再用tlink.exe来连接obj文件,生成exe文件。如果缺少相关文件,tlink会连接其他相关文件。经过实验,如果缺少maths.lib,程序能够输出helloworld,而如果缺少c0s.obj或者cs.lib编译成的exe文件就会运行出错,这是因为maths.lib是运算相关的库,如果程序里没有运算的话,即使缺少也不影响程序的执行,而c0s.obj或者cs.lib是程序启动运行所需要的文件,所以一旦缺少就会出错。
修改:经过再次的实验,我发现缺少maths.lib文件,编译连接生成的exe文件也会显示出错,这说明之前的结论是不成立的。tcc.exe的功能是把c源文件编译成二进制obj文件,再调用tlink.exe进行连接生成exe文件。即只要执行一条命令就能把c源文件编译连接成可执行的exe文件。我们没有改变tcc.exe文件的内容,那么tcc还是会调用tlink,只是因为相关文件不全而出错导致tlink没有正确执行连接而已。实验发现先用tcc -c hello.c或者tcc -linclude hello.c将源文件编译成obj文件,再连接成exe文件还是执行出错,在网上有资料说这样编译连接会导致返回错误,但没有说明具体原因。我觉得可能单独用tlink连接hello.obj会在调用相关文件上出错,就是说tlink没有调用相关文件的能力,只是tcc调用它的时候告诉它应该按什么顺序来连接,它才能正常连接。但是这个猜想和上面的问题一样,我暂时还找不到方法和资料来验证,希望学长能在衍生课上讲一讲,具体的问题是这样的:
如果缺少相关文件,生成的obj文件是含有其他相关文件吗?为什么一定要tcc.exe调用tlink.exe才能生成正确的可执行文件?
(2)为何在原来的平台上即使没有tcc和tlink也能够编译链接成功。
答:TC2.0集成有多种编译器,c语言和汇编语言是可以混合编译的。如果出现汇编语言,那么TC2.0就会调用tcc.exe来进行编译。Turbo c包有两种编译器,集成开发环境下的叫做TC.EXE和命令行方式的叫做TCC.EXE. 集成开发环境包括:集成编辑器、命令行编译器、连接器、调试器。
(3)库文件是怎么搜索的?
答:在turboc.CFG中可以指定tcc可以用来搜索的库文件的位置。但是用TC2.0修改路径不会保存在turboc.CFG中,而是生成另一个配置文件。
(4)三种模式,是否可以互相的替换
答:其实c语言编译有6种模式,这6种模式编译的结果都是一样的,只是支持的数据大小和程序大小不一样。
(5)为何打印出来的段地址的值和用debug调试的时候出来的地址的值是不一样的?
答:编译时给定了偏移地址,载入时cmd或者debug再给定段地址,所以段地址不一样。
(6)假如代码量超过了64K后,会如何?
答:那么就不能用默认的内存编译模式(小模式)来编译,会出错。应该用支持大程序的模式来编译(如中模式、大模式、巨模式)。编译器会把代码分成几个不超过64kb的程序来编译。
(7)为什么打印出来的偏移地址改变,在平常的时候main函数的偏移地址是1fa但是此时的main函数的偏移地址不是这样的了?
答:主函数的偏移地址不一定是1fa,而是第一个程序的偏移地址是1fa。之后函数的偏移地址按程序的长度发生变化。其实原理和汇编语言里不同段的地址不同是一样的。C0s.Obj里的函数加载完后正好到了1fa处应该加载源文件的内容了,这时那个函数在第一个就把哪个函数放在1fa处。
(8)如何用一条语句打印出段地址和偏移地址。
答:可以用printf(“%lx”,main);打印出段地址和偏移地址。
4、学习感想