我尝试在汇编中编写 pong 以更好地了解我的电脑中实际发生的情况
我已经禁用了我的AV,这会将其标记为有害,并在禁用AV的情况下重新启动我的电脑,并且代码之前可以工作,我没有更改任何内容。它可能是由于一些愚蠢的疏忽,但作为一个通常的高级程序员,代码在重新启动我的电脑后就停止工作,这真的很奇怪。我没有收到任何有关的错误。
我明白了
hello.asm(51):警告 A6001:过程没有返回
这是一个错误,但我之前可以忽略它,它会编译,就像我之前说的那样。
.386
.model flat, stdcall
option casemap:none
include C:\MASM32\include\masm32rt.inc
includelib user32.lib
includelib kernel32.lib
.data
txClass db "MyWinClass", 0
wcx WNDCLASSEX <WNDCLASSEX, CS_HREDRAW or CS_VREDRAW, WndProc, 0, 0, 1, 2, 3, COLOR_BTNFACE+1, 0, txClass, 4>
rect RECT <20, 0, 40, 100> ; Rectangle to hold the client area dimensions
ball RECT <200, 200, 210,210> ; Rectangle to hold the client area dimensions
ballMX DWORD 5
ballMY DWORD 5
.data? ; uninitialised data - use for handles etc
hMenu dd ?
ps PAINTSTRUCT<?>
dwStartTime DWORD ?
dwElapsedTime DWORD ?
hWnd2 DWORD ?
.code
WinMain proc uses ebx
LOCAL msg:MSG
mov ebx, offset wcx
wc equ [ebx.WNDCLASSEX]
mov wc.hInstance, rv(GetModuleHandle, 0)
mov wc.hIcon, rv(LoadIcon, NULL, IDI_APPLICATION)
mov wc.hIconSm, eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx, NULL, wc.lpszClassName, chr$("Pong"),
WS_OVERLAPPEDWINDOW or WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, wc.hInstance, NULL
mov hWnd2, eax
invoke SetTimer, hWnd2, 1, 8, NULL
.While 1
invoke GetMessage, ADDR msg, NULL, 0, 0
.Break .if !eax
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.Endw
exit msg.wParam
WinMain endp
WndProc proc uses esi edi ebx hWnd, uMsg, wParam:WPARAM, lParam:LPARAM
LOCAL hdc: HDC
SWITCH uMsg
CASE WM_CREATE
ret
CASE WM_KEYDOWN
mov eax, wParam
SWITCH eax
CASE VK_S
add dword ptr [rect.top], 5
add dword ptr [rect.bottom], 5
CASE VK_W
sub dword ptr [rect.top], 5
sub dword ptr [rect.bottom], 5
ret
ret
ENDSW
invoke InvalidateRect, hWnd, NULL, TRUE ; Force the window to repaint
ret
CASE WM_TIMER
push ebx
mov eax, ball.bottom
mov ebx, ps.rcPaint.bottom
cmp eax,ebx
jb cont
neg ballMY
cont:
mov eax,ballMY
add ball.top, eax
add ball.bottom, eax
xor ebx, ebx
mov eax, ball.right
mov ebx, ps.rcPaint.right
cmp eax,ebx
jb cont2
neg ballMX
cont2:
mov eax,ballMX
add ball.left, eax
add ball.right, eax
pop ebx
invoke InvalidateRect, hWnd, NULL, TRUE ; Request a repaint
CASE WM_PAINT
invoke BeginPaint, hWnd, ADDR ps ; Start painting the window
mov hdc, eax ; Store the device context handle
invoke CreateSolidBrush, 0000000
invoke FillRect, hdc, ADDR ps.rcPaint, eax
invoke CreateSolidBrush, 0FFFFFFh
invoke FillRect, hdc, ADDR rect, eax
invoke CreateSolidBrush, 0FFFFFFh
invoke FillRect, hdc, ADDR ball, eax
invoke EndPaint, hWnd, ADDR ps ; End painting
ret
CASE WM_DESTROY
invoke PostQuitMessage, NULL
ENDSW
invoke DefWindowProc, hWnd, uMsg, wParam, lParam
ret
WndProc endp
end WinMain
RegisterClassEx
失败了
invoke RegisterClassEx, addr wc
用新代码替换了原始代码,用所需变量填充 WNDCLASSEX 结构。
运行代码会产生此窗口
pong.asm
.386
.model flat, stdcall
option casemap:none
include C:\MASM32\include\masm32rt.inc
includelib user32.lib
includelib kernel32.lib
.data
txClass db "MyWinClass", 0
rect RECT <20, 0, 40, 100> ; Rectangle to hold the client area dimensions
ball RECT <200, 200, 210,210> ; Rectangle to hold the client area dimensions
ballMX DWORD 5
ballMY DWORD 5
.data? ; uninitialised data - use for handles etc
hMenu dd ?
ps PAINTSTRUCT<?>
dwStartTime DWORD ?
dwElapsedTime DWORD ?
hWnd2 DWORD ?
.code
WinMain proc hInst :DWORD,
hPrevInst :DWORD,
CmdLine :DWORD,
CmdShow :DWORD
;====================
; Put LOCALs on stack
;====================
LOCAL wc :WNDCLASSEX
LOCAL msg :MSG
LOCAL Wwd :DWORD
LOCAL Wht :DWORD
LOCAL Wtx :DWORD
LOCAL Wty :DWORD
;==================================================
; Fill WNDCLASSEX structure with required variables
;==================================================
mov wc.cbSize, sizeof WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW \
or CS_BYTEALIGNWINDOW
mov wc.lpfnWndProc, offset WndProc
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
m2m wc.hInstance, hInst ;<< NOTE: macro not mnemonic
mov wc.hbrBackground, COLOR_BTNFACE+1
mov wc.lpszMenuName, NULL
mov wc.lpszClassName, offset txClass
invoke LoadIcon,hInst,500 ; icon ID
mov wc.hIcon, eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor, eax
mov wc.hIconSm, 0
invoke RegisterClassEx, ADDR wc
test eax, eax
jnz regOk
invoke MessageBox,0,SADD("RegistrationFailed"),
SADD("Oops"),
MB_OK or MB_ICONINFORMATION
jmp done
regOk:
invoke CreateWindowEx, NULL, wc.lpszClassName, chr$("Pong"),
WS_OVERLAPPEDWINDOW or WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, wc.hInstance, NULL
mov hWnd2, eax
invoke ShowWindow,hWnd2,SW_SHOWNORMAL
invoke UpdateWindow,hWnd2
invoke SetTimer, hWnd2, 1, 8, NULL
.While 1
invoke GetMessage, ADDR msg, NULL, 0, 0
.Break .if !eax
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.Endw
done:
exit msg.wParam
WinMain endp
WndProc proc uses esi edi ebx hWnd, uMsg, wParam:WPARAM, lParam:LPARAM
LOCAL hdc: HDC
SWITCH uMsg
CASE WM_CREATE
ret
CASE WM_KEYDOWN
mov eax, wParam
SWITCH eax
CASE VK_S
add dword ptr [rect.top], 5
add dword ptr [rect.bottom], 5
CASE VK_W
sub dword ptr [rect.top], 5
sub dword ptr [rect.bottom], 5
ret
ret
ENDSW
invoke InvalidateRect, hWnd, NULL, TRUE ; Force the window to repaint
ret
CASE WM_TIMER
push ebx
mov eax, ball.bottom
mov ebx, ps.rcPaint.bottom
cmp eax,ebx
jb cont
neg ballMY
cont:
mov eax,ballMY
add ball.top, eax
add ball.bottom, eax
xor ebx, ebx
mov eax, ball.right
mov ebx, ps.rcPaint.right
cmp eax,ebx
jb cont2
neg ballMX
cont2:
mov eax,ballMX
add ball.left, eax
add ball.right, eax
pop ebx
invoke InvalidateRect, hWnd, NULL, TRUE ; Request a repaint
CASE WM_PAINT
invoke BeginPaint, hWnd, ADDR ps ; Start painting the window
mov hdc, eax ; Store the device context handle
invoke CreateSolidBrush, 0000000
invoke FillRect, hdc, ADDR ps.rcPaint, eax
invoke CreateSolidBrush, 0FFFFFFh
invoke FillRect, hdc, ADDR rect, eax
invoke CreateSolidBrush, 0FFFFFFh
invoke FillRect, hdc, ADDR ball, eax
invoke EndPaint, hWnd, ADDR ps ; End painting
ret
CASE WM_DESTROY
invoke PostQuitMessage, NULL
ENDSW
invoke DefWindowProc, hWnd, uMsg, wParam, lParam
ret
WndProc endp
end WinMain
C:\masm32\tools
和C:\masm32\examples
中有很多示例使用此代码正确注册Windows类
RegisterWinClass proc lpWndProc:DWORD, lpClassName:DWORD,
Icon:DWORD, Cursor:DWORD, bColor:DWORD
LOCAL wc:WNDCLASSEX
mov wc.cbSize, sizeof WNDCLASSEX
mov wc.style, CS_BYTEALIGNCLIENT or \
CS_BYTEALIGNWINDOW
m2m wc.lpfnWndProc, lpWndProc
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
m2m wc.hInstance, hInstance
m2m wc.hbrBackground, bColor
mov wc.lpszMenuName, NULL
m2m wc.lpszClassName, lpClassName
m2m wc.hIcon, Icon
m2m wc.hCursor, Cursor
m2m wc.hIconSm, Icon
invoke RegisterClassEx, ADDR wc
ret
RegisterWinClass endp