我在WindowPaint事件中调用BeginPaint(hWnd,lpPaint)时遇到问题。似乎函数BeginPaint覆盖了堆栈。
一个小C程序告诉我PAINTSTRUCT(lpPaint)的大小应该是34。 如果我把这个地址放到EBP-34或更多的EBP-56作为lpPaint的返回值,它会崩溃。如果我允许很多堆栈并将返回地址放到EBP-170上就可以了。
简单代码:
;Note : All Win32 API functions preserve the EBP, EBX, ESI, and EDI registers
extern GetModuleHandleA
extern ExitProcess
extern GetCommandLineA
extern RegisterClassExA
extern LoadIconA
extern LoadCursorA
extern CreateWindowExA
extern ShowWindow
extern UpdateWindow
extern MessageBoxA
extern GetMessageA
extern TranslateMessage
extern DispatchMessageA
extern PostQuitMessage
extern DefWindowProcA
extern DrawTextA
extern BeginPaint
extern EndPaint
import GetModuleHandleA kernel32.dll
import ExitProcess kernel32.dll
import GetCommandLineA kernel32.dll
import RegisterClassExA user32.dll
import LoadIconA user32.dll
import LoadCursorA user32.dll
import CreateWindowExA user32.dll
import ShowWindow user32.dll
import UpdateWindow user32.dll
import MessageBoxA user32.dll
import GetMessageA user32.dll
import TranslateMessage user32.dll
import DispatchMessageA user32.dll
import PostQuitMessage user32.dll
import DefWindowProcA user32.dll
import DrawTextA user32.dll
import BeginPaint user32.dll
import EndPaint user32.dll
section .text use32
..start:
;Handle from calling process
push dword 0
call [GetModuleHandleA]
mov dword [hInstance], eax
;Get command line
call [GetCommandLineA]
mov dword [commandLine], eax
;Main window
Call WindowMain
;Exit
Push eax
call [ExitProcess]
;========================================================================================
; Create a main windows
;========================================================================================
WindowMain:
push ebp
mov ebp, esp
;Local variable
;==============
;EBP-48 = WNDCLASSEX Structure 48 bytes
;EBP-72 = MSG 24 bytes
;EBP-76 = HWND, handle of our window 4 bytes
sub esp, 76
lea ebx, [ebp-48] ;EBX is now address of WNDCLASSEX
;WNDCLASSEX Structure : http://msdn.microsoft.com/en-us/library/ms633577(v=vs.85).aspx
mov dword [ebx+00], 48 ;Size of the structure
mov dword [ebx+04], 3 ;Style of the window
mov dword [ebx+08], WindowProcedure ;Callback function for events
mov dword [ebx+12], 0
mov dword [ebx+16], 0
mov dword [ebx+20], hInstance ;Handle to the window
;[ebx+24] = HICON
;[ebx+28] = HCURSOR
mov dword [ebx+32], 6 ;Background brush
mov dword [ebx+36], 0 ;Menu name NULL
mov dword [ebx+40], ClassName ;Class name for the window
;[ebx+44] = HICON
;LoadIconA(0, IDI_APPLICATION);
push 32512
push 0
call [LoadIconA]
mov dword [ebx+24], eax ;Icon for our window
mov dword [ebx+44], eax ;Small icon for our window
;LoadCursorA(0, IDC_ARROW);
push dword 32512
push 0
call [LoadCursorA]
mov dword [ebx+28], eax
;RegisterClassExA(WNDCLASSEX address);
push ebx
call [RegisterClassExA]
;CreateWindowEx(0, ClassName, window title, WS_OVERLAPPEDWINDOW, x, y, width, height, handle to parent window, handle to menu, hInstance, NULL);
push 0
push hInstance
push 0
push 0
push 400 ;High
push 500 ;Wide
push dword 0x80000000 ;CW_USEDEFAULT
push dword 0x80000000 ;CW_USEDEFAULT
;WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX
push dword 0x00 | 0xC00000 | 0x80000 | 0x40000 | 0x20000 | 0x10000 ;WS_OVERLAPPEDWINDOW
push dword ApplicationName
push dword ClassName
push dword 0
call [CreateWindowExA]
mov dword [ebp-76], eax ;Handle of our window
cmp eax, 0
jz .newWindowsFailed
;ShowWindow(hWind, SW_SHOWDEFAULT);
push dword 10
push dword [ebp-76]
call [ShowWindow]
;UpdateWindow(hWind);
push dword [ebp-76]
call [UpdateWindow]
.MessageLoop:
;GetMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
push dword 0
push dword 0
push dword 0
lea ebx, [ebp-72]
push ebx
call [GetMessageA]
cmp eax, 0 ;WM_QUIT
jz .MessageLoopExit
;TranslateMessage(lpMsg);
lea ebx, [ebp-72]
push ebx
call [TranslateMessage]
;DispatchMessageA(lpMsg);
lea ebx, [ebp-72]
push ebx
call [DispatchMessageA]
jmp .MessageLoop
.MessageLoopExit:
jmp .finish
.newWindowsFailed:
push dword 0
push dword 0
push errMsg
push 0
call [MessageBoxA]
mov eax, 1 ;Return error
mov esp, ebp
pop ebp
ret
.finish:
mov esp, ebp
pop ebp
ret
;========================================================================================
; Handle the events that our window sends us.
;========================================================================================
;LRESULT CALLBACK WindowProc(
; _In_ HWND hwnd,
; _In_ UINT uMsg,
; _In_ WPARAM wParam,
; _In_ LPARAM lParam
;);
;========================================================================================
WindowProcedure:
push ebp
mov ebp, esp
;Local variable
;==============
;EBP-56 = PAINTSTRUCT <- RECALCULER LA TAILLE DE LA STUCTURE!!!
;EBP-60 = HDC
;EBP-76 = RECT
sub esp, 170
mov eax, dword [ebp+12] ;uMsg
cmp eax, 2 ;WM_DESTROY
jz .WindowDestroy
cmp eax, 0X0F ;WM_PAINT
jz .WindowPaint
.WindowDefault:
push dword [ebp+20]
push dword [ebp+16]
push dword [ebp+12]
push dword [ebp+08]
call [DefWindowProcA]
;The return value is from DefWindowProcA so we can't change EAX
mov esp, ebp
pop ebp
ret 16
.WindowDestroy:
;We pass 0 as an argument to the PostQuitMessage() function, to tell it
;to pass 0 as the value of wParam for the next message. At that point,
;GetMessage() will return 0, and the message loop will terminate.
;PostQuitMessage(nExitCode);
push dword 0
call [PostQuitMessage]
jmp .WindowProcedureFinish
.WindowPaint:
;BeginPaint(hWnd, lpPaint);
lea ebx, [ebp-34]
push ebx
push dword [ebp+8]
call [BeginPaint]
mov dword [ebp-60], eax ;Save device context
jmp .WindowProcedureFinish
.WindowProcedureFinish:
xor eax, eax
mov esp, ebp
pop ebp
ret 16
msgBox:
; MessageBoxA(0, msg1, title, 0);
push dword 0
push dword ClassName
push dword TextLabel
push dword 0
call [MessageBoxA]
ret
section .data
ClassName db "Main Window", 0
ApplicationName db "Win32 Assembler", 0
errMsg db "An error occured while making the new window.", 0
TextLabel db "Welcom to the main event!", 13, 10, 13, 10, 0
section .bss
hInstance resd 1
commandLine resd 1
编译:
nasm -fobj main.asm
alink -oPE main.obj -o main.exe
答案 0 :(得分:4)
一个小C程序告诉我PAINTSTRUCT(lpPaint)的大小 应该是34
真的?什么C编译器是???如果您在MSDN上查找PAINTSTRUCT
:
typedef struct tagPAINTSTRUCT {
HDC hdc;
BOOL fErase;
RECT rcPaint;
BOOL fRestore;
BOOL fIncUpdate;
BYTE rgbReserved[32];
} PAINTSTRUCT, *PPAINTSTRUCT;
hdc = 4个字节
fErase = 4个字节
rcPaint = RECT` = 16字节
fRestore = 4个字节
fIncUpdate = 4个字节
rgbReserved = 32个字节
和RECT
:
typedef struct _RECT {
LONG left;
LONG top;
LONG right;
LONG bottom;
} RECT, *PRECT;
所有这些加起来给你64个字节!
这就是[EBP-56]
不起作用的原因,但[EBP-170]
会起作用,为结构留出足够的空间。