Is there anything meaningful on the stack when the Windows loader calls the "start:" label in a PE program? I know that when WinMain is reached (in a C program), there are 4 dwords:
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // pointer to command line
int nCmdShow // show state of window
);
In 32-bit C for Windows, the hPrevInstance is always zero. I examined the stack in a basic Masm32 application, and that field is indeed zero at the entry point. But I can't make sense of the other three fields. I was after the command tail. The address in the third field is readable by the program (no page fault occurs) but the data there does not look like a command tail.
Thx.
Posted on 2004-10-25 20:23:41 by LarryH
Larry,

You must provide the command line yourself using an API function. There is nothing useful on the stack at start. In assembler if you want a WinMain procedure, you must produce the parameters yourself.
Posted on 2004-10-25 21:14:35 by hutch--
Thanks Hutch. I'm sure you're right. Also, I looked at some C programs under a debugger, and the C compiler has attached a prolog to WinMain, which finds the command tail by an API call, just as you say. And I suppose, if the stack contains dwords which "seem" to be hPrevInstance and lpCommandLine, that is probably just an artifact of the fact that the Windows loader itself was written in C.
Posted on 2004-10-25 22:44:17 by LarryH
Since a win32 app can be terminated by a simple "ret" instead of calling ExitProcess, the first dword onto the stack must be "defined" in the sense that it will point to valid "termination code".
Posted on 2004-10-25 22:59:38 by japheth
first dword on stack hold a return address to kernel that will ExitThread your program and terminate it.
further down in stack we can see some return addresses, the default seh handler for your program, and the last, your modules entry point.

this is how it looks on my machine (winxp) should be similiar on others:

$ ==> > 77E7EB69 RETURN to kernel32.77E7EB69
$+4 > 0000A911
$+8 > 77D4CBDC RETURN to user32.77D4CBDC from user32.77D4CBFE
$+C > 7FFDF000
$+10 > F558BCF4
$+14 > 0012FFC8
$+18 > 8052F184
$+1C > FFFFFFFF End of SEH chain
$+20 > 77E9BB86 SE handler
$+24 > 77E95A18 kernel32.77E95A18
$+28 > 00000000
$+2C > 00000000
$+30 > 00000000
$+34 > 00409264 FlashFXP.<ModuleEntryPoint>
$+38 > 00000000
Posted on 2004-10-26 03:05:18 by pwn
You can always load a program from a debugger like OllyDbg, and watch what's on the stack pane on startup. :)
Posted on 2004-10-26 16:45:03 by QvasiModo
It's "very likely" that the first DWORD on stack will contain a return-address into the system, which will end up with ExitThread... but I haven't seen it documented anywhere officially, so even though it holds true on all win32 versions, you "shouldn't depend on it for release-quality software" :-)
Posted on 2004-10-27 10:04:04 by f0dder
Thanks for the info, guys. DOS also puts a return address on the stack when it loads *.com: the word 0, which points to the instruction INT 20h in the PSP. I think this practice goes back to the time of the CP/M operating system. But I've never heard of any programmer using or recommending that kind of exit in DOS.
Posted on 2004-10-31 02:01:24 by LarryH