tlink链接输出Null pointer assignment的探究

发表于:2015年1月2日 02:31  分类:c 639次浏览

tlink是turbo c 2.0中的链接器,可以将编译生成的obj文件和lib文件进行链接,生成可执行文件exe,查看tlink的使用帮助:

D:\c>tlink
Turbo Link  Version 2.0  Copyright (c) 1987, 1988 Borland International
Syntax:  TLINK objfiles, exefile, mapfile, libfiles
@xxxx indicates use response file xxxx
Options: /m = map file with publics
         /x = no map file at all
         /i = initialize all segments
         /l = include source line numbers
         /s = detailed map of segments
         /n = no default libraries
         /d = warn if duplicate symbols in libraries
         /c = lower case significant in symbols
         /3 = enable 32-bit processing
         /v = include full symbolic debug information
         /e = ignore Extended Dictionary
         /t = create COM file

编写了如下代码:

main()
{
	printf("hello world!");
}

首先,使用编译器tcc.exe编译生成obj文件:

tcc -c a.c

然后,将需要用到的库文件cs.obj、c0s.lib、maths.lib、emu.lib拷贝到同一文件夹下,用tlink.exe链接obj和需要的lib文件。

D:\c>tlink C.OBJ c0s.obj , c.exe , c.map , maths.lib emu.lib cs.lib
Turbo Link  Version 2.0  Copyright (c) 1987, 1988 Borland International

链接生成了可执行文件exe,运行结果:

D:\c>C.EXE
hello world!
Null pointer assignment

问题:
为什么会输出“Null pointer assignment”呢?

调试:
使用turbo debug加载c.exe,反汇编单步调试。
跟踪到产生“Null pointer assignment”的代码:
tlink1
前一页代码如下:
tlink2
运行到上图红框所示代码时,数据段内容:
tlink3
通过求数据段0000-002f中的字节内容之和,决定是否call 01E3,该子程序代码:
tlink4
在tlink链接生成的exe中,显然调用了上述代码。
查看8086CPU中断大全,功能号为40h的int 21h中断——向设备或文件写制定数目的字节,接收的参数——bx=文件句柄,ds:dx指向缓冲区,cx=要写的字节数,返回——如果进位标志DF设置,ax=错误代码,否则ax=写入的字节数。
在此处的具体作用是:将数据段中003f开始的19h个字节写入屏幕,并且cld清除进位标志,单步跟踪得到ax=19h,也就是“Null pointer assignemt ”。
之后,代码运行至int 21h的4ch号中断,程序结束。

分析:
为什么会输出“Null pointer assignment”呢?从上面的调试可以看到字符串“hello world!”插入到了整个数据段之前,改写了本应该是程序版本信息的位置,所以输出“Null pointer assignment”。考虑到进入程序后,最先执行c0s.obj中的代码,可能的原因是obj文件的调用顺序出错,调换c0s.obj和c.obj的顺序,正确的tlink语句顺序是:

D:\c>tlink c0s.obj C.OBJ , c.exe , c.map , maths.lib emu.lib cs.lib
Turbo Link  Version 2.0  Copyright (c) 1987, 1988 Borland International

在此运行生成的exe文件,结果正确:
tlink5

拓展:
进入程序后最先执行c0s.obj中的代码,所以c0s.obj放到最前头。tlink连接obj文件的顺序决定了代码在程序中的位置,而对于lib文件中函数的调用顺序肯定也有要求,这有待进一步探究。

发表评论

电子邮件地址不会被公开。 必填项已用*标注