注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

★ ★ ★ 卡多 - K.D

DELPHI

 
 
 

日志

 
 

第三课 经典汇编教程Win32Asm教程  

2011-01-02 12:36:46|  分类: ‖ 杂文 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
12.0-第一个程序 
是创建你的第一个程序的时候了。本章中的指导将这样组织: 
12.1-第一步 
如果万事具备,你应该在你的masm同一个区上有一个win32(或win32asm)目录。为每个工程,你应该创建一个子目录。 
在win32目录中创建一个名为“Firstprogram“的子目录。创建一个新的文本文件并重命名为“first.asm”。 
12.2-第二步 
在first.asm中输入一下代码: 
.486 
.model flat, stdcall 
option casemap:none 
incl?lib \masm32\lib\kernel32.lib 
incl?lib \masm32\lib\user32.lib 
incl? \masm32\incl?\kernel32.inc 
incl? \masm32\incl?\user32.inc 
incl? \masm32\incl?\windows.inc 
因为现在,我们仅需要kernel32和user32两个dll。 
12.3-第三步 
我们将要创建著名的“Hello World”程序。要显示“hello World”字符串,我们要用消息对话框。消息对话框由MessageBox函数创建。你可以在《win32 程序员参考》(看第二章)中查找这个函数。这是书上说的: 
MessageBox函数创建,显示并操作消息对话框。消息对话框包含应用程序定义的消息和标题,加上任何预定义的图标与按钮的组合。 
int MessageBox( 
HWND hWnd, // handle of owner window 
LPCTSTR lpText, // address of text in message box 
LPCTSTR lpCaption, // address of title of message box 
UINT uType // style of message box 
); 
Parameters 
hWnd 
Identifies the owner window of the message box to be created. If this parameter is NULL, the message box has no owner window. 
lpText 
Points to a null-terminated string containing the message to be displayed. 
lpCaption 
Points to a null-terminated string used for the dialog box title. If this parameter is NULL, the default title Error is used. 
uType 
Specifies a set of bit flags that determine the contents and behavior of the dialog box. This parameter can be a combination of flags from the following groups of flags. 
[--SNIP--] 
在这段文字后有所有常数和标志的列表(他们定义在windows.inc中)。因为它太长了,我没有在这里列出来。通过查看参考,你就知道MessageBox函数要4个参数:父窗口(owner),指向消息串的指针,指向标题串的指针和消息框的类型。 
HWnd可以是Null。因为我们的程序没有窗口。 
LpText必须是指向我们文本的指针。这仅仅意为参数是文本所在内存地址的offset。 
LpCaption 是标题串的offset。 
UType 是参考中解释的像MB_OK,MB_OKCANCEL,MB_IConERROR等值的组合。 
让我们先定义两个用于MessageBox的字符串: 
在first.asm中加入: 
.data 
MsgText db "Hello world!",0 
MsgTitle db "This is a messagebox",0 
.data 指示data部分的开始。用db,字节直接被插入,而且字符串又只是字节的集合,data部分会在包含上面的字符串,附加上结尾的0。MsgText装有第一个字符串的offset。MsgTitle有第二个字符串的offset。现在我们可以使用函数: 
invoke MessageBox, NULL, offset MsgText, offset MsgTitle, Null 
但因为用的是invoke,你可以使用(更安全)ADDR代替offset: 
invoke MessageBox, Null, ADDR MsgText, ADDR MsgTitle, Null 
我们还没有看最后一个参数,但这不会有什么问题。因为MB_OK(有一个ok按钮的消息对话框的样式)等于0(NULL)。但你也可以使用其他的任何样式。Utype(第4个参数)的定义是: 
指定一系列决定对话框内容与行为的位标志。这个参数可以是下面标志组中标志的组合。 
现在以我们要一个有OK按钮与“information”图标的简单消息对话框为例。MB_OK是OK按钮的样 式,MB_ICONINFORMATION是information图标的样式。样式是用“or”操作符联合的。这不是or伪代码。Masm会在汇编前处 理or操作。不用or,你可以用+号(加号)代替,但有时对层叠样式有问题(一个样式包含其他一些样式)。但在本例中你也可以用+号。 
.code 
start: 
invoke MessageBox, NULL, ADDR MsgText, ADDR MsgTitle, MB_OK + MB_ICONINFORMATION 
end start 
把以上的代码加入到你的first.asm文件中。 
我们还加入了一个start标签。如果你现在汇编你的程序并运行它,它将显示一个消息对话框但很有可能在你点OK之后就崩溃了。这是因为程序没有结束,而处理器开始执行MessageBox代码后的任何东西。Windows中程序是用ExitProcess函数结束的: 
VOID ExitProcess( 
UINT xitCode //对于所有线程的退出代码 ); 
我们可以把0用作退出码。 
把你的代码改成这样: 
.code 
start: 
invoke MessageBox, NULL, ADDR MsgText, ADDR MsgTitle, MB_OK + MB_ICONINFORMATION 
invoke ExitProcess, NULL 
end start 
12.4-第4步 
因此我们最终的程序是: 
.486 
.model flat, stdcall 
option casemap:none 
incl?lib \masm32\lib\kernel32.lib 
incl?lib \masm32\lib\user32.lib 
incl? \masm32\incl?\kernel32.inc 
incl? \masm32\incl?\user32.inc 
incl? \masm32\incl?\windows.inc 
.data 
MsgText db "Hello world!",0 
MsgTitle db "This is a messagebox",0 
.code 
start: 
invoke MessageBox, NULL, ADDR MsgText, ADDR MsgTitle, MB_OK or MB_ICONINFORMATION 
invoke ExitProcess, NULL 
end start 
12.5-第5步 
现在我们将从源代码产生可执行文件。 
用一下内容新建一个文本文件并命名为make.bat: 
@echo off 
ml /c /coff first.asm 
link /s systemindows first.obj 
pause>nul 
解释: 
ml /c /coff first.asm 
Ml是宏汇编器(masm)。Masm将从程序创建原始代码。参数的意思是: /c =汇编不链接(因为我们用link.exe来做这项工作) /coff = 产生COFF格式的object(对象)文件,这是Windows可执行文件的标准格式。 first.asm = a汇编first.asm文件 
link /s systemindows first.obj 
链接器把object文件和所有导入的dll与库链接起来: /s systemindows = 创建Windows的可执行文件。 first.obj = 链接 first.obj 
如果你把所有的事情都正确的完成了,并运行批处理文件。将产生first.exe。运行它,看看有什么结果。 
13.0-Windows中的窗口 
在本章中,我们将创建一个有窗口的程序 
13.1-窗口 
你可能已经猜到了Windows之所以称为Windows的原因了。在Windows中,有两种程序:GUI程序和控制台程序。控制台模式的程序 看上去就像Dos程序,它们在一个似-dos的窗口中运行。你使用的大多数程序是GUI(图形用户界面)程序,它们有一个用于和用户交互的图形界面。这是 由创建窗口来完成的。几乎你在Windows中看见的每一件东西都是窗口。首先,你创建一个父窗口,然后是像编辑框,静态控件(文本标签-译者注),按钮 等的自窗口(控件)。 
13.2-窗口类 
每一个窗口都有名字。你为你的父窗口定义你自有的类。对于控件,你可以使用Windows的标准类名(例如,“Edit”,“Static”,“Button”) 
13.3-结构 
你程序中的窗口类是用“RegisterClassEx“函数注册的。(RegisterClassEx是RegisterClass的扩展版本,后者已经不太使用了)这个函数的声明是: 
ATOM RegisterClassEx( 
CONST WNDLCASSEX *lpwcx//有类数据的结构之地址 
); 
lpwcx:指向WNDCLASSEX结构。在把它传递给函数之前,你必须用适当的类属性填写结构。 
唯一的参数是指向结构的指针。先来看看一些结构的基本知识: 
一个结构是一些变量(数据)的集合。它用STR T定义: 
SOMESTR TURE STR T 
dword1 dd ? 
dword2 dd ? 
some_word dw ? 
abyte db ? 
anotherbyte db ? 
SOMESTR TURE ENDS 
(结构名不一定要大写) 
你可以用问号把你的变量定义在未初始化data部分。现在你可以根据定义创建一个结构: 
Initialized 
Initializedstr ture SOMESTR TURE <100,200,10,'A',90h> 
Uninitialized 
UnInitializedstr ture SOMESTR TURE <> 
在第一个例子中,创建了一个新的结构(用初始化了的结构保存它的offset),而且结构的每一个元素用初始化数值填写了。第二个例子只是告诉masm为结构名分配内存,而且每个数据元素用0初始化。在创建了结构之后,你可以在代码中使用它: 
mov eax, Initializedstr ture.some_word 
; eax现在是 10 
inc UnInitializedstr ture.dword1 
; 结构的dword1步增 
结构是这样存在内存中的: 
内存地址 内容 
offset of Initializedstr ture 100 (dword, 4 bytes) 
offset of Initializedstr ture + 4 200 (dword, 4 bytes) 
offset of Initializedstr ture + 8 10 (word, 2 bytes) 
offset of Initializedstr ture + 10 65 or 'A' (1 byte) 
offset of Initializedstr ture + 11 90h (1 byte) 
12.3-WNDCLASSEX 
现在已经了解了足够多的结构知识,让我们处理RegisterClassEx吧。在《win32程序员参考》中,你可以查找WNDCLASSEX结构的定义。 
typedef str t _WNDCLASSEX { // 
UINT cbSize; 
UINT style; 
WNDPROC lpfnWndProc; 
int cbClsExtra; 
int cbWndExtra; 
HANDLE hInstance; 
HICON hIcon; 
HCURSOR hCursor; 
HBRUSH hbrBackground; 
LPCTSTR lpszMenuName; 
LPCTSTR lpszClassName; 
HICON hIconSm; 
} WNDCLASSEX; 
解释 
cbSize 
WNDCLASSEX结构体的大小。用于Windows的认证。你可以用SIZEOF得到它的大小: mov wc.cbsize, SIZEOF WNDCLASSEX 
style 
为类指定一个样式(如果窗口要有滚动条,加上重画标志。等等) 
lpfnWndProc 
指向Windows Procedure的指针(本章后面有更多内容) 
cbClsExtra 
在Windows类结构后本配多少额外内存。对我们不重要 
cbWndExtra 
在Windows实例后分配多少额外内存。对我们也不重要 
hInstance 
你程序的实力句柄。你可以用GetMo leHandle函数得到这个句柄 
hIcon 
窗口图标资源的句柄 
hCursor 
窗口光标资源的句柄 
hbrBackground 
用于填充背景的画刷句柄,或是标准刷子类型中的一个,如 COLOR_WINDOW, COLOR_BTNFACE , COLOR_BACKGROUND. 
lpszMenuName 
指向一个指定菜单类名的零结尾字符串 
lpszClassName 
指向一个指定窗口类名的零结尾字符串 
hIconSm 
一个和窗口类关联的小图标句柄 
在你的Win32文件夹中创建一个名为firstWindow的文件夹并在这个文件夹中创建一个名为window.asm的新文件,输入一下内容: 
.486 
.model flat, stdcall 
option casemap:none 
incl?lib \masm32\lib\kernel32.lib 
incl?lib \masm32\lib\user32.lib 
incl?lib \masm32\lib\gdi32.lib 
incl? \masm32\incl?\windows.inc 
incl? \masm32\incl?\kernel32.inc 
incl? \masm32\incl?\user32.inc 
incl? \masm32\incl?\gdi32.inc 
然后创建一个名为make.bat的.bat文件。把这些文本粘贴进去: 
@echo off 
ml /c /coff window.asm 
link /s systemindows window.obj 
pause>nul 
从现在开始,为了节省空间,仅显示小段的代码。你可以通过点来显示教程此处的全部代码。完整的代码在新窗口中显示。 
译者注:为了方便,我又把这些放回来了。 
13.4-注册类 
现在我们在名为WinMain的过程中注册类。该过程中完成窗口的初始化。 
把这些加入你的汇编文件: 
WinMain PROTO STDCALL WORD, WORD, WORD 
.data? 
hInstance dd ? 
.code 
invoke GetModuleHandle, NULL 
mov hInstance, eax 
invoke WinMain, hInstance, NULL, NULL, SW_SHOWNORMAL 
end start 
这些代码通过GetModuleHandle得到模块句柄,并把模块句柄放入hInstance变量中。这个句柄在Windows API中频繁使用。然后它调用WinMain过程。这不是一个API函数,而是一个我们将要定义的过程。原型是:WinMain PROTO STDCALL WORD, WORD, WORD, WORD,因而是一个带4个参数的函数: 
现在把这些代码放在end start:前 
WinMain proc hInstWORD, hPrevInstWORD, CmdLineWORD, CmdShowWORD 
ret 
WinMain endp 
你根本就不需要用这个winmain过程,但这是一种十分普遍的处世化你的程序的方法。Vis l C自动初始化这个函数的参数,但我们必须自己来做。现在不要管hPrevInst和CmdLine。集中注意在hInst和CmdShow上。Hinst 是实例句柄(=模块句柄),CmdShow是定义窗口该如何显示的标志。(你可以在API参考关于ShowWindows部分发现更多) 
在前面代码中的"invoke WinMain, hInstance, NULL, NULL, SW_SHOWNORMAL"用正确的实例句柄和显示标志调用这个函数。现在我们可以在WinMain中写我们的初始化代码了。 
WinMain proc hInstWORD, hPrevInstWORD, CmdLineWORD, CmdShowWORD 
LOCAL wc:WNDCLASSEX 
LOCAL hwndWORD 
ret 
WinMain endp 
这有我们将在过程中要用的两个局部变量 
.data 
ClassName db "FirstWindowClass",0 
.code 
WinMain proc hInstWORD, hPrevInstWORD, CmdLineWORD, CmdShowWORD 
LOCAL wc:WNDCLASSEX 
LOCAL hwndWORD 
; now set all the str ture members of the WNDCLASSEX str ture wc: 
mov wc.cbSize,SIZEOF WNDCLASSEX 
mov wc.style, CS_HREDRAW or CS_VREDRAW 
mov wc.lpfnWndProc, OFFSET WndProc 
mov wc.cbClsExtra,NULL 
mov wc.cbWndExtra,NULL 
push hInst 
pop wc.hInstance 
mov wc.hbrBackground,COLOR_WINDOW 
mov wc.lpszMenuName,NULL 
mov wc.lpszClassName,OFFSET ClassName 
invoke LoadIcon,NULL,IDI_APPLICATION 
mov wc.hIcon, eax 
mov wc.hIconSm, eax 
invoke LoadCursor,NULL,IDC_ARROW 
mov wc.hCursor,eax 
invoke RegisterClassEx, ADDR wc 
ret 
WinMain endp 
让我们来看看发生了什么: 
mov wc.cbSize,SIZEOF WNDCLASSEX 
mov wc.style, CS_HREDRAW or CS_VREDRAW 
mov wc.lpfnWndProc, OFFSET WndProc 
mov wc.cbClsExtra,NULL 
mov wc.cbWndExtra,NULL 
初始化了结构的大小(这是RegisterClassEx要求的)。设置类的样式为”CS_HREDRAW or CS_VREDRAW”,然后设置了窗口过程的offset。你在后面会知道什么是窗口过程,现在你仅需要记住你需要WndProc过程的地址。该地址可 以通过“offset WndProc”获得。Cb.ClsExtra和cb.WndExtra我们没有使用因而设它们为Null。 
Push hInst 
Pop wc.hInstance 
Wc.hInstance设为WinMain的hInst参数。为什么我们不用:mov wc.hInstance, hInst?因为mov指令不允许从一个地址移到另一个地址。通过push/pop,值被压入栈,然后又弹入目标中。 
mov wc.hbrBackground, COLOR_WINDOW 
mov wc.lpszMenuName, NULL 
mov wc.lpszClassName, OFFSET ClassName 
类的背景色被设为COLOR_WINDOW,没有定义菜单(null)而且lpszClassName设为一个指向零结尾的类名字符串:“FirstWindowClass”它应该是一个在你的程序中定义的唯一名字。 
invoke LoadIcon, NULL, IDI_APPLICATION 
mov wc.hIcon, eax 
mov wc.hIconSm, eax 
窗口需要一个图标。但又因为我们要一个指向图标的句柄,我们使用LoadIcon来载入图标并获得句柄。LoadIcon有两个参 数:hInstance和lpIconName。HInstance是包含图标的可执行文件的模块句柄。LpIconName是一个指向图标资源和图标 ID的字符串的指针。如果你用NULL为hInstance,你可以从一些标准图表中选这一个(这却是是因为我们在这里还没有图标资源)hIconSm是 小图标,你可以对它使用相同的句柄。 
invoke LoadCursor,NULL,IDC_ARROW 
mov wc.hCursor,eax 
对光标也一样。NULL作hInstance,并用一个标准光标类型:IDC_ARROW,标准Windows箭头型光标。 
invoke RegisterClassEx, ADDR wc 
现在,最终用RegisterClassEx来注册类,通过一个指向WNDCLASSEX结构的指针作参数。 
13.5-创建窗口 
现在,你已经注册了一个类,你可以使用它创建一个窗口: 
HWND CreateWindowEx( 
DWORD dwExStyle, // extended window style 
LPCTSTR lpClassName, // pointer to registered class name 
LPCTSTR lpWindowName, // pointer to window name 
DWORD dwStyle, // window style 
int x, // horizontal position of window 
int y, // vertical position of window 
int nWidth, // window width 
int nHeight, // window height 
HWND hWndParent, // handle to parent or owner window 
HMENU hMenu, // handle to menu, or child-window identifier 
HINSTANCE hInstance, // handle to application instance 
LPVOID lpParam // pointer to window-creation data 
); 
DwExstyle和dwStyle是两个决定窗口样式的参数。 
LpClassName 是一个指向你注册了的类名的指针。 
LpWindowName 是你窗口的名字(如果有的话,这将成为你窗口的标题) 
X, Y, nWidth, nHeight 决定你窗口的位置和大小 
HMenu 是菜单窗口的句柄(在后面讨论,现在为空) 
HInstance 是程序实例的句柄 
LpPararm 是你能在你的程序中使用的扩展值 
.data 
AppName "FirstWindow",0 
.code 
INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\ 
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\ 
CW_USEDEFAULT,400,300,NULL,NULL,\ 
hInst,NULL 
mov hwnd, eax 
invoke ShowWindow, hwnd, SW_SHOWNORMAL 
invoke UpdateWindow, hwnd 
(注意\使汇编器读下一行的时候好像还在同一行) 
我们的代码将用我们刚刚注册的类名创建一个新的窗口。标题是“FirstWindow”(程序名,AppName),样式是 WS_OVERLAPPEDWINDOW,这是一个创建有标题,系统菜单,可缩放边框和最大化/最小化按钮的窗口样式。CW_USERDEFAULT作为 x和y的位置会使Windows为新窗口使用缺省位置。窗口的(初始)大小是400×300象素。 
函数的返回值是窗口句柄,HWND。它储存在局部变量hwnd中。然后窗口用ShowWindow显示。UpdateWindow确保窗口被画出。 
13.6-消息循环 
窗口可以通过消息和你的程序以及其他窗口通讯。无论何时,一条消息被发送给指定的窗口。它的窗口过程都要被调用。每个窗口都有一个消息循环或消息 泵(pump)。这是一个无止尽的检查是否给有你的窗口的消息的循环。而且如果有,把消息传递给dispatchMessage函数。这个函数会调用你的 窗口过程。消息循环和窗口过程是两个完全不同的东西!!! 
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShowWORD 
LOCAL wc:WNDCLASSEX 
LOCAL hwndWORD 
LOCAL msg:MSG ;<< 
........ 
.WHILE TR 
invoke GetMessage, ADDR msg,NULL,0,0 
.BREAK .IF (!eax) 
invoke TranslateMessage, ADDR msg 
invoke DispatchMessage, ADDR msg 
.ENDW 
这是消息循环看上去的样子。.WHILE TR, .ENDW循环到eax为0之前都会继续。如果它接到了WM_QUIT消息,GetMessage返回0,这将关闭窗口因而程序应该在不论 GetMessage返回0时退出。如果不是这样(0),消息被传递给TranslateMessage(这个函数把按键翻译为消息)而且消息被 Windows用DispatchMessage函数解包。消息本身在一个消息循环的组成部分MSG结构中(LOCAL msg: MSG被加入过程,增加了一个称为msg的局部消息结构)你可以在你的所有程序中用这个消息循环。 
13.7-窗口过程 
消息会被发送往窗口过程。一个窗口过程看上去总是这样: 
WndProc PROTO STDCALL WORD, WORD, WORD, WORD 
.code 
WndProc proc hWndWORD, uMsgWORD, wParamWORD, lParamWORD 
mov eax, uMsg 
.IF eax==XXXX 
.ELSEIF eax==XXXX 
.ELSE 
invoke DefWindowProc, hWnd, uMsg, wParam, lParam 
.ENDIF 
ret 
WndProc endp 
窗口过程总是有4个参数 
hWnd 包含窗口句柄 
uMsg 消息 
wParam 消息的第一个参数(由消息定义) 
lParam 消息的第二个参数(由消息定义) 
窗口不处理的消息应该传递给DefWindowProc,它会处理这些。一个窗口过程的例子: 
WndProc proc hWndWORD, uMsgWORD, wParamWORD, lParamWORD 
mov eax, uMsg 
.IF eax==WM_CREATE 
invoke MessageBox, NULL, ADDR AppName, ADDR AppName, NULL 
.ELSEIF eax==WM_DESTROY 
invoke PostQuitMessage, NULL 
.ELSE 
invoke DefWindowProc, hWnd, uMsg, wParam, lParam 
.ENDIF 
ret 
WndProc endp 
这段代码在窗口初始化时显示程序名称。也要注意我加入了WM_DESTROY消息的处理。这条消息在窗口将要关闭的时候发送。程序要用PostQuitMessage作出反应。 
现在看看最终的代码: 
.486 
.model flat, stdcall 
option casemap:none 
incl?lib \masm32\lib\kernel32.lib 
incl?lib \masm32\lib\user32.lib 
incl?lib \masm32\lib\gdi32.lib 
incl? \masm32\incl?\windows.inc 
incl? \masm32\incl?\kernel32.inc 
incl? \masm32\incl?\user32.inc 
incl? \masm32\incl?\gdi32.inc 
WinMain PROTO STDCALL WORD, WORD, WORD, WORD 
WndProc PROTO STDCALL WORD, WORD, WORD, WORD 
.data? 
hInstance dd ? 
.data 
ClassName db "FirstWindowClass",0 
AppName db "FirstWindow",0 
.code 
start: 
invoke GetModuleHandle, NULL 
mov hInstance, eax 
invoke WinMain, hInstance, NULL, NULL, SW_SHOWNORMAL 
invoke ExitProcess, NULL 
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShowWORD 
LOCAL wc:WNDCLASSEX 
LOCAL hwndWORD 
LOCAL msg:MSG 
mov wc.cbSize,SIZEOF WNDCLASSEX 
mov wc.style, CS_HREDRAW or CS_VREDRAW 
mov wc.lpfnWndProc, OFFSET WndProc 
mov wc.cbClsExtra,NULL 
mov wc.cbWndExtra,NULL 
push hInst 
pop wc.hInstance 
mov wc.hbrBackground,COLOR_WINDOW 
mov wc.lpszMenuName,NULL 
mov wc.lpszClassName,OFFSET ClassName 
invoke LoadIcon,NULL,IDI_APPLICATION 
mov wc.hIcon, eax 
mov wc.hIconSm, eax 
invoke LoadCursor,NULL,IDC_ARROW 
mov wc.hCursor,eax 
invoke RegisterClassEx, addr wc 
INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\ 
WS_OVERLAPPEDWINDOW-WS_SIZEBOX-WS_MAXIMIZEBOX,CW_USEDEFAULT,\ 
CW_USEDEFAULT,400,300,NULL,NULL,\ 
hInst,NULL 
mov hwnd,eax 
invoke ShowWindow, hwnd,SW_SHOWNORMAL 
invoke UpdateWindow, hwnd 
.WHILE TR 
invoke GetMessage, ADDR msg,NULL,0,0 
.BREAK .IF (!eax) 
invoke TranslateMessage, ADDR msg 
invoke DispatchMessage, ADDR msg 
.ENDW 
mov eax,msg.wParam 
ret 
WinMain endp 
WndProc proc hWndWORD, uMsgWORD, wParamWORD, lParamWORD 
mov eax, uMsg 
.IF eax==WM_CREATE 
invoke MessageBox, NULL, ADDR AppName, ADDR AppName, NULL 
.ELSEIF eax==WM_DESTROY 
invoke PostQuitMessage, NULL 
.ELSE 
invoke DefWindowProc, hWnd, uMsg, wParam, lParam 
.ENDIF 
ret 
WndProc endp 
end start 
--
I like FreeBsD..
  评论这张
 
阅读(117)| 评论(1)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017