采用了一个最简单的例子,孙鑫《深入浅出MFC》的第一个窗口例子
采用obj2asm把WinMain.obj反编译为WinMain.asm,格式大致如下
.686p .mmx .model flat option casemap :none public _WinMain@16 ...... extrn __imp__DispatchMessageA@4 :near ...... extrn __imp__MessageBoxA@16 :near _TEXT SEGMENT ASSUME FS:FLAT _WinMain@16: push ebp ...... _TEXT ENDS .....毕业论文 .
makefile文件
WinMain.exe: WinMain.obj Link /SUBSYSTEM:windows /nologo WinMain.obj user32.lib gdi32.lib WinMain.obj: WinMain.asm .asm.obj: Ml /c /coff $<
执行nmake命令后出现错误:
LINK : error LNK2001: unresolved external symbol _WinMainCRTStartup
WinMain.exe : fatal error LNK1120: 17 unresolved externals
如果把asm中的_WinMain@16改为_WinMainCRTStartup就可以正常链接出exe,这里默认的入口函数为什么是_WinMainCRTStartup?在哪里指定的?
高级语言的程序入口是定义在公共模块里的吧,程序自己的 main() 类函数只是被它调用而已。看看 obj2asm 生成的文件,最后的 end 语句后应该没有指定入口的。而且,生成的文件里应该有对 _WinMainCRTStartup 的说明,否则以上面的内容和连接涉及到的文件,是不应该蹦出来这个“未定义标号”的,而应该是程序入口未指定之类。_WinMainCRTStartup是默认的程序入口点, C语言运行时库. 可以自己指定程序入口点的.
_WinMainCRTStartup是VC中编译进去调用WinMain函数的代码。用来初始化一些东西,以及处理命令行参数,然后才进入WinMain,程序里面的一些C库函数才能正常运行。(CRT = C runtime initialization routine)
_WinMainCRTStartup的代码应该在LIBC.lib、或LIBC???.lib(名字不同表示单线程的、多线程的、debug版本的等等)中,VC安装环境如果安装了CRT源代码,可找相关代码看看。vc6里面的是CRT0.C, CRTDLL.C,CRTEXE.C,DLLCRT0.C等,不同的工程编不同的启动代码。
如果你的WinMain.asm里面,没有调用什么c库函数代码,你将入口指向_WinMain@16(_WinMain@16改为_WinMainCRTStartup)程序或许可以执行,但退出可能会有异常之类的——_WinMain@16和_WinMainCRTStartup参数个数不一样,你也许可把_WinMain@16参数去掉,返回的RET XX指令改为RET指令解决。
如果你的WinMain.asm里面,调用了一些c库函数代码,最好把LIBC.lib或者LIBC???.lib加进来。不要修改入口指向。