| ||
Object-oriented programming considerably complicates the resulting executable code. Consider one small example. Listing 25.8 contains an easy C++ program.
#include <windows.h> #include <stdio.h> class string { public: char c[200]; char g[100]; string() {strcpy(c, "Hello"); strcpy(g, "Hello");} int strep(); }; string::stri() { strcpy(c, g); return 0; } main() { string * s = new string; s->strcp() ; printf("%s\n", s->c); delete s; }
Listing 25.9 contains the disassembled code of the main procedure. Disassembling was done with IDA Pro.
CODE:00401122 _main proc near ; DATA XREF: DATA:0040C044 CODE:00401122 CODE:00401122 var_28 = DWORD PTR -28H CODE:00401122 var_18 = WORD PTR -18H CODE:00401122 dest = DWORD PTR -4 CODE:00401122 argc = DWORD PTR 8 CODE:00401122 argv = DWORD PTR 0CH CODE:00401122 envp = DWORD PTR 10H CODE:00401122 CODE:00401122 PUSH EBP CODE:00401123 MOV EBP, ESP CODE:00401125 ADD ESP, 0FFFFFFD8H CODE:00401128 PUSH EBX CODE:00401129 MOV EAX, OFFSET STRU_40C084 CODE:0040112E CALL @__INITEXCEPTBLOCKLDTC CODE:00401133 PUSH 12CH CODE:00401138 CALL UNKNOWN_LIBNAME_8 CODE:0040113D POP ECX CODE:0040113E MOV [EBP+DEST], EAX CODE:00401141 TEST EAX, EAX CODE:00401143 JZ SHORT LOC_40117D CODE:00401145 MOV [EBP+VAR_18], 14H CODE:0040114B PUSH OFFSET aHello ; SRC CODE:00401150 PUSH [EBP+DEST] ; DEST CODE:00401153 CALL _STRCPY CODE:00401158 ADD ESP, 8 CODE:0040115B PUSH OFFSET aHello_0 ; SRC CODE:00401160 MOV EDX, [EBP+DEST] CODE:00401163 ADD EDX, 0C8H CODE:00401169 PUSH EDX ; DEST CODE:0040116A CALL _STRCPY CODE:0040116F ADD ESP, 8 CODE:00401172 MOV [EBP+VAR_18], 8 CODE:00401178 MOV EBX, [EBP+DEST] CODE:0040117B JMP SHORT LOC_401180 CODE:0040117D ;-------------------------------------- CODE:0040117D CODE:0040117D CODE:0040117D LOC_40117D: ; CODE XREF: _MAIN+21 CODE:0040117D MOV EBX, [EBP+DEST] CODE:00401180 CODE:00401180 LOC_401180: ; CODE XREF: _MAIN+59 CODE:00401180 PUSH EBX ; DEST CODE:00401181 CALL SUB_401108 CODE:00401186 POP ECX CODE:00401187 PUSH EBX ; CHAR CODE:00401188 PUSH OFFSET AS ; __VA_ARGS CODE:0040118D CALL _PRINTF CODE:00401192 ADD ESP, 8 CODE:00401195 PUSH EBX ; BLOCK CODE:00401196 CALL @$BDELE$QPV ; OPERATOR DELETE(VOID *) CODE:0040119B POP ECX CODE:0040119C MOV EAX, [EBP+VAR_28] CODE:0040119F MOV LARGE FS:0, EAX CODE;004011A5 XOR EAX, EAX CODE:004011A7 POP EBX CODE:004011A8 MOV ESP, EBP CODE:004011AA POP EBP CODE:004011AB RETN CODE:004011AB _MAIN ENDP
As you can see, the disassembled code is sophisticated. Note that because of the limited volume of this book I won't provide detailed analysis of this code; in this case, it would be necessary to include an analysis of the library functions. However, some key facts deserve special attention:
The NEW operator is reduced to the execution of a library procedure, unknown_iibname_8 . The latter allocates memory for the properties of the object instance (300 bytes).
The constructor is stored and executed directly in the program body. This is because the constructor is defined in the class text. For experimental purposes, try to place the constructor text into a separate function. You'll see that the constructor will be called from main like any normal function.
The @_InitExceptBiockLDTC procedure is inserted by the translator for exception handling. You can remove the information needed for exception handling, which will reduce the size of the executable code. However, you won't be able of using exception-handling operators such as try or catch .
When calling some method, at least one parameterthe pointer to the object instanceis always placed into the stack.
Now, consider the fragment, disassembled using IDA Pro, of the same C++ program. This time the program was compiled using the -x option, which for Borland C++ means that exception handling is not supported. As you can see, the program text is considerably simpler in Listing 25.10.
.text:00401122 _main proc near ; DATA XREF: .data:0040B0C8 .text:00401122 .text:00401122 argc = dword ptr 8 .text:00401122 argv = dword ptr 0Ch .text:00401122 envp = dword ptr 10h .text:00401122 .text:00401122 PUSH EBP .text:00401123 MOV EBP, ESP .text:00401125 PUSH EBX .text:00401126 PUSH 12CH .text:0040112B CALL UNKNOWN_LIBNAME_8 .text:00401130 POP ECX .text:00401131 MOV EBX, EAX .text:00401133 TEST EAX, EAX .text:00401135 JZ SHORT LOC_40115D .text:00401137 PUSH OFFSET aHello ; SRC .text:0040113C PUSH EBX ; DEST .text:0040113D CALL _STRCPY .text:00401142 ADD ESP, 8 .text:00401145 PUSH OFFSET aHello_0 ; src .text:0040114A LEA EDX, [EBX+0C8H] .text:00401150 PUSH EDX ; DEST .text:00401151 CALL _STRCPY .text:00401156 ADD ESP, 8 .text:00401159 MOV ECX, EBX .text:0040115B JMP SHORT LOC_40115F .text:0040115D ;------------------------------------------ .text:0040115D .text:0040115D loc_40115D:; CODE XREF: _main+13 .text:0040115D MOV ECX, EBX .text:0040115F .text:0040115F loc_40115F:; CODE XREF: _main+39 .text:0040115F MOV EBX, ECX .text:00401161 PUSH EBX ; DEST .text:00401162 CALL SUB_401108 .text:00401167 POP ECX .text:00401168 PUSH EBX ; CHAR .text:00401169 PUSH OFFSET aS ; __va_args .text:0040116E CALL _PRINTF .text:00401173 ADD ESP, 8 .text:00401176 PUSH EBX ; handle .text:00401177 CALL __RTL_CLOSE .text:0040117C POP ECX .text:0040117D XOR EAX, EAX .text:0040117F POP EBX .text:00401180 POP EBP .text:00401181 RETN .text:00401181 _main ENDP
| ||