減小gcc的編譯體積
- 先來說說exe
-
- 縱觀各個選項的效果
- 最佳效果
- 來說說dll
-
- 一個玩法
- 似乎沒用的警告?
- 解決它,給出實作
- 提高
- 小實驗
-
- 目标
- 思路
- 開幹
先來說說exe
作為可執行檔案,其體積重要性不得而知.
縱觀各個選項的效果
(本文所有一律采取32位,64位同理)
正常編譯:
gcc -m32 a.c -o a.exe
102kb,正常運作
加上
-s
開關:
gcc -m32 a.c -s
12kb,正常運作
加上
-w
,效果幾乎…沒有
最佳效果
這不顯而易見嘛…如下:
gcc -s -w [-m32] sourcefile.c -o outputfile.exe
似乎并沒什麼用
來說說dll
動态連結庫的體積一直是個迷…還是先看看各個選項的結果吧(預設加上-m32)
開關 | 體積 |
---|---|
無 | 80k |
-s | 11k |
-s -w | 11k |
一個玩法
你可以帶上
-nostartfiles
開關.來看看效果
似乎沒用的警告?
看得見沒有定義一個函數叫做
[email protected]
.很明顯這是stdcall的格式.可以了解成一個叫做
DllMainCRTStartup
的函數,有三個
int
型參數.
抱着信心忽略這個警告,結果翻車了:列印的内容呢!
解決它,給出實作
看名字好像是啟動函數.诶?dll也有主函數?是的沒錯網上查就知道了.聽說這個函數會在dll被加載,寫在,或者線程啟動等時機被自動調用.
那是不是給出這個函數的實作就行了呢?可以試試這個:
編譯試試?警告:
說白了用自己的函數替代了标準運作時庫的那個啟動函數(其實是個預設值)
運作試試?還是不行.
網上查了下資料,看見有人寫了個startup函數,傳回
true
!
ref
咱也來試試呵,給他改一下:
運作成功!
提高
明顯可以在任意項目的dll中使用這個法子,但是有個缺點,好像直接替代别個的預設值顯得很不道地.那麼有個
-e
參數大家記得吧,設定入口點的.于是這個函數随便命名,然後-e指定一下就行了.這個不做解釋
小實驗
目标
不管用什麼工具,語言,編譯器,甚至手寫exe,反正給我個最小的檔案,可以輸出"helllo,world!"字樣.
思路
要小,那麼第一個想到的應該是nasm而不是手寫bin.前者比後者明智許多并且效率高.等效替代嘛!
再就是,結合上述兩種優化體積的方法,來試試最小能到多少
(衆所周知,-m32比-m64小,32位的指令寬,以及對齊什麼的都有影響,是以為了效果明顯在此使用32位編譯)
開幹
寫個asm:
[SECTION .text]
[GLOBAL _pp]
[GLOBAL _dlls]
[EXTERN _printf]
[BITS 32]
_pp:
PUSH EBP
MOV EBP, ESP
SUB ESP, 12
PUSH LC0
CALL _printf
LEAVE
RET
_dlls:
PUSH EBP
MOV EBP, ESP
NOP
MOV EAX, 1
LEAVE
RET
[SECTION .data]
LC0:
DB "hello,world!", 10, 0
(注:’\n’ == 10)
編譯的指令:
nasm -fwin32 a.asm -o a.o
gcc -m32 -nostartfiles -s -w -e_pp a.o -o a.exe
./a
由于沒有符号表,是以不展示objdump的結果了.但是可以明确的是,這個程式裡隻有我們的代碼段,和少許gcc加進去的資訊.試驗成功!2K!
另:由此可見,對齊也是有影響的.不可能每次編譯都是正好512等二進制"整"數的整數倍啊!我自己試了下,改動彙編代碼(比如加個NOP)不會影響輸出檔案的大小,證明該檔案是以合适的位元組大小對齊.