Точка входа WinMain - ассемблерный код выглядит так, как будто в точку входа не переданы аргументы
В настоящее время я играюсь с сборкой Win32.
Я уже некоторое время борюсь с точкой входа WinMain в сборке. Для меня есть одно странное различие между тем, что NASM и link.exe создали из моего рукописного ассма, и тем, что придумал MSVC.
1) код C(++) - просто еще один приветственный мир 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) Монтажный эквивалент
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
Техническая спецификация":
- ОС является 32-битной Win7
- Программа C++ была скомпилирована с MS VC++ 2013
- Программа сборки была составлена с nasm -fwin32 msgbox.asm
, а затем связано с link /nodefaultlib /subsystem:windows msgbox.obj kernel32.lib user32.lib -entry:main
Теперь возникает актуальный вопрос.
Когда я разобрал их с OllyDbg 2.01, вот что я увидел:
1) версия C++
2) версия ASM:
Теперь, если мы посмотрим на окно стека, похоже, что Windows фактически не передала правильные аргументы моей точке входа в сборку. Перед возвратом в ntdll есть только два целых числа мусора, в отличие от версии C++, где присутствуют все четыре параметра.
Для меня это проблема, так как я хотел бы получить (в другой сборочной программе) переменную hInstance внутри точки входа. С помощью [EBP+8]
дает мне мусор, о котором я говорил выше, вместо правильного значения hInstance.
Любая помощь с благодарностью.
2 ответа
WinMain
точка входа в ваш код C++ вызывается библиотекой времени выполнения C, а не Windows.
Фактическая подпись точки входа Win32
void __stdcall NoCRTMain(void);
Вы можете получить командную строку, используя GetCommandLine
и если вам нужно преобразовать его в формат argc/argv, вы можете использовать CommandLineToArgvW
,
Ты можешь получить hInstance
позвонив GetModuleHandle
с аргументом, установленным в NULL
, (Обратите внимание, что в Win32, в отличие от 16-битной Windows, HINSTANCE
а также HMODULE
это одно и то же.)
Эти четыре аргумента предоставляются средой выполнения, а не операционной системой. Если вы посмотрите на [esp]
значение в точке входа, версия сборки возвращается к kernel32
ОС, а версия C++ возвращается к коду времени выполнения вашего модуля.
Откройте версию C++ с OllyDbg на реальной точке входа, и вы увидите много кода инициализации, такого как синтаксический анализ аргументов, переменные TLS и т. Д. Кроме того, сравните размер двоичных файлов, и вы увидите около 4 КБ против 30-90 кб.