大家都是VC6 研究的多,但是VC8中有些变化。我配了图文给大家说明:
我们任意新建一个WIN32程序:
自动生成的代码 ,我们用Release模式编译:
但是注意了,如果我们把这个程序拷贝到其它机器是肯定无法运行的,原因是没有VC的运行时8.0的库。要让我们的程序可以共享,我们必须静态连接:
编译以后会发现应用程序:
这当然让我们不能够容忍,一个纯WIN32应用程序,居然这么大。。。还没有用MFC呢?
怎么办呢:让我们一步一步地来,首先摆脱掉运行库。
1.取消对运行库的依赖:
改为是
编译一下:
会出现编译错误:
1>------ 已启动生成: 项目: MyEmpytWin32, 配置: Release Win32 ------
1>正在链接...
1>LINK : error LNK2001: 无法解析的外部符号__tmain
1>MyEmpytWin32.obj : error LNK2001: 无法解析的外部符号@__security_check_cookie@4
1>C:\Documents and Settings\Administrator\My Documents\Visual Studio 2005\Projects\MyEmpytWin32\Release\MyEmpytWin32.exe : fatal error LNK1120: 2 个无法解析的外部命令
1>生成时间0:00
继续编译会出现编译器错误:
1>正在链接...
1>LINK : error LNK2001: 无法解析的外部符号_mainCRTStartup
1> C:\Documents and Settings\Administrator\My Documents\Visual Studio 2005\Projects\MyEmpytWin32\Release\MyEmpytWin32.exe : fatal error LNK1120: 1 个无法解析的外部命令
设置入口点首先我们改一下代码,把默认的 Vc Runtime Main函数改动一下:
像这样子:
#include "stdafx.h"
int main()
{
return 0;
}
并设置入口点:
编译成功以后:
会发现程序小了好多。但是超小的话我们还得做一些处理:
1.合并区段
察看区段
添加下面的命令行(!VC8不允许将资源区段合并到任何区段!)
1>已完成代码的生成
1>LINK : warning LNK4254: 节“.data”(C0000040)合并到具有不同属性的“.text”(60000020)
1> 正在嵌入清单...
出现警告,我们不必理会!
已经比较小了,不过用OD打开看1000字节对齐还浪费了不少字节!
打开MSDN找到对齐的相关帮助:
/ALIGN[:number]
其中: number 对齐
我们这里设置为1024(小于将无法被windows加载器加载,,)
!下面我们来打造小于512字节的超小应用程序!
去除调试信息:
去除清单文件
现在在编译器一下:

怎么样?满意了吧。我们为了让我这个程序有点实际意义:
去掉默认的Unicode支持 毕竟Unicode是16 bits一个字符,不合算:)
#include "stdafx.h"
#include <windows.h>
int main()
{
MessageBox(NULL,"Hello World~\n This is a smallest app","你好",MB_ICONINFORMATION);
return 0;
}
代码像这样

大小和运行时截图唯一的遗憾就是.text节里面还剩余字节但是却超过了512字节:(。。
下一篇文章我将介绍更有实用价值的,毕竟VC的运行库在很多地方还是很方便的,而且如果不使用 Runtime就无法进行浮点运算。。这在写注册机之类的操作当然不允许的。
继续我们的话题-VC8中打造超小应用程序。
上次说到了如何摆脱Runtime
但是又遇到了新问题,关于浮点计算的问题,而且里面的一些库函数不用也太可惜了
这里有一种变通方法:
我们知道 VC6的库是自带的,,不过我们又不想用VC6的IDE和编译器。毕竟比起VC8来说还是相差两个版本。但是由于在VC8中浮点到整数型的类型转换是由SSE2指令,换句话来说默认的编译器是无法通过编译器的,如果我们使用VC6的库,因为缺少一个函数!
具体的我们下面再说,在这之前,我们要做几个准备工作。
1. 准备VC6的 Runtime动态链接库的LIB文件。
2. 准备INTER FOR VS2005编译器。这个要花些时间,去下载一个精简版吧。
先新建一个项目,然后在属性里面选择忽略所有默认库。我以前说过如果设置,这里就不说了。
接下来,关键:

并设置

然后我们就可以开始编译了
随便输入一个函数吧
int main(int argc, _TCHAR* argv[])
{
printf("i Love You! PeDiy");
return 0;
}
很显然程序成功执行了
我们看一下汇编代码吧还是。
不错,用的是自带的动态链接库,但是确实是VC8的编译器的代码。
好了,下面来说说浮点运算:
我们为了避免用效率低下的MSVCRT也就是说我们想用VC8的SSE2优化。我们只得这样子办!
但是编译代码显然会出错:
1>DDKTest.obj : error LNK2001: 无法解析的外部符号___libm_sse2_sin
1> C:\Documents and Settings\Administrator\My Documents\Visual Studio 2005\Projects\DDKTest\Release\DDKTest.exe : fatal error LNK1120: 1 个无法解析的外部命令
2> 另外进行类型转换也是会出错的!
好了,这就是我为什么要大家下载INTER编译器的原因。
我们都知道它编译的代码很强悍。而且重要的是本身这个编译器就可以工作在VC6~8所有版本里面,当然就可以通过这个要绕过我们非常麻烦的问题,从而做到体积和速度的平衡点。
这里注意一下:其实还有一种解决方案,就是通过对比VC6和VC8的exports的不同,手动创建所需要的代码,不过工作量稍微大了一点,我有时间我会写一个库的。。。
我们切换到Inter编译器状态
进入属性
我们要更改一下,首先不能够忽略所有的默认库,会把我们的INTER库也给忽略的,
另外添加特定的也就是我们的静态库VC8Runtime忽略/
在编译一下。成功了。我们反汇编看看代码吧。/
程序大小为3.5KB。如果合并一下区段的话会比较小的1.62 KB (1,664 字节)
而且所有的函数都基本上没有问题
int main(int argc, _TCHAR* argv[])
{
printf("i Love You! PeDiy\n");
double a;
int b;
a=1.1;
a=sin(a);
b=int(a);
printf("运算结果为%f 整数为%d",a,b);
system("PAUSE");
return 0;
}
成功编译,解决了在VC8的编译器上无法编译的问题。
顺利实现在VC8的IDE上面做到控制体积的。至此基本完美完成了我们打造超小应用程序 IN VC8的任务。
当然了 唯一的遗憾就是如果INTER编译器打开SSE3优化的话会使得体积增加16KB。
当然了基本任务已经完成了。现在给你一个程序,很有可能你不知道到底是哪个编译器编译的。毕竟使用了VC6的RUNTIME。