如何把VC代码优化

如何把VC代码优化,第1张

人们都说vc做出的东西可以小点,现在你打开vc编译一个Hello World出来!点属性看

下,咦!我没走眼吧,就一Hello World就160kb真是要人命啊!

呵呵!上面的情况是笔者所遭遇的情况.不过后来了解vc可以通过设置参数来自定义

编译方式.为什么文件那么大!主要是编译器加入了很多没必要的代码(这里是对我们

而言,不过有些代码还是有利于安全的).好了我们就手动改下编译器的参数来看看能

到多大!

我们主要用到的技巧有:

一,使用release版而不用debug版编译

使用debug版编译会生成许多垃圾信息.我们先使用默认的设置进行一下编译.可以看

到编译后生成的文件有152k之巨.使用release版编译具体方法是:在"build(编译)-

-->Configuration(配置)"中将"Win32 debug"移去,然后再次编译可以发现文件已经

小了很多,才24k.但离我们的目标还很远呢.

二,设置自己的入口点函数

C或C++程序默认的入口函数是main()或WinMain(),但我们现在不用什么

Main,WinMain.因为这些都不是直接的入口点,编译器在产生exe文件的时候,将为我

们生成真正的入口点.下面我们来定义自己的入口函数,具体是把main或WinMain改成

其它的名字(如MyFun),打开"Project(工程)--->settings(设置)"选项,选中"link"

选项卡,在"Category(分类)"下拉列表中选"output",在" Entry-Point symbol(输入

项-点符号)"中输入我们刚才定义的入口函数(MyFun),在源程序中也要做相应修改,

然后再编译.现在是16k了:)

三,更改编译对齐方式

通常VC在编译的时候,采用的对齐方式是0x1000,即4096bytes,我们现在将他改成

0x200,即512bytes.

在刚才打开的"link"选项卡,在下面的"Project options(工程选项)"中添

加:/align:512(还可以将512设

置的更小如16,32.....).注意两个参数之间有个空格. 3k了^_^用32试试 1.84k好

~~~用16 1.79k天哪!

再把程序的数据段和代码段放在一起,添加:/merge.data=.text

/merge:.rdata=.text 1.76k go on!

另外,如果要是用到MFC函数的程序,可在"Project(工程)--->settings(设置)"里面

的"通用(General)"选项卡中在"Microsoft Foundation Classes"中选择使用一个

MFC的dll(Use MFC in a Share Dll)也会使文件大小缩小很多.现在我们的超小后门

编译好了,试下能用否. ok 没问题哦

大家注意到程序运行时会产生一个cmd窗口,要让他没有就好了.这也好办.

回到VC++中,在"Project(工程)--->settings(设置)"选项,选中"link"选项卡,在下

面的"Project options(工程选项)"有/subsystem:console选项,表示程序是控制台

程序,双击运行是会有一个cmd窗口,把console改为windows就没有窗口了.:),运行

一下 没有窗口哦 但有进程 连接一下试试

ok 没问题 这样我们的超小1.76k telnet小后门就成功了 不被查杀哦 ^_^

// 编译器 cl.exe(Visual C++ 6.0)

// 没有做任何优化情况下,编译大小为:16K

// 编译优化后: 1K (用16进制编辑器把尾部的0x00去掉: 712bytes)

#include <windows.h>

#pragma comment(lib,"kernel32.lib")

// 作用: 指定节对齐为512字节

#pragma comment(linker, "/align:512")

// 作用: 合并节

// 将.data节和.rdata节合并到.text节(代码节)

#pragma comment(linker, "/merge:.data=.text")

#pragma comment(linker, "/merge:.rdata=.text")

// 作用: 指定子系统为windows (和优化无关)

// vc编译器默认是console,会有个黑糊糊的CMD窗口,不好看.用windows就好了

#pragma comment(linker, "/subsystem:windows")

// 作用: 指定入口函数

// 子系统为windows的默认入口点WinMain和console的默认入口点main,都会引入

#pragma comment(linker, "/ENTRY:main")

//int WinMain(HINSTANCE current, HINSTANCE prev, LPSTR cmdline, int

//showcmd)

// 作用: 去掉函数的栈帧代码,纯属吹毛求疵:-)

// 即函数开头的push ebp / mov ebp, esp和结尾的pop ebp / retn

__declspec(naked)

void main()

{

// 调用wmp. 这是按套路出牌的方法.

//typedef VOID (__stdcall *fnRunDllW)(HWND, HINSTANCE, LPCWSTR, DWORD)

//((fnRunDllW)GetProcAddress(LoadLibrary("msdxm.ocx"), "RunDllW"))

(0,0,0,0)

// 不按套路出牌,不压入RunDllW的函数参数,直接调用.

//GetProcAddress(LoadLibrary("msdxm.ocx"), "RunDllW")()

MessageBox(0,0,0,0)

// 注意此时的堆栈是不平衡的.

// 但是通过ExitProcess()退出自身,就不用去考虑平衡了.

ExitProcess(0)

}

cl.exe所在的文件夹里面有一个批处理叫做

VSVAR32.BAT

首先运行它一次,你就可以用cl.exe来编译你的代码了。

CL.exe 是控制 Microsoft C 和 C++ 编译器与链接器的 32 位工具。编译器产生通用对象文件格式 (COFF) 对象 (.obj) 文件。链接器产生可执行文件 (.exe) 或动态链接库文件 (DLL)。

注意,所有编译器选项都区分大小写。

若要编译但不链接,请使用 /c。

使用 NMAKE 生成输出文件。

使用 BSCMAKE 支持类浏览。

以下是一个完整的编译器选项分类列表。

优化

选项 作用

/O1 创建小代码

/O2 创建快速代码

/Oa 假设没有别名

/Ob 控制内联展开

/Od 禁用优化

/Og 使用全局优化

/Oi 生成内部函数

/Op 改善浮点数一致性

/Os 代码大小优先

/Ot 代码速度优先

/Ow 假定在函数调用中使用别名

/Ox 使用最大优化 (/Ob1gity /Gs)

/Oy 省略框架指针

代码生成

选项 作用

/clr 启用 C++ 的托管扩展并产生在公共语言运行库上运行的输出文件

/EH 指定异常处理模型

/G3 优化代码以优选 386 处理器。在 Visual C++ 5.0 中已经停用,编译器将忽略此选项

/G4 优化代码以优选 486 处理器。在 Visual C++ 5.0 中已经停用,编译器将忽略此选项

/G5 优化代码以优选 Pentium

/GB 与 /G6 等效;将 _M_IX86 的值设置为 600

/Gd 使用 __cdecl 调用约定

/Ge 激活堆栈探测

/GF

/GF 启用字符串池

/GH 调用挂钩函数 _penter

/GH 调用挂钩函数 _pexit

/GL 启用全程序优化

/Gm 启用最小重新生成

/Gr 启用运行时类型信息 (RTTI)

/Gr 使用 __fastcall 调用约定

/GS 控制堆栈探测

/GT 支持使用静态线程本地存储区分配的数据的纤程安全

/GX 启用同步异常处理

/Gy 启用函数级链接

/GZ 使用 __stdcall 调用约定

/MD 使用 MSVCRT.lib 创建多线程 DLL

/MDd 使用 MSVCRTD.lib 创建调试多线程 DLL

/ML 使用 LIBC.lib 创建单线程可执行文件

/MLd 使用 LIBCD.lib 创建调试单线程可执行文件

/MT 使用 LIBCMT.lib 创建多线程可执行文件

/MTd 使用 LIBCMTD.lib 创建调试多线程可执行文件

输出文件

选项 作用

/FA

/FA 创建列表文件

设置列表文件名

/Fd 重命名程序数据库文件

/Fe 重命名可执行文件

/Fm 创建映射文件

/Fo 创建对象文件

/Fp 指定预编译头文件名

/FR

/FR 生成浏览器文件

/Fx 将插入的代码与源文件合并

调试

选项 作用

/GS 缓冲区安全检查

/GZ 与 /RTC1 相同

/RTC 启用运行时错误检查

/Wp64 检测 64 位可移植性问题

/Yd 将完整的调试信息放在所有对象文件中

/Yl 创建调试库时插入 PCH 引用

/Z7 生成与 C 7.0 兼容的调试信息

/Zd 生成行号

/Zi 生成完整的调试信息

预处理器

选项 作用

/AI 指定在解析传递到#using 指令的文件引用时搜索的目录

/c 在预处理期间保留注释

/D 定义常数和宏

/E 将预处理器输出复制到标准输出

/EP 将预处理器输出复制到标准输出

/Fl 预处理指定的包含文件

/FU 强制使用文件名,就像它已被传递到#using 指令一样

/I 在目录中搜索包含文件

/P 将预处理器输出写入文件

/U 移除预定义宏

/U 移除所有的预定义宏

/X 忽略标准包含目录

/ZI 将调试信息包含在与“编辑并继续”兼容的程序数据库中

语言

选项 作用

/noBool 取消 C++ bool、true 和 false 关键字

/vd 取消或启用隐藏的 vtordisp 类成员

/vmb 对指向成员的指针使用最佳的基

/vmg 对指向成员的指针使用完全一般性

/vmm 声明多重继承

/vms 声明单一继承

/vmv 声明虚拟继承

/Za 禁用语言扩展

/Zc 在 /Ze 下指定标准行为

/Ze 启用语言扩展

/Zg 生成函数原型

/Zl 从 .obj 文件中移除默认库名

/Zp n 封装结构成员

/Zs 只检查语法

链接

选项 作用

/F 设置堆栈大小

/LD 创建动态链接库

/LDd 创建调试动态链接库

/link 将指定的选项传递给 LINK

/MD 使用 MSVCRT.lib 编译以创建多线程 DLL

/MDd 使用 MSVCRTD.lib 编译以创建调试多线程 DLL

/ML 使用 LIBC.lib 编译以创建单线程可执行文件

/MLd 使用 LIBCD.lib 编译以创建调试单线程可执行文件

/MT 使用 LIBCMT.lib 编译以创建多线程可执行文件

/MTd 使用 LIBCMTD.lib 编译以创建调试多线程可执行文件

预编译头

选项 作用

/Y- 忽略当前生成中的所有其他预编译头编译器选项

/Yc 创建预编译头文件

/Yd 将完整的调试信息放在所有对象文件中

/Yu 在生成期间使用预编译头文件

/YX 自动处理预编译头

杂项

选项 作用

@ 指定响应文件

/? 列出编译器选项

/c 编译但不链接

/H 限制外部(公共)名称的长度

/HELP 列出编译器选项

/J 更改默认的 char 类型

/NOLOGO 取消显示登录版权标志

/QI0f 确保 Pentium 0F 指令没有问题

/QIfdiv FDIV、FPREM、FPTAN 和 FPATAN 指令有缺陷的 Intel Pentium 微处理器的变通方法

QIfist 当需要从浮点类型转换为整型时取消 Helper 函数 _ftol 的调用

/showIncludes 在编译期间显示所有包含文件的列表

/Tc

/Tc 指定 C 源文件

/Tp

/Tp 指定 C++ 源文件

/V 设置版本字符串

/w 设置警告等级

/w 禁用所有警告

/Wall 启用所有警告,包括默认情况下禁用的警告

/WL 在从命令行编译 C++ 源代码时启用错误信息和警告消息的单行诊断

/Zm 设置编译器的内存分配限制

CL 命令行使用下列语法:

CL [option...] file... [option | file]... [lib...] [@command-file] [/link link-opt...]

下表说明CL 命令的输入项意义

option 一个或多个 CL 选项。请注意,所有选项都应用于所有指定的源文件。选项是由一个正斜杠 (/) 或一个短划线 (–) 指定的。如果某个选项带有参数,则该选项的说明指定在选项和参数之间是否允许有空格。选项名(/HELP 选项除外)区分大小写。有关更多信息,请参阅 CL 选项的顺序。

file 一个或多个源文件、.obj 文件或库的名称。CL 编译源文件并将 .obj 文件和库的名称传递给链接器。有关更多信息,请参阅 CL 文件名语法。

lib 一个或多个库名。CL 将这些名称传递给链接器。

command-file 包含多个选项和文件名的文件。有关更多信息,请参阅 CL 命令文件。

link-opt 一个或多个链接器选项。CL 将这些选项传递给链接器。

您可以指定任意数目的选项、文件名和库名,条件是命令行上的字符数不超过 1024,该限制是 *** 作系统指定的。

CL 命令文件请参见

设置编译器选项 | 编译器选项

命令文件是一个文本文件,它包含您另外在命令行上键入或使用 CL 环境变量指定的选项和文件名。CL 接受在 CL 环境变量中或命令行上用作参数的编译器命令文件。与命令行或 CL 环境变量不同,命令文件允许使用多行选项和文件名。

命令文件中的选项和文件名将根据 CL 环境变量中或命令行上的命令文件名的位置被进行处理。但是,如果 /link 选项出现在命令文件中,则该行其余部分的所有选项将被传递给链接器。命令文件的后面几行中的选项和命令行上命令文件调用之后的选项仍被作为编译器选项接受。

命令文件一定不能包含 CL 命令。每个选项必须在同一行上开始和结束;不能使用反斜杠 (\) 跨行组合一个选项。

命令文件用一个 @ 符后接一个文件名指定;该文件名可指定绝对路径或相对路径。

我用的是VC8,这个是代码优化:

属性 ->C/C++ ->Optimization ->Optimization

设成Disabled(/0d);

默认Debug版是关闭的。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/11997247.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-20
下一篇 2023-05-20

发表评论

登录后才能评论

评论列表(0条)

保存