WinMain entry point - assembly code looks as if there were no arguments to entry point
I am currently playing with Win32 build.
I have been struggling with WinMain entry point into assembly for a while now. There's one strange one - for me, the difference between NASM and link.exe is produced from my handwritten asm and what MSVC came up with.
1) C (++) Code is just another world of Greeting MessageBox
#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) 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":
- OS - 32-bit Win7
- C ++ program was compiled with MS VC ++ 2013
- Build program compiled with nasm -fwin32 msgbox.asm
and then linked withlink /nodefaultlib /subsystem:windows msgbox.obj kernel32.lib user32.lib -entry:main
Now here's a topical question .
When I disassembled them with OllyDbg 2.01, this is what I saw:
1) C ++
version 2) ASM version:
Now, if we look at the stack window, it looks like Windows did not actually pass the correct arguments to my assembly entry point. There are only two garbage chains before returning to ntdll, unlike the C ++ version where all four parameters are present.
This is a problem for me as I would like to get (in a different assembly) the hInstance variable inside the entry point. Usage [EBP+8]
gives me the garbage I mentioned above instead of the correct hInstance value.
Any help is greatly appreciated.
source to share
The entry point WinMain
in C ++ code is called by the C runtime library, not Windows.
Win32 entry point actual signature
void __stdcall NoCRTMain(void);
You can get the command line using GetCommandLine
, and if you need to convert it to argc / argv format, you can use CommandLineToArgvW
.
You can get hInstance
it by calling GetModuleHandle
with the argument set to NULL
. (Note that in Win32, as opposed to 16-bit Windows, hInstance
and HMODULE
are the same thing.)
source to share
These four arguments are provided by the runtime, not the operating system. If you look at the value [esp]
at the entry point, the assembly version falls back to kernel32
, that is, the OS, and the C ++ version falls back to your module's execution code.
Open the C ++ version with OllyDbg at a real entry point and you will see a lot of initialization code like argument parsing, TLS variables, etc. Also compare the size of the binaries and you will see about 4kb versus about 30-90kb.
source to share