Sometimes when reversing the code - I see that each linked file is separated by these functions:
_$E19_$E18
sometimes - there is no such separation (depending on the degree of compiler optimization).
What is their meaning?
.text:0000021C .text:0000021C ; =============== S U B R O U T I N E ======================================= .text:0000021C .text:0000021C .text:0000021C _$E19 proc near ; DATA XREF: .CRT$XCU:_$S20o .text:0000021C mov cl, byte ptr ds:??_B?1???id@?$ctype@G@std@@$D@@9@51 .text:00000222 mov al, 1 .text:00000224 test al, cl .text:00000226 jnz short loc_230 .text:00000228 or cl, al .text:0000022A mov byte ptr ds:??_B?1???id@?$ctype@G@std@@$D@@9@51, cl .text:00000230 .text:00000230 loc_230: ; CODE XREF: _$E19+Aj .text:00000230 jmp _$E18 .text:00000230 _$E19 endp .text:00000230 .text:00000230 ; --------------------------------------------------------------------------- .text:00000235 db 7 dup(90h) .text:00000235 _text ends .text:00000235 .text:0000023C ; =========================================================================== .text:0000023C .text:0000023C ; Segment type: Pure code .text:0000023C ; Segment permissions: Read/Execute .text:0000023C _text segment para public 'CODE' use32 .text:0000023C assume cs:_text .text:0000023C ;org 23Ch .text:0000023C ; COMDAT (pick no duplicate) .text:0000023C assume es:nothing, ss:nothing, ds:_CRT$XCU, fs:nothing, gs:nothing .text:0000023C .text:0000023C ; =============== S U B R O U T I N E ======================================= .text:0000023C .text:0000023C .text:0000023C _$E18 proc near ; CODE XREF: _$E19:loc_230j .text:0000023C push offset ?id@?$ctype@G@std@@$E ; void (__cdecl *)() .text:00000241 call _atexit .text:00000246 pop ecx .text:00000247 retn .text:00000247 _$E18 endp .text:00000247 .text:00000247 ; --------------------------------------------------------------------------- .text:00000248 db 4 dup(90h) .text:00000248 _text ends .text:00000248 for example:
class aa { public: aa(); ~aa(); void fun(); }; class bb { public: bb(); ~bb(); void fun(); }; class cc { public: cc(); ~cc(); void fun(); }; // IMPLEMENTATION aa::aa() { } aa::~aa() { } void aa::fun() { printf("aa called"); } // ------------------------ bb::bb() { } bb::~bb() { } void bb::fun() { printf("bb called"); std::string s = "asd"; // <------------ reason } // -------------------------- cc::cc() { } cc::~cc() { } void cc::fun() { printf("cc called"); } generates this list of functions:
aa::aa(void) aa::~aa(void) aa::fun(void) bb::bb(void) bb::~bb(void) bb::fun(void) std::basic_string<char,std::char_traits<char>,std::allocator<char>>::_Grow(uint,bool) std::basic_string<char,std::char_traits<char>,std::allocator<char>>::_Copy(uint) $E19 $E18 [thunk]:std::ctype<ushort>::id`template static data member destructor helper' cc::cc(void) cc::~cc(void) cc::fun(void) _main _printf But, the global variable initialized by the functions (_$E19, _$E18) is never used.
i'm vote for the new tag: code-generation
_$E19is the code that registers or unregisters (00000224 with subsequentjnzor "fallthrough") the routine referenced at 0000023C with atexit. Now, I could be wrong and without further context I won't dare to answer this, but perhaps it helps you on your way to find out.