龙空技术网

masm32开发包与VC6.0之间存在的Bug的体现及解决办法

看雪学苑 161

前言:

现在看官们对“vc6存在兼容问题”都比较注意,姐妹们都需要了解一些“vc6存在兼容问题”的相关资讯。那么小编在网上收集了一些关于“vc6存在兼容问题””的相关知识,希望姐妹们能喜欢,看官们快快来学习一下吧!

概览:本文做了个Demo测试小程序来体现masm32开发包的库与VC6.0存在的一些不兼容的问题,如下即为所描述的问题及列举的对应的解决办法:

1、在RadASM环境下连接VC6.0生成的.obj时,找不到_main符号的问题及解决办法。

2、VC6.0对GetEnvironmentStrings这个函数的ASCII版本和UNICODE版本的宏替换与masm32的不一致的问题及解决办法。

一、Bug的触发:

创建VC6.0工程,声明和定义ShowHello()函数,然后编译生成.obj目标文件:

创建RadASM控制台工程。由于VC6.0编译好的代码都会被生成在.obj里面,所以就能在RadASM工程直接调用.obj里面的函数。将编译好的StdAfx.obj扔到RadASM工程文件夹下,并添加到RadASM工程里面。然后就可以调用了,以下就是调用ShowHell()这个函数。

编译可通过,但是连接的时候报了两个错误:

二、错误一:

提示缺少_main符号,为什么会缺少_main符号?是因为在VC6.0生成的.obj会把LIBCD.LIB一块连接进去(LIBCD.LIB在VC6.0安装目录的VC98下的LIB文件夹里面)。在 LIBCD.LIB中有一个crt0.obj,这个crt0.obj就是VC6的入口代码,我们用IDA打开LIBCD.LIB查看:

双击这个crt0.obj进去后发现,就会看到的即是VC6.0的入口代码:

入口代码做完一些初始化工作后,就调用了main函数

由于连接了LIBCD.LIB,而LIBCD.LIB又有入口函数被连接,而拷贝到RadASM工程下的StdAfx.obj并没有入口函数的定义,于是就报错第一个错误:缺少_main符号。

解决办法一:将RadASM的程序入口改为main:

再连接,第一个错误解决了!

解决办法二:直接定一个的空函数,使RadASM连接时能检测到_main符号:

这个方法同样可以解决第一个错误!

三、错误二:

缺少一个函数定义:__imp__GetEnvironmentStrings

首先,在VC6.0下我们看看GetEnvironmentStrings这个函数在何时被调用。通过栈回溯定位到VC的mainCRTStartup,然后往下就会看到:是mainCRTStartup调用了这个函数:

关键点:在RadASM连接时会报错,是由于识别不出.obj下的这个函数,即masm32对这个声明的与VC6.0声明的不一致。

问题的体现:

1、我们先看masm32对ASCII与UNICODE版本的实现。打开masm32的include目录,找到kernel32.inc

打开并定位到GetEnvironmentStrings这个函数:

masm32调用该函数时如果是ASCII版,则用GetEnvironmentStringsA宏替换,如果是UNICODE版,则用GetEnvironmentStringsW宏替换。

2、再看微软对ASCII版本与UNICODE版本的实现,首先我们以举MessageBox为例子:

但是很不幸的是GetEnvironmentStrings这个函数并不这样子:

这时就发现了,后缀带A的GetEnvironmentStringsA的是ASCII版本,而带W的GetEnvironmentStringsW是UNICODE版。也就是说带GetEnvironmentStringsA的是宏,而GetEnvironmentStrings才是函数。

通过对比发现,问题很明显的体现了,masm32与微软VC6.0对此函数的声明不一致,才会导致上面说的RadASM连接此函数时报的那个错误!!

解决办法一:先修改masm32处的声明:

修改完保存,但是此时连接依然是不会过的,因为.lib已经打包了kernel32.inc。简洁的解决办法,可直接拿VC6.0下的.lib直接覆盖masm32下的这个.lib,这是一种解决办法。我们就试着将它拷到masm32的.lib目录下:

然后,在RadASM工程下再次连接:

这样连接就过了。但此时程序依然不能运行,由于我们给RadASM提供的.obj是VC环境下编译的.obj,所以对应的入口函数也应改为mainCRTStartup,即:

此处,再编译、连接、运行,即可看正常运行。

解决办法二:除上面提供的方法外,还有另外的解决办法:将修改后的kernel32.inc重新生成.lib文件替换原来的.lib。我们使用masm32提供的工具inc2l来重新生成kernel32.lib。这个工具在masm32的tool目录下:

将我们修改过的kernel32.inc拷贝进来:

打开命令行,并编译生成kernel32.lib:

将重新生成的kernel32.lib拷贝到masm32目录下的lib文件夹覆盖旧的kernel32.lib:

到了这一步,就算大功告成了。将RadASM再做连接,编译通过了!

运行看到效果:

到此,RadASM连接VC6.0时的两个报错都解决了。

四、尾声:

此博文是在科锐学习期间的日常笔记,心血来潮就发表了此帖子,对此有遗落的地方望各位大佬指出供小弟加以改正。最后感谢看雪提供的平台使大家有相互学习的机会!

本文由看雪论坛 小钟 原创 转载请注明来自看雪社区

标签: #vc6存在兼容问题