На этом шаге мы рассмотрим как оптимизирует код транслятор Borland C++ 4.5.
Ранее мы пытались восстановить исходный текст программы по ассемблерному коду. Насколько это удалось, можно выяснить, сравнив получившийся текст с исходным. Причина отличия двух текстов программ заключается в том, что транслятор, кроме всего прочего, производит еще оптимизацию кода. Результат оптимизации - принципиальная невозможность восстановить исходный текст по исполняемому коду. Можно, однако, получить программный текст, правильно описывающий алгоритм исполнения. Можно просто понять то, что делает данный код.
Рассмотрим небольшую программу на С.
#include <iostream.h> #include <conio.h> void main() { int i; char a[10]; char b[11]; for(i=0; i<10; i++) { a[i]='a'; *(b+i)='a'; cout << a[i] << " " << b[i] << endl; } getch(); }
Приведем текст дизассемблированной программы, полученной с помощью IDA PRO:
CODE:00410074 _main proc near ; DATA XREF: DATA:00420044 CODE:00410074 CODE:00410074 var_18 = byte ptr -18h CODE:00410074 var_C = byte ptr -0Ch CODE:00410074 argc = dword ptr 8 CODE:00410074 argv = dword ptr 0Ch CODE:00410074 envp = dword ptr 10h CODE:00410074 CODE:00410074 push ebp CODE:00410075 mov ebp, esp CODE:00410077 add esp, 0FFFFFFE8h CODE:0041007A push ebx CODE:0041007B push esi CODE:0041007C xor ebx, ebx CODE:0041007E CODE:0041007E loc_41007E: ; CODE XREF: _main+52 CODE:0041007E mov [ebp+ebx+var_C], 61h CODE:00410083 mov [ebp+ebx+var_18], 61h CODE:00410088 mov al, [ebp+ebx+var_18] CODE:0041008C push eax CODE:0041008D mov al, [ebp+ebx+var_C] CODE:00410091 push eax CODE:00410092 push ds:_cout CODE:00410098 call @ostream@$blsh$qc ; ostream::operator<<(char) CODE:0041009D add esp, 8 CODE:004100A0 mov esi, eax CODE:004100A2 push 0 CODE:004100A4 push offset unk_420070 CODE:004100A9 push esi ; ostream::outstr(char *,char *) CODE:004100AA call @ostream@outstr$qpxct1 CODE:004100AF add esp, 0Ch CODE:004100B2 push esi CODE:004100B3 call @ostream@$blsh$qc ; ostream::operator<<(char) CODE:004100B8 add esp, 8 CODE:004100BB push eax CODE:004100BC call @endl$qr7ostream ; endl(ostream &) CODE:004100C1 pop ecx CODE:004100C2 inc ebx CODE:004100C3 cmp ebx, 0Ah CODE:004100C6 jl short loc_41007E CODE:004100C8 call _getch CODE:004100CD pop esi CODE:004100CE pop ebx CODE:004100CF mov esp, ebp CODE:004100D1 pop ebp CODE:004100D2 retn CODE:004100D2 _main endp
Видно, что здесь оптимизация отсутствует. По такому тексту достаточно просто восстановить исходную С-программу.
На следующем шаге мы рассмотрим работу транслятора Visual C++ 6.0.