I'm currently playing around with Win32 assembly.
I've been struggling with the WinMain entry point in assembly for some time now. There's one bizarre - to me - difference between what NASM & link.exe produced from my hand-written asm and what MSVC has come up with.
1) The C(++) code - just another MessageBox hello world
#include <Windows.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MessageBoxA(NULL, "Hello world", "Window title", MB_OK | MB_ICONEXCLAMATION);
}
2) The assembly equivalent
global _main
extern _MessageBoxA@16
extern _ExitProcess@4
section .text
_main:
push 0x30
push wintitle
push message
push 0
call _MessageBoxA@16
push 0
call _ExitProcess@4
section .data
message:
db 'Hello, World', 0
wintitle:
db 'Window title', 0
Technical "specification":
- The OS is a 32bit Win7
- The C++ program has been compiled with MS VC++ 2013
- The assembly program has been compiled with nasm -fwin32 msgbox.asm
, then linked with link /nodefaultlib /subsystem:windows msgbox.obj kernel32.lib user32.lib -entry:main
Now here comes the actual question.
When I disassembled these with OllyDbg 2.01, this is what I saw:
1) C++ version
2)ASM version:
Now, if we take a look at the stack window, it looks as if Windows didn't actually pass the right arguments to my assembly entry point. There are just two garbage integers before a return to ntdll, as opposed to the C++ version, where all four parameters are present.
This is a problem for me as I would like to obtain (in another assembly program) the hInstance variable inside the entry point. Using [EBP+8]
gives me the garbage I've mentioned above instead of the right hInstance value.
Any help is greatly appreciated.
The WinMain
entry point in your C++ code is called by the C runtime library, not by Windows.
The actual Win32 entry point signature is
void __stdcall NoCRTMain(void);
You can obtain the command line using GetCommandLine
and if you need to convert it to argc/argv format you can use CommandLineToArgvW
.
You can get hInstance
by calling GetModuleHandle
with the argument set to NULL
. (Note that in Win32, unlike 16-bit Windows, HINSTANCE
and HMODULE
are the same thing.)