https://www.barbieinablender.org/

Archive

Archive for January, 2009

void main() v/s int main()

January 8th, 2009 2 comments

Many people use void main() instead of int main() while writing C/C++ programs, inspite of void not being accepted as a return type for main in the C/C++ standard.

I too used to do the same until some programmers on a programming forum told me a few years ago about the C++ Standard.

But what does void do anyway? How is it different from return 0?

I disassembled a few test programs to check what really happens under the hood.  It is interesting to know what happens when a program is executed.

Almost everybody believes that main()/WinMain() is the entrypoint of all C/C++ programs but it isn’t so.

On Windows, a start() function gets called before the main() function. It first calls GetVersion(), GetCommandLine(), GetEnvironmentStrings(), GetStartupInfo() and GetModuleHandle() API Functions from kernel32.dll in the exact order. Then it passes the Module Handle, command-line arguments and environment variables as arguments to main() and then calls it.

But what about main()’s return value? Is it read after main() quits?

It doesn’t matter what data type you return from main(). Whether its int or void it doesn’t make any difference.
Here’s what actually happens.
In an executable file, the start() function which calls the main() function, expects a return value of data type integer so that it may decide what argument is passed to the exit() function which is called after main().
If void is chosen as the return type for main, the EAX register is passed as an argument to the exit function.
Since the EAX register almost always contains the return value of any function, so if we say return 0, EAX would be set to zero, that’s all.
Generally whenever void is used, EAX is set to zero at the end of main() , so it is exactly the same as passing return 0.
But since void main() is not a part of the standard, compiler developers are given full freedom to design their own implementation of the code after main() returns. Hence, we cannot always assume that EAX is set to 0 with a void main().

Ever wondered what happens to the return value after main() quits?
Take a look at this disassembled snippet of the start() function from a C/C++ program.

call dword ptr [esi+18h] ; call main()
add esp, 0Ch
; (4 x 3) 12 bytes are cleared from the stack to clear space
; occupied by main()'s three arguments.
push eax ; status for exit. Return value of main() is pushed
call _exit

So no matter what you do, even if you ignore the return value type, the compiler will still pass the contents of the EAX Register into the exit function. This could lead to some unwanted results, and hence it is better to return 0 (ie. EXIT_SUCCESS) or 1(EXIT_FAILURE) depending on when and why you have designed the program to end.

So even though, it is almost always the same, there is a reason why the standard recommends using int. Simply for the following reasons:
returning 0 by default is COMPILER DEPENDENT.
No Guarantee about the content of the EAX Register after main() exits.
Will not be portable to all Operating Systems.
May cause incorrect termination of main()

So even though void main and return 0 are alike, we should try to avoid its use.

Microsoft does it differently

January 8th, 2009 1 comment

A while back I was studying the Len() function of VB6 and I came across something interesting.

Contrary to our belief that this function counts the number of characters in a string and returns it, it actually does something totally different.

Here’s how it works.

When any string is stored in VB, it is automatically stored in this format (in unicode):

Suppose the String is “ABC”:

06 00 00 00 41 00 42 00 43 00

The 41 to 43 part is a typical unicode style of storing strings, but 2 unicode characters before that, the number of bytes occupied by the string (including zeros) is stored (which is similar to Pascal style strings).
Hence 06 stands for 6 bytes occupied by “ABC” (since it’s stored as A,0,B,0,C,0)

So all that the Len() does is read 4 bytes before the beginning of the string and return that value itself, instead of calculating the length of the string.

So actually, the Len Function does nothing except read the length from the string format and return it.
Want to see how they do it?
Here’s the Disassembled Listing of the Len() Function MSVBVM60.DLL DLL File.

__vbaLenBstr proc near
   string = dword ptr 4

   mov eax, [esp+string] ; eax points to string
   test eax, eax ; ZF,SF,PF = EAX and EAX
   jz short break ; If String is Null then break from loop
   mov eax, [eax-4] ; Gets Unicode Length stored before string.

   ; Here’s how Text from textbox is stored internally:
   ; If text is born2c0de then in memory:
   ; (0×12 0×00) 0×00 0×00 (0×62 0×00 …)
   ; ie. length of string in bytes(unicode) (here 18 bytes)
   ; followed by a Unicode 0 (0×00 0×00)
   ; followed by the actual string in unicode
   ; (’b’ 00 ‘o’ 00 … ‘e’ 00)
   ; So [eax-4] just gets the unicode length of
   ; string which already is stored when a
   ; string is taken as input from keyboard.

   ; The Len() function doesn’t even calculate length!!!
   shr eax, 1 ; Divides Length by 2 to get Actual Length.
   ; Uses eax so it can be used as a return value.

break:
   retn 4
__vbaLenBstr endp