首页
社区
课程
招聘
我学Win32汇编―创建简单的窗口
发表于: 2005-1-14 22:28 4262

我学Win32汇编―创建简单的窗口

2005-1-14 22:28
4262
我学Win32汇编―创建简单的窗口的一点心得,大侠们就不用看了…..

                                           --------------大菜鸟YongPeng

.386                        ;386指令集(RING3层)3

.MODEL Flat,stdcall         ;内存寻址模式,参数传递约定(从右向左)

option casemap:none         ;区分标号的大小写

include \masm32\include\windows.inc         ;引入头文件

include \masm32\include\user32.inc          ;引入头文件

include \masm32\include\kernel32.inc        ;引入头文件

includelib \masm32\lib\user32.lib           ;引入库

includelib \masm32\lib\kernel32.lib         ;引入库

winmain proto:DWORD,:DWORD,:DWORD,:DWORD    ;WINODWS应用程序的入口点

.DATA                                       ;已初始化的变量(数据段)

ClassName db "我的第一个汇编小程序",0       ;WINDOWS类名

AppName db "汇编第一课",0                   ;窗口的名字

.DATA?                              ;未初始化的变量

hInstance HINSTANCE ?               ;代表应用程序的句柄

CommandLine LPSTR ?                 ;保存存从命令行传入的参数

.CODE                               ;代码段

start:                              ;程序代码的开始处

invoke GetModuleHandle,NULL         ;获取应用程序句柄,eax保存应用程序句柄 (eax保存返回值)

mov hInstance,eax                   ;将应用程序的名柄eax写入变量hinstance中

invoke GetCommandLine               ;调用API获取命令行参数

mov CommandLine,eax                 ;将命令行参入变量CommandLine

invoke WinMain,hInstance,NULL,CommandLine,SW_SHOWDEFAULT;调用程序入口函数,返回参数入eax

invoke ExitProcess,eax              ;程序结束时,把返回码传给windows

WinMain proc hInst:HINSTANCE,hprevInst:HINSTANCE,Cmdline:LPSTR,CmdShow:DWORD   ;WINDAIN定义

LOCAL wc:WNDCLASSEX                        ;为局部变量在堆栈中申请内存空间

LOCAL msg:MSG                              ;为局部变量在堆栈中申请内存空间

LOCAL hwnd:HWND                            ;为局部变量在堆栈中申请内存空间

mov wc.cbsize,SIZEOF WNDCLASSEX            ;WNDCLASSEX的大小

mov wc.style,CS_HREDRAW or CS_VREDRAW      ;派生窗口具有的风格

mov wc.lpfnWndProc,OFFSET Wndproc          ;窗口处理函数的指针

mov wc.cbClsExtra,NULL                     ;指定紧跟在窗口类结构后的附加字节数

mov wc.cbWndExtra,NULL                     ;指定紧跟在窗口事例后的附加字节数

push hInstance                             ;本模块的事例名柄

pop wc.hInstance                           ;???

mov wc.hbrBackground,COLOR_WINDOW+1        ;背景画刷的句柄

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.hCurcor,eax                         ;指向返回光标的名柄

invoke RegisterClassEx,addr wc             ;注册窗口类,(addr操作符用来把标号的变量传递给函数)

invoke CreateWindowEx,NULL,\               ;产生实际的窗口|(NULL)为没有附加窗口风格

               ADDR ClassName,\             ;ASCIIZ形式的窗口类名称的地址

               ADDR AppName,\               ;ASCIIZ开式的窗口名称的地址

               WS_OVERLAPPEDWINDOW,\        ;窗口的风格(这里是最为普遍的风格)

               CW_USEDEFAULT,\              ;指定窗口左上角以像素为单位的屏幕坐标位置(X)

               CW_USEDEFAULT,\              ;指定窗口左上角以像素为单位的屏幕坐标位置(Y)

               CW_USEDEFAULT,\              ;以像素为单位的窗口大小(宽)

               CW_USEDEFAULT,\              ;以像素为单位的窗口大小(高)

               NULL,\                       ;父窗口的句柄(NULL代表只有一个窗口)

               NULL,\                       ;WINDOWS菜单的名柄

               hInst,\                      ;产生该窗口的应用程序的实例名柄

               NULL                         ;指向欲传给窗口的结构体数据类型参数的指针

mov hwnd,eax                                ;调用成功后,eax为返回的窗口名柄,存入变量以备后用

invoke ShowWindow,hwnd,CmdShow              ;调用ShowWindow来按照我们希望的方式来显示窗口

invoke UpdateWindow,hwnd                    ;调用UpdateWindow来更新客户区

-------------------------这时候窗口已显示在屏幕上了--------------------------------------------

WHILE TRUE                                      ;

           Invoke GetMessage,ADDR msg,NULL,0,0  ;从调用线程的消息队列里取得一个消息并将其放于指定的结构(msg)

           .BREAK .IF(!eax)                      ;返回值如果不为0,程序继续顺序向下执行

           invoke TranslateMessage,ADDR msg      ;从键盘接受原始按键消息,后解释成WM_CHAR(含有按键的ASCII码)

           invoke DispatchMessage,ADDR msg       ;调度一个消息给负责该窗口过程的函数

.ENDW                                            ;如果消息循环结束,退出码存放在MSG中的wParam中

mov eax,msg.wParam                               ;把退出码写入eax

ret                                              ;返回

WinMain endp                                     ;函数定义结束

WndProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM  ;窗口处理函数定义

.IF uMsg==WM_DESTROY                        ;如果WINDOWS传递过来的消息为WM_DESTROY=$0002(窗口销毁)

   Invoke PostQuitMessage,NULL             ;调用函数中止线程

.ELSE                                      ;否则向下执行

   invoke DefWindowProc,hWnd,Umsg,wParam,lParam ;调用函数把收到的参数传给缺省的窗口处理函数

   ret                                     ;结束消息循环返回

.ENDIF                                     ;结束循环

xor eax,eax                                ;调用函数中止线程后,在EAX中传递0

ret                                        ;结束消息循环返回传EAX=0到invoke ExitProcess,eax

WndProc endp                                    ;函数定义结束

End start                                       ;程序代码结束

其实反汇编后大体的思路是一样的,就是伪指令invoke 变成了CALL,而且CALL函数之前需要将参数由右向左入堆栈,反汇编后不再是参数定义,而是具体是地址或数值,如果有什么不对的地方,请大家提出来,共同进步!

这儿我没有贴出反汇编后的代码,大家可以自己去反汇编看看,会有意想不到的效果!哈哈,让大家见笑了,我顺便将创建的EXE文件放上来了,大家可以下载回去试试

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 159
活跃值: (89)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
附件:win.rar 我上传的附件
2005-1-14 22:31
0
雪    币: 339
活跃值: (1510)
能力值: ( LV13,RANK:970 )
在线值:
发帖
回帖
粉丝
3
支持一下。代码写的比较工整哈。不过注意以下注释不必加的太多,太多反而显得冗余。
2005-1-15 00:31
0
雪    币: 260
活跃值: (81)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
好,支持楼主,!
2005-1-15 01:29
0
游客
登录 | 注册 方可回帖
返回
//