首页
社区
课程
招聘
VC编译出来的程序为什么那么大啊?
2006-5-29 19:17 14219

VC编译出来的程序为什么那么大啊?

2006-5-29 19:17
14219
一个超简单的VC程序:
#include <windows.h>
void main()
{
        char* text="my first window";
        char* caption="good";
        MessageBox(NULL,text,caption,0);
}
编译后的可执行文件竟然有138K,我想如果用汇编实现,最多就3到4K,一下子大了这么多,这是为什么啊?各位大虾能告诉我吗?

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞7
打赏
分享
最新回复 (29)
雪    币: 2367
活跃值: (756)
能力值: (RANK:410 )
在线值:
发帖
回帖
粉丝
小虾 10 2006-5-29 19:19
2
0
这是因为VC还自动加入了启动代码。不过也有解决的方法。下面的链接:
http://bbs.pediy.com/showthread.php?s=&threadid=19823
雪    币: 191
活跃值: (55)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
chenzping 2 2006-5-29 19:35
3
0
不错,不错。
先谢谢我们热心的版主啦。
雪    币: 217
活跃值: (99)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
dwing 1 2006-5-29 19:59
4
0
最初由 chenzping 发布
一个超简单的VC程序:
#include <windows.h>
void main()
{
char* text="my first window";
char* caption="good";
MessageBox(NULL,text,caption,0);
}
编译后的可执行文件竟然有138K,我想如果用汇编实现,最多就3到4K,一下子大了这么多,这是为什么啊?各位大虾能告诉我吗?


估计你刚刚才认识VC吧,至少也应该知道debug和release的区别...
如果你需要,我可以让上面的程序用VC编译成1KB的可执行文件.
雪    币: 191
活跃值: (55)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
chenzping 2 2006-5-30 08:46
5
0
真的可以吗,楼上的大哥告诉我下怎么编译好吗? 先谢谢啦。
雪    币: 211
活跃值: (40)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
17521 1 2006-5-30 09:03
6
0
我也想知道怎么编译
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dzzz 2006-5-30 11:46
7
0
最初由 dwing 发布
估计你刚刚才认识VC吧,至少也应该知道debug和release的区别...
如果你需要,我可以让上面的程序用VC编译成1KB的可执行文件.


期待大虾指点
雪    币: 235
活跃值: (100)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
lemony 1 2006-5-30 14:54
8
0
过度优化可能最终导致程序无法运行~~~

没有必要啦,VC编译会嵌入很多自己的东西,也包括一些对程序的优化~~

如果只是想要写出小的程序,那就用asm吧
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
chinawash 2006-5-30 16:09
9
0
是可以的,甚至会小于1KB,记得论坛里好象有过,记不清楚了,惭愧!
雪    币: 211
活跃值: (40)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
17521 1 2006-5-30 21:24
10
0
扎还没有人出来介绍一下优化的详细方法呢
雪    币: 236
活跃值: (326)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
gzgzlxg 11 2006-5-30 23:27
11
0
VC实际就是垃圾代码生成器,你如果不信我的话,可以随便写几句编译,然后用ida分析,就一目了然了。4楼所说得其实就是将编译条件设置到发行,加上优化,去掉VC++的那些库,得出的结果就是1k一下,但是就是这个1k一下,还是垃圾代码,你所写的那段代码最小可以做到连PE文件头在内200个字节自己左右,但你必须会自己修改pe文件头,4楼的方法中也必须设置link的参数,其中/ALIGN:xx 必须在0x40一下(这个数是2 的倍数)。
雪    币: 191
活跃值: (55)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
chenzping 2 2006-5-31 16:10
12
0
谁能详细解释一下吗?
雪    币: 217
活跃值: (99)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
dwing 1 2006-5-31 18:35
13
0
最初由 gzgzlxg 发布
VC实际就是垃圾代码生成器,你如果不信我的话,可以随便写几句编译,然后用ida分析,就一目了然了。4楼所说得其实就是将编译条件设置到发行,加上优化,去掉VC++的那些库,得出的结果就是1k一下,但是就是这个1k一下,还是垃圾代码,你所写的那段代码最小可以做到连PE文件头在内200个字节自己左右,但你必须会自己修改pe文件头,4楼的方法中也必须设置link的参数,其中/ALIGN:xx 必须在0x40一下(这个数是2 的倍数)。

// Release方式编译,结果是1KB的可执行程序
#pragma comment(linker,"/MERGE:.data=.text")
#pragma comment(linker,"/MERGE:.rdata=.text")
#pragma comment(linker,"/ENTRY:main")
#pragma comment(linker,"/OPT:NOWIN98")
#include <windows.h>
int main()
{
	char *text="my first window";
	char *caption="good";
	MessageBox(0,text,caption,0);
	return 0;
}

0040101E >/$  6A 00           push    0                        ; /Style = MB_OK|MB_APPLMODAL
00401020  |.  68 18104000     push    00401018                 ; |Title = "good"
00401025  |.  68 08104000     push    00401008                 ; |Text = "my first window"
0040102A  |.  6A 00           push    0                        ; |hOwner = NULL
0040102C  |.  FF15 00104000   call    [<&USER32.MessageBoxA>]  ; \MessageBoxA
00401032  |.  33C0            xor     eax,eax
00401034  \.  C3              retn

00000000h: 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00
00000010h: B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00
00000020h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000030h: 00 00 00 00 00 00 00 00 00 00 00 00 C8 00 00 00
00000040h: 0E 1F BA 0E 00 B4 09 CD 21 B8 01 4C CD 21 54 68
00000050h: 69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F
00000060h: 74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20
00000070h: 6D 6F 64 65 2E 0D 0D 0A 24 00 00 00 00 00 00 00
00000080h: 9D 14 24 DA D9 75 4A 89 D9 75 4A 89 D9 75 4A 89
00000090h: D9 75 4B 89 D8 75 4A 89 BB 6A 59 89 DA 75 4A 89
000000a0h: 8D 56 7A 89 D8 75 4A 89 52 69 63 68 D9 75 4A 89
000000b0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000000c0h: 00 00 00 00 00 00 00 00 50 45 00 00 4C 01 01 00
000000d0h: 3C E3 7A 44 00 00 00 00 00 00 00 00 E0 00 0F 01
000000e0h: 0B 01 06 00 00 02 00 00 00 00 00 00 00 00 00 00
000000f0h: 1E 10 00 00 00 10 00 00 00 20 00 00 00 00 40 00
00000100h: 00 10 00 00 00 02 00 00 04 00 00 00 00 00 00 00
00000110h: 04 00 00 00 00 00 00 00 00 20 00 00 00 02 00 00
00000120h: 00 00 00 00 03 00 00 00 00 00 10 00 00 10 00 00
00000130h: 00 00 10 00 00 10 00 00 00 00 00 00 10 00 00 00
00000140h: 00 00 00 00 00 00 00 00 38 10 00 00 28 00 00 00
00000150h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000160h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000170h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000180h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000190h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000001a0h: 00 10 00 00 08 00 00 00 00 00 00 00 00 00 00 00
000001b0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000001c0h: 2E 74 65 78 74 00 00 00 82 00 00 00 00 10 00 00
000001d0h: 00 02 00 00 00 02 00 00 00 00 00 00 00 00 00 00
000001e0h: 00 00 00 00 20 00 00 60 00 00 00 00 00 00 00 00
000001f0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000200h: 68 10 00 00 00 00 00 00 6D 79 20 66 69 72 73 74
00000210h: 20 77 69 6E 64 6F 77 00 67 6F 6F 64 00 00 6A 00
00000220h: 68 18 10 40 00 68 08 10 40 00 6A 00 FF 15 00 10
00000230h: 40 00 33 C0 C3 CC CC CC 60 10 00 00 00 00 00 00
00000240h: 00 00 00 00 76 10 00 00 00 10 00 00 00 00 00 00
00000250h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000260h: 68 10 00 00 00 00 00 00 BE 01 4D 65 73 73 61 67
00000270h: 65 42 6F 78 41 00 55 53 45 52 33 32 2E 64 6C 6C
00000280h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000290h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000002a0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000002b0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000002c0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000002d0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000002e0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000002f0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000300h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000310h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000320h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000330h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000340h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000350h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000360h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000370h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000380h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000390h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000003a0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000003b0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000003c0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000003d0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000003e0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000003f0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

哪里有垃圾代码?不要告诉我对齐'00'数据也叫垃圾代码.
BCB那才是"垃圾代码生成器".
雪    币: 236
活跃值: (326)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
gzgzlxg 11 2006-6-1 00:56
14
0
没有条件转移,只有一个简单的Call当然不会出垃圾代码,你试试加几句条件转移,在加几个循环,就明白我说的是什么了。
雪    币: 217
活跃值: (99)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
dwing 1 2006-6-1 08:32
15
0
最初由 gzgzlxg 发布
没有条件转移,只有一个简单的Call当然不会出垃圾代码,你试试加几句条件转移,在加几个循环,就明白我说的是什么了。


除极为复杂的算法程序外,一般的条件转移和循环VC都能有效地优化.
而类似lea eax,[eax]这样的指令也是故意安排的,使下面的指令被对齐.以利于指令cache充分地装入指令流.

除非汇编水平极高的人外,VC以最短代码方式编译比手工写汇编可能更短.
我发现许多人喜欢这样写程序:
push 0
push 0
push 0
call xxxx
或者写 invoke xxxx,0,0,0
而VC很聪明地编译成:
xor eax,eax
push eax
push eax
push eax
call xxxx
而究竟有多少人清楚push 0是2字节指令,push eax是1字节指令?

即使以最快代码方式编译,速度也很可能比手工写汇编可能更快.
因为许多用汇编写程序的人都不了解如何优化cache,如何安排指令搭配才能使CPU并行运算,如何充分利用流水线.
这比少写几句汇编代码还要有效.

当然对于多媒体指令和其它扩展指令,高级语言编译器还无法优化的很好.

我写这些并不是排斥汇编,而是汇编要用到真正发挥的地方.写视音频编码解码的核心就必须用汇编,而写个界面及消息处理程序用汇编完全跟自己过不去,导致无法很好地调试和维护,这比稍稍加快速度或稍稍减少代码量要重要得多.

PS: 怎么形容Borland的编译器呢? JBuilder2005的界面核心竟然是用VC编译的,还附带了MFC的运行库
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
willii 2006-6-1 09:04
16
0
VC不是万能,你如果要最求最小代码自然要用汇编。
但是VC也绝不是垃圾代码生成器,楼主的例子应该是用了Debug编译造成的。
公平的说,VC编译的代码质量还是可以的,当然你如果非要挑毛病那肯定能挑出来
雪    币: 236
活跃值: (326)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
gzgzlxg 11 2006-6-1 12:04
17
0
其实masm32的宏,那些 .if  .while  都不怎么样,那个 repeat 生成的代码还可以。所以也不代表使用宏汇编就可以生成很好的代码,另外和link的版本也有很大的关系。
每一种编程语言只要他还活着,就有他生存的道理,至于使用什么语言,那是因需要而定的,也可以因个人的喜好而定。
汇编开发效率太低,所以用来研究一些问题还是可以的,搞开发还是用高级语言比较好玩,现在机器越来越快,容量越来越大,有几句垃圾代码也无所谓,写壳还人为的制造垃圾。
我什么语言都学不好,主要原因是记不住,哈哈,现在机器的容量越来越大,可是我随着越来越老,脑容量却越来越小,在过几年也许一门语言都不会了。
雪    币: 196
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
guochao 2006-6-1 13:46
18
0
把编译方式改一下,然后在把没有用到的连接库去掉可以减小一些体积
雪    币: 217
活跃值: (99)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
dwing 1 2006-6-1 19:02
19
0
最初由 guochao 发布
把编译方式改一下,然后在把没有用到的连接库去掉可以减小一些体积


连接库改不改无所谓,楼主的问题主要在于DEBUG模式含有大量的调试信息,都是便于在VC中非常方便地跟踪代码和变量的.
选择RELEASE模式并使用DLL的标准库是最减小体积有效的方法.
雪    币: 191
活跃值: (55)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
chenzping 2 2006-6-2 09:09
20
0
怎样使用DLL的标准库呢;楼上的的朋友介绍一下好吗?
雪    币: 217
活跃值: (99)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
dwing 1 2006-6-2 09:20
21
0
最初由 chenzping 发布
怎样使用DLL的标准库呢;楼上的的朋友介绍一下好吗?

Project -> Settings -> C/C++ -> Code Generation -> Use run-time library -> Multithreaded DLL
雪    币: 191
活跃值: (55)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
chenzping 2 2006-6-2 09:48
22
0
谢谢,你真厉害
雪    币: 241
活跃值: (160)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xiluoyou 2006-6-7 23:22
23
0
最初由 dwing 发布
Project -> Settings -> C/C++ -> Code Generation -> Use run-time library -> Multithreaded DLL

怎么用命令实现?如#pragma comment什么的?
雪    币: 207
活跃值: (40)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
堀北真希 1 2006-6-7 23:29
24
0
最初由 dwing 发布
即使以最快代码方式编译,速度也很可能比手工写汇编可能更快.
因为许多用汇编写程序的人都不了解如何优化cache,如何安排指令搭配才能使CPU并行运算,如何充分利用流水线.
这比少写几句汇编代码还要有效.


非常同意Dwing

用VC的最快速度编译常常比最小尺寸编译出来的大
行数少并不代表速度快
雪    币: 222
活跃值: (10)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
drwch 3 2006-6-22 18:39
25
0
我觉得想要做一个好的ASM程序师,下面这篇文章是非看不可的

http://www.codingnow.com/2000/download/pentopt.htm

CACHE对齐的确是一个很容易被忽视的问题
游客
登录 | 注册 方可回帖
返回