View Full Version : Các kỹ thuật optimize code của VC++ 200x Compiler
Hi all !
Tính tui hay build code trong Release mode rồi open it in IDA để xem code ASM mà VC++ compiler sinh ra. Một thời gian dài, tui đi từ ngạc nhiên này đến các ngạc nhiên khác về kỹ thuật optimize code của VC++ compiler từ 2003 về sau này (2010 tui chưa install, lười rồi).
Dưới đây, tui xin mạo muội trình bày một số kỹ thuật optimize code của VC++ compiler mà tui đã biết và trong các article trên Internet:
1. Loại bỏ biến, code thừa, không dùng, tự tính toán constant:
vd:
void Func()
{
int A = 2;
int Size = 3 * 8 * A;
UpdateSize(Size * 5);
}
Code qua optimize:
void Func()
{
UpdateSize(240);
}
Loại bỏ biến A & Size vì A & Size là constant, chỉ khởi gán 1 lần, dùng 1 lần. Nhờ loại A & Size, compiler sẽ không cần sinh mã cấp phát stack cho A & Size. ASM code sẽ nhỏ hơn, nhanh hơn.
2. Loại bỏ các biến copy không dùng
void f(int g)
{
int j = g;
func(j * 2);
}
Code optimize:
void f(int g)
{
func(g * 2);
}
Compiler remove biến j vì g chính là j. Loại bỏ j, compiler không còn cần sinh code cấp phát stack cho j nữa.
3. Tự đông sinh code inline cho các function nhỏ (không cần phải declare inline), vd memcpy, strcpy....
4. Còn tiếp...
benina
12-03-2010, 12:24 PM
Tiếp tục đi bác TQN, học được mấy cái này dù mình code tầm bậy nó cũng optimize cho mình đỡ phải ngồi optimize source code. Nhưng theo tui biết optimize mã binary sau khi biên dịch của VC lại kém hiệu quả hơn BC. Hiệu quả ở đây là size và speed. Vì vậy Olly được viết trong BC (hay TC gì đó ko nhớ rõ) là vì lý do đó.
Thanz u for advance.
Benina
OllyDbg được viết = Borland C++ Builder 5 Free Compiler (bcc55.exe). Oleg, tác giả của OllyDbg không có VS (và không mua) nên phải dùng đồ free. Ở nước ngoài chứ có phải VN mình đâu anh Be, đồ gì cũng có, muốn VS 2010 cũng có luôn...????
Bây giờ tui mà nghe cái câu "Borland is speed" (hay "Delphi is speed") thì lại thấy ngậm ngùi, nhớ thời hoàng kim xa xưa của Borland. Từ bản Borland C++ 5.x trở về trước, tốc độ compile, link, sinh code ASM của Borland là vô địch. Nhưng giờ đây thì phải nhường bước cho VS 200x và Intel C++ compiler rồi. Code bự bà cố, sinh code dư cũng bà cố luôn.
Nhiều lúc ngồi code, RE application trên C++Builder, Delphi của Borland(CodeGear/Embraccor), tui cứ thấy bực, sinh code tệ quá, thậm chí stupid quá.
Vd tui đang re 1 app viết = C++Builder 2010 (mới nhất đấy nhé). Có 1 hàm đơn giản sau:
.text:00401880 __fastcall CurrentProcessId(void) proc near
.text:00401880 ; CODE XREF: GetCurrentProcessHandle+4p
.text:00401880 ; ThreadProc_2+3Fp
.text:00401880 ; ThreadProc_1+19p
.text:00401880
.text:00401880 var_4 = dword ptr -4
.text:00401880
.text:00401880 push ebp
.text:00401881 mov ebp, esp
.text:00401883 push ecx
.text:00401884 call GetCurrentProcessId ; Call Procedure
.text:00401884
.text:00401889 mov [ebp+var_4], eax
.text:0040188C mov eax, [ebp+var_4]
.text:0040188F pop ecx
.text:00401890 pop ebp
.text:00401891 retn ; Return Near from Procedure
.text:00401891
.text:00401891 __fastcall CurrentProcessId(void) endp
Đọc kỹ ta sẽ thấy hai thằng thừa.
1. Local var var_4 là thừa, tốn thêm 2 lệnh mov eax vào var_4 rồi lại var_4 vào eax (GetCurrentProcessId return value trong eax).
2. push ecx làm gì, trong khi GetCurrentProcessId là hàm void. ECX = this đi nữa thì call API function thì push làm gì, phải tốn thêm lệnh pop ecx
Nếu VC++200x compile thì code sẽ như sau (giã sử ta không cho nó inline và force create function prologue/epilogue)
push ebp
mov ebp, esp
call GetCurrentProcessId
pop ebp
ret
Còn cho nó inline thì chỉ là call GetCurrentProcessId mà thôi.
phu7o7cs
16-04-2010, 05:03 PM
Mình là một người rất thích Delphi... nhưng giờ đây cũng phải chuyển sang VS...
Quả đúng là: Delphi và C++ Builder đang tụt hậu. Từ bản 8(.Net) cho đến bản 2009 rất là tệ... nhưng với bản 2010 thì có khởi sắc rất nhiều... Hi vọng là nó sẽ trở về lại thời kì vàng son của mình... Tới đây, bản 2011 sẽ có khả năng Cross Platform...
Trong VS, nếu mình thực hiện lệnh:
DWORD t1 = Gettickcount();
for(int i = 0; i < 10000000; i++)
for (j = 0; j < 100000000; j ++);
DWORD t2 = Gettickcount();
thì t2 - t1 = 0. Vì lý do gì thì mọi người cũng hiểu rồi...
Nature Master
20-06-2010, 02:32 AM
DWORD t1 = Gettickcount();
for(int i = 0; i < 10000000; i++)
for (j = 0; j < 100000000; j ++);
DWORD t2 = Gettickcount();
thì t2 - t1 = 0. Vì lý do gì thì mọi người cũng hiểu rồi...
Ơ, tại sao nó lại bằng nhau nhỉ, chạy những 10tr * 100tr lần lặp cơ mà (:-O)
icttrack
20-06-2010, 07:46 AM
@Nature Master: làm việc vô nghĩa thì có nên tạo vòng lặp đó ko?
Nature Master
23-06-2010, 11:15 AM
À há, em ko để í thấy dấu ; sau for j nên tưởng
for(int i = 0; i < 10000000; i++)
for (j = 0; j < 100000000; j ++)
DWORD t2 = Gettickcount();
vBulletin® v3.8.4, Copyright ©2000-2010, Jelsoft Enterprises Ltd. Administrer by Kevin Hoang