WinMain入口点 - 汇编代码看起来好像没有传递给入口点的参数

时间:2014-09-23 22:09:27

标签: c winapi visual-c++ assembly entry-point

我正在玩Win32程序集。

我一直在努力处理汇编中的WinMain入口点一段时间了。对我而言,有一个奇怪的 - NASM和...之间的区别。 link.exe是由我手写的asm和MSVC提出的。

1)C(++)代码 - 只是另一个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)装配等效

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 ++版本
enter image description here

2)ASM版本:
enter image description here



现在,如果我们看一下堆栈窗口,看起来好像Windows实际上没有将正确的参数传递给我的汇编入口点。返回到ntdll之前只有两个垃圾整数,而不是C ++版本,其中存在所有四个参数。

这对我来说是一个问题,因为我想在(在另一个汇编程序中)获取入口点内的hInstance变量。使用[EBP+8]给了我上面提到的垃圾而不是正确的hInstance值。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:6)

C ++代码中的WinMain入口点由C运行时库调用,而不是由Windows调用。

实际的Win32入口点签名是

void __stdcall NoCRTMain(void);

您可以使用GetCommandLine获取命令行,如果需要将其转换为argc / argv格式,可以使用CommandLineToArgvW

您可以通过将参数设置为hInstance来调用GetModuleHandle来获取NULL。 (请注意,在Win32中,与16位Windows不同,HINSTANCEHMODULE是相同的。)

答案 1 :(得分:4)

这四个参数由运行时提供,而不是由操作系统提供。如果您将查看入口点上的[esp]值,则程序集版本将返回到kernel32,即操作系统,而C ++版本将返回到模块的运行时代码。

在真正的入口点打开带有OllyDbg的C ++版本,你会看到许多初始化代码,比如参数解析,TLS变量等。另外,比较二进制文件的大小,你会看到4 kb vs大约30-90 kb。