HITEA 版 (精华区)
发信人: hfl (凤凰·风中轻舞), 信区: HITEA
标 题: Win32汇编语言(五)
发信站: 哈工大紫丁香 (2002年04月02日21:20:29 星期二), 站内信件
五、显示一个窗口的Win32汇编语言程序
学习过Win32SDK编程的读者编写的第一个应用程序可能就是显示一个窗口的C语言
程序,笔者也编写了这样一个C语言程序,该程序文件名为SIMPLE.C,程序如下:
#include <windows.h>
static char szWindowClass[]="SIMPLE";
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM
lParam);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR
lpCmdLine,int nShowCmd)
{
WNDCLASSEXA wcex;
HWND hWnd;
MSG msg;
if(!hPrevInstance)
{
wcex.cbSize=sizeof(WNDCLASSEXA);
wcex.style=CS_HREDRAW|CS_VREDRAW;
wcex.cbClsExtra=0;
wcex.cbWndExtra=0;
wcex.lpfnWndProc=WndProc;
wcex.hInstance=hInstance;
wcex.hIcon=LoadIconA(hInstance,IDI_APPLICATION);
wcex.hCursor=LoadCursorA(0,IDC_ARROW);
wcex.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName=NULL;
wcex.lpszClassName=szWindowClass;
wcex.hIconSm=LoadIconA(hInstance,IDI_APPLICATION);
if(!RegisterClassExA(&wcex)) return FALSE;
}
hWnd=CreateWindowExA(0,szWindowClass,"SIMPLE",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
0,0,hInstance,NULL);
if(!hWnd) return FALSE;
ShowWindow(hWnd,nShowCmd);
UpdateWindow(hWnd);
while(GetMessageA(&msg,0,0,0))
{
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM
lParam)
{
HDC hDC;
PAINTSTRUCT ps;
switch(message)
{
case WM_PAINT:
hDC=BeginPaint(hWnd,&ps);
EndPaint(hWnd,&ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProcA(hWnd,message,wParam,lParam);
}
return -1;
}
本程序与一般的显示一个窗口的C语言程序基本相同,只是只使用ANSI字符集。现
在笔者用Win32汇编语言程序实现本程序的功能,程序如下:
包含文件(SIMPLE.INC):
UINT TYPEDEF DWORD
LONG TYPEDEF DWORD
LPSTR TYPEDEF PTR BYTE
LPCSTR TYPEDEF LPSTR
PVOID TYPEDEF PTR
LPVOID TYPEDEF PVOID
HANDLE TYPEDEF PVOID
HINSTANCE TYPEDEF HANDLE
HWND TYPEDEF HANDLE
HMENU TYPEDEF HANDLE
HDC TYPEDEF HANDLE
HGDIOBJ TYPEDEF HANDLE
HICON TYPEDEF HANDLE
HCURSOR TYPEDEF HANDLE
HBRUSH TYPEDEF HANDLE
tagWNDCLASSEXA STRUCT
cbSize UINT ?
style UINT ?
lpfnWndProc DWORD ?
cbClsExtra DWORD ?
cbWndExtra DWORD ?
hInstance DWORD ?
hIcon DWORD ?
hCursor DWORD ?
hbrBackground DWORD ?
lpszMenuName DWORD ?
lpszClassName DWORD ?
hIconSm DWORD ?
tagWNDCLASSEXA ENDS
WNDCLASSEXA TYPEDEF tagWNDCLASSEXA
tagPOINT STRUCT
x LONG ?
y LONG ?
tagPOINT ENDS
POINT TYPEDEF tagPOINT
tagMSG STRUCT
message UINT ?
wParam DWORD ?
lParam DWORD ?
time DWORD ?
pt POINT <>
tagMSG ENDS
MSG TYPEDEF tagMSG
LPMSG TYPEDEF PTR MSG
tagRECT STRUCT
left LONG ?
top LONG ?
right LONG ?
bottom LONG ?
tagRECT ENDS
RECT TYPEDEF tagRECT
tagPAINTSTRUCT STRUCT
hdc DWORD ?
fErase DWORD ?
rcPaint RECT <>
fRestore DWORD ?
fIncUpdate DWORD ?
rgbReserved BYTE 32 DUP(?)
tagPAINTSTRUCT ENDS
PAINTSTRUCT TYPEDEF tagPAINTSTRUCT
LPPAINTSTRUCT TYPEDEF PTR PAINTSTRUCT
NULL = 0
TRUE = 0ffffffffh
FALSE = 0
SW_SHOWDEFAULT = 10
CS_HREDRAW = 0002h
CS_VREDRAW = 0001h
IDI_APPLICATION = 32512
IDC_ARROW = 32512
COLOR_WINDOW = 5
WS_OVERLAPPEDWINDOW = 00cf0000h
CW_USEDEFAULT = 80000000h
WM_PAINT = 000fh
WM_DESTROY = 0002h
GetModuleHandleA PROTO stdcall, :LPCSTR
GetCommandLineA PROTO stdcall
ExitProcess PROTO stdcall, :UINT
LoadIconA PROTO stdcall, :HINSTANCE,:LPCSTR
LoadCursorA PROTO stdcall, :HINSTANCE,:LPCSTR
RegisterClassExA PROTO stdcall, :PTR WNDCLASSEXA
CreateWindowExA PROTO stdcall, :DWORD,:LPCSTR,:LPCSTR,:DWORD,:
DWORD,:DWORD,:DWORD,:DWORD,:HWND,:HMENU,:HINSTANCE,:LPVOID
ShowWindow PROTO stdcall, :HWND,:DWORD
UpdateWindow PROTO stdcall, :HWND
GetMessageA PROTO stdcall, :LPMSG,:HWND,:UINT,:UINT
TranslateMessage PROTO stdcall, :PTR MSG
DispatchMessageA PROTO stdcall, :PTR MSG
BeginPaint PROTO stdcall, :HWND,:LPPAINTSTRUCT
EndPaint PROTO stdcall, :HWND,:PTR PAINTSTRUCT
PostQuitMessage PROTO stdcall, :DWORD
DefWindowProcA PROTO stdcall, :HWND,:UINT,:DWORD,:DWORD
源程序(SIMPLE.ASM):
.386p
.MODEL flat,stdcall
INCLUDE SIMPLE.INC
WinMain PROTO stdcall, :HINSTANCE,:HINSTANCE,:LPSTR,:
DWORD
.STACK 4096
.DATA
WindowClass BYTE 'SIMPLE',0
WindowTitle BYTE 'SIMPLE',0
hInst1 HINSTANCE 0
lpCmdLine1 LPSTR 0
.CODE
_start:
INVOKE GetModuleHandleA,NULL
mov hInst1,eax
INVOKE GetCommandLineA
mov lpCmdLine1,eax
INVOKE WinMain,hInst1,NULL,lpCmdLine1,SW_SHOWDEFAULT
INVOKE ExitProcess,eax
WinMain PROC hInst:HINSTANCE,hPrevInst:HINSTANCE,lpCmdLine:LPSTR,
nShowCmd:DWORD
LOCAL wcex:WNDCLASSEXA
LOCAL hWnd:HWND
LOCAL msg:MSG
.IF !hPrevInst
mov wcex.cbSize,SIZEOF WNDCLASSEXA
mov wcex.style,CS_HREDRAW or CS_VREDRAW
mov wcex.cbClsExtra,0
mov wcex.cbWndExtra,0
mov wcex.lpfnWndProc,OFFSET WndProc
mov eax,hInst
mov wcex.hInstance,eax
INVOKE LoadIconA,hInst,IDI_APPLICATION
mov wcex.hIcon,eax
INVOKE LoadCursorA,0,IDC_ARROW
mov wcex.hCursor,eax
mov wcex.hbrBackground,COLOR_WINDOW+1
mov wcex.lpszMenuName,NULL
mov wcex.lpszClassName,OFFSET WindowClass
INVOKE LoadIconA,hInst,IDI_APPLICATION
mov wcex.hIconSm,eax
INVOKE RegisterClassExA,ADDR wcex
.IF !eax
mov eax,FALSE
ret
.ENDIF
.ENDIF
INVOKE CreateWindowExA,0,ADDR WindowClass,ADDR WindowTitle,
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
CW_USEDEFAULT,0,0,hInst,NULL
mov hWnd,eax
.IF !eax
mov eax,FALSE
ret
.ENDIF
INVOKE ShowWindow,hWnd,nShowCmd
INVOKE UpdateWindow,hWnd
.WHILE TRUE
INVOKE GetMessageA,ADDR msg,0,0,0
.BREAK .IF !eax
INVOKE TranslateMessage,ADDR msg
INVOKE DispatchMessageA,ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain ENDP
WndProc PROC hWnd:HWND,message:UINT,wParam:DWORD,lParam:DWORD
LOCAL hDC:HDC
LOCAL ps:PAINTSTRUCT
.IF message==WM_PAINT
INVOKE BeginPaint,hWnd,ADDR ps
mov hDC,eax
INVOKE EndPaint,hWnd,ADDR ps
mov eax,0
ret
.ELSEIF message==WM_DESTROY
INVOKE PostQuitMessage,0
mov eax,0
ret
.ELSE
INVOKE DefWindowProcA,hWnd,message,wParam,lParam
ret
.ENDIF
mov eax,0ffffffffh
ret
WndProc ENDP
PUBLIC _start
END
汇编连接本程序的命令如下:
ml /c /coff /Cp simple.asm
link /subsystem:windows /entry:_start simple.obj kernel32.lib user32.lib
gdi32.lib
运行汇编连接后生成的SIMPLE.EXE文件,屏幕上将显示出一个标准的窗口,窗口的
标题是“SIMPLE”。
学习过Win32SDK编程的读者都知道,Win32应用程序的入口点是WinMain函数,实际
上WinMain函数是被C语言的初始化和结束代码调用的,Win32应用程序的真正入口
点和DOS应用程序没有什么区别,都是在文件头中指定的应用程序起始点。Win32汇
编语言没有C语言的初始化和结束代码,必须自己编写初始化和结束代码调用
WinMain函数(过程),WinMain函数的原型是:
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR
lpCmdLine,int nShowCmd);
WinMain函数有4个参数,分别是:
hInstance——应用程序当前实例的句柄,可以通过调用GetModuleHandle函数获取。
hPrevInstance——应用程序前一个实例的句柄,Win32中当前地址空间中不会有应
用程序的其他实例在运行,该参数通常设置为NULL(提供该参数只是便于移植
Win16应用程序源程序)。
lpCmdLine——命令行参数,可以通过调用GetCommandLine函数获取。
nShowCmd——主窗口的显示状态,可以设置成SW_SHOWDEFAULT(缺省状态)。
本程序的初始化和结束代码如下:
INVOKE GetModuleHandleA,NULL
mov hInst1,eax
INVOKE GetCommandLineA
mov lpCmdLine1,eax
INVOKE WinMain,hInst1,NULL,lpCmdLine1,SW_SHOWDEFAULT
INVOKE ExitProcess,eax
Win32标准函数调用方式,函数返回值通过EAX寄存器返回。可见本程序的初始化和
结束代码很简单,只是调用GetModuleHandle函数获取应用程序当前实例的句柄,
调用GetCommandLine函数获取命令行参数,然后调用WinMain函数(过程),
WinMain函数返回后调用ExitProcess函数终止程序的执行。
将本程序与SIMPLE.C程序比较,可以看出程序结构十分相似,本程序大量使用了
MASM 6.0以上版本的汇编器提供的结构化汇编语言伪指令,并不比C语言麻烦多少。
--
◆◆◆◆◆◆◆━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━
┃ 你不在我身边 好冷 ┃
┃ 见不到你影子 会疼 ┃
┃ 从此我再不分夜晚白天 是雪地或冰天 ┃
┃ 就算伤心 我也要等 ┃
━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━◆◆◆◆◆◆◆
※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: 202.118.229.253]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:8.947毫秒