微点交流论坛
» 游客:  注册 | 登录 | 帮助

 

作者:
标题: Windows下32位汇编语言编程初窥-详解程序的基本框架
jr21066
版主

电脑&数码区版主


积分 1648
发帖 1646
注册 2006-12-16
#1  Windows下32位汇编语言编程初窥-详解程序的基本框架

整理硬盘发现以前写的.献给刚学习汇编的朋友吧.

Windows下32位汇编语言编程初窥-详解程序的基本框架

    汇编语言是最古老的计算机语言,也是执行效率最高的语言。目前在对程序的速度和大小有较高要求的地方还是用汇编语言来的。或是在高级语言中对部分代码用汇编语言来进行集中优化。市面上汇编语言的教程仍然多是早期的8086机Dos下编程,对于32位的图形方式下的汇编语言编程教程还是比较少,下边我就我学习中找到的一点经验来跟大家交流一下。

    下边的程序是一个最简单的窗口显示程序的源码,Windows下编程基本框架都是一样的。只要理解了下边的程序,以后编程中只需在现有代码基础上增加新的代码就可以了。


;以下是对程序的解释,分号后均为注释部分
.586
;.586是一个汇编语言伪指令,他告诉编译器我们的程序是使用80586指令集编写的。
.model flat,stdcall
;.MODEL 是用来指定内存模式的,在Win32下只有Flat一种内存模式,也就是4G的内存空间,stdcall指的是标准调用,也就是说是C语言的压栈方式,后入先出,最右面的参数是最后一个进堆栈的。
option casemap:none

;下边这些是包含文件,里面有最常用的一些函数声明及定义,如果你要用到图形方面的API时可以加上Gdi32.inc,也可以根据需要再加上其它的库文件
   include windows.inc
   include user32.inc
   include kernel32.inc
   
   includelib user32.lib
   includelib kernel32.lib


WinMain proto :DWORD,:DWORD,:DWORD,:DWORD


.data
;.data是数据段,定义了预定义的变量这些变量在程序加载时由系统负责初始化
   ClassName db "MainWinClass",0
   AppName  db "Main Window",0

.data?
;data?定义了未初始化的变量,它定义的数据是在程序执行时才分配的,不会增加程序本身的大小,但它的数据值不会被初始化.
   hInstance HINSTANCE ?
   CommandLine LPSTR ?

.code
;.code是代码段,所有的代码都放在这里.代码段是不允许写入的,任何对代码段数据的写入都会引起访问异常,所以对于需要写入的数据要放在数据段内。

; ---------------------------------------------------------------------------


start:
        invoke GetModuleHandle, NULL        ;获取模块句柄
        mov    hInstance,eax
       
        invoke GetCommandLine                ;获取命令行参数
        mov    CommandLine,eax
       
        invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT        ;调用主程序
        invoke ExitProcess,eax                ;退出程序

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
        LOCAL wc:WNDCLASSEX        ;声明一个窗口类的局部变量
        LOCAL msg:MSG                ;声明一个消息局部变量
        LOCAL hwnd:HWND                ;声明一个窗口句柄的局部变量
       
;以下对窗口类进行初始化
        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  hInstance                                        ;模块句柄
        pop   wc.hInstance
        mov   wc.hbrBackground,COLOR_BTNFACE+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.hCursor,eax                                ;保存光标句柄
       
        invoke RegisterClassEx, addr wc                        ;注册窗口类
        INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
           WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
           CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
           hInst,NULL
        ;建立窗口,参数ClassName指定了类名,AppName为应用程序名,然后是窗口风格,句柄
        mov   hwnd,eax                ;保存窗口句柄
       
        invoke ShowWindow, hwnd,SW_SHOWNORMAL        ;显示窗口
        invoke UpdateWindow, hwnd                ;更新窗口,只有更新后才能在屏幕上看见窗口
       
;下边是个循环,窗口在建立之后不是一成不变的,而是在不断的等待系统的消息,一有消息后就进行处理,处理完成后把控件权再交回系统。只有得到退出消息后循环才会结束。
        .WHILE TRUE
                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 hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
;这里就是窗口的主阵地,所有的处理都在这里,所有的消息会被发送到这里,程序对需要处理的消息进行处理,不需要的消息发回系统

        .IF uMsg==WM_CREATE                ;窗口建立
                invoke PostQuitMessage,NULL        ;发送退出消息
        .ELSEIF uMsg==WM_DESTROY        ;窗口将被销毁
        .ELSEIF uMsg==WM_MOVE                ;窗口被移动
        .ELSEIF uMsg==WM_SIZE                ;窗口大小被改变
        .ELSEIF uMsg==WM_ACTIVATE        ;窗口被激活或失去激活状态
        .ELSEIF uMsg==WM_SETFOCUS        ;获得焦点
        .ELSEIF uMsg==WM_KILLFOCUS        ;失去焦点
        .ELSEIF uMsg==WM_ENABLE                ;改变enable状态
        .ELSEIF uMsg==WM_SETREDRAW        ;设置窗口是否能重画
        .ELSEIF uMsg==WM_SETTEXT        ;应用程序发送此消息来设置一个窗口的文本
        .ELSEIF uMsg==WM_GETTEXT        ;应用程序发送此消息来复制对应窗口的文本到缓冲区
        .ELSEIF uMsg==WM_GETTEXTLENGTH        ;得到与一个窗口有关的文本的长度(不包含空字符)
        .ELSEIF uMsg==WM_PAINT                ;窗口重绘事件
        .ELSEIF uMsg==WM_CLOSE                ;窗口将要关闭
        .ELSEIF uMsg==WM_QUERYENDSESSION        ;程序自己调用ExitWindows
        .ELSEIF uMsg==WM_QUIT                ;结束程序运行或程序调用postquitmessage
        .ELSEIF uMsg==WM_QUERYOPEN        ;当用户窗口恢复以前的大小位置时,把此消息发送给某个图标
        .ELSEIF uMsg==WM_ERASEBKGND        ;当窗口背景必须被擦除时
        .ELSEIF uMsg==WM_SYSCOLORCHANGE        ;当系统颜色改变时
        .ELSEIF uMsg==WM_ENDSESSION        ;当系统进程发出WM_QUERYENDSESSION消息,查询是否退出
        .ELSEIF uMsg==WM_SHOWWINDOW        ;隐藏或显示窗口
        .ELSEIF uMsg==WM_ACTIVATEAPP        ;发此消息给应用程序哪个窗口是激活的,哪个是非激活的
        .ELSEIF uMsg==WM_FONTCHANGE        ;当系统的字体资源库变化时发送此消息给所有顶级窗口
        .ELSEIF uMsg==WM_TIMECHANGE        ;当系统的时间变化时发送此消息给所有顶级窗口
        .ELSEIF uMsg==WM_MOUSEACTIVAT        ;鼠标激活
        .ELSEIF uMsg==WM_CHILDACTIVATE        ;子窗口被激活
        .ELSEIF uMsg==WM_GETMINMAXINFO        ;窗口将被改变大小或位置时
        .ELSEIF uMsg==WM_PAINTICON        ;发送给最小化窗口当它图标将要被重画
        .ELSEIF uMsg==WM_ICONERASEBKGND        ;发送给某个最小化窗口,当它在画图标前它的背景必须被重画
        .ELSEIF uMsg==WM_NEXTDLGCTL        ;发送此消息给一个对话框程序去更改焦点位置
        .ELSEIF uMsg==WM_WINDOWPOSCHANGING        ;窗口的大小和位置将要被改变时
        .ELSEIF uMsg==WM_WINDOWPOSCHANGED        ;窗口的大小和位置已经被改变时
        .ELSEIF uMsg==WM_POWER                ;系统将要进入暂停状态时发送此消息
        .ELSEIF uMsg==WM_COPYDATA        ;当一个应用程序传递数据给另一个应用程序时发送此消息
        .ELSEIF uMsg==WM_HELP                ;用户按下了F1
        .ELSEIF uMsg==WM_CONTEXTMENU        ;点击了右键
        .ELSEIF uMsg==WM_STYLECHANGING        ;窗口的风格将被改变时
        .ELSEIF uMsg==WM_STYLECHANGED        ;窗口的风格被改变后
        .ELSEIF uMsg==WM_DISPLAYCHANGE        ;显示器的分辨率改变后
        .ELSEIF uMsg==WM_SETICON        ;设置图标
        .ELSEIF uMsg==WM_NCCREATE        ;窗口第一次被创建时
        .ELSEIF uMsg==WM_NCDESTROY        ;此消息通知某个窗口,非客户区正在销毁
        .ELSEIF uMsg==WM_NCHITTEST        ;移动鼠标,按住或释放鼠标时发生
        .ELSEIF uMsg==WM_NCLBUTTONDOWN        ;非客户区按下鼠标左键时
        .ELSEIF uMsg==WM_NCLBUTTONUP        ;非客户区释放鼠标左键
        .ELSEIF uMsg==WM_NCLBUTTONDBLCLK;非客户区双击鼠标左键
        .ELSEIF uMsg==WM_NCRBUTTONDOWN        ;非客户区按下鼠标右键
        .ELSEIF uMsg==WM_NCRBUTTONUP        ;非客户区释放鼠标右键
        .ELSEIF uMsg==WM_KEYDOWN        ;按下一个键
        .ELSEIF uMsg==WM_KEYUP                ;释放一个键
        .ELSEIF uMsg==WM_INITDIALOG        ;在一个对话框程序被显示前发送此消息
        .ELSEIF uMsg==WM_COMMAND        ;用户选择一条菜单命令项或当某个控件发送一条消息给它的父窗口
        .ELSEIF uMsg==WM_SYSCOMMAND        ;当用户选择最大化或最小化时
        .ELSEIF uMsg==WM_TIMER                ;定时器事件
        .ELSEIF uMsg==WM_MOUSEMOVE        ;移动鼠标
        .ELSEIF uMsg==WM_LBUTTONDOWN        ;按下鼠标左键
        .ELSEIF uMsg==WM_LBUTTONUP        ;释放鼠标左键
        .ELSEIF uMsg==WM_LBUTTONDBLCLK        ;双击鼠标左键
        .ELSEIF uMsg==WM_RBUTTONDOWN        ;按下鼠标右键
        .ELSEIF uMsg==WM_RBUTTONUP        ;释放鼠标右键
        .ELSEIF uMsg==WM_RBUTTONDBLCLK        ;双击鼠标右键
                ;
        .ELSE                ;如果不是程序所需要的消息,交由系统处理
                invoke DefWindowProc,hWnd,uMsg,wParam,lParam               
                ret
        .ENDIF
       
        xor eax,eax        ;清消息,返回
        ret
WndProc endp


end start       
;end 之后的语句将不再被编译程序编译,所有代码必须放在end语句之前。后边的参数说明了程序开始执行的地方。

[ Last edited by jr21066 on 2007-12-9 at 14:52 ]

※ ※ ※ 本文纯属【jr21066】个人意见,与【 微点交流论坛 】立场无关※ ※ ※

有点点才会放心
2007-12-9 14:51
查看资料  发送邮件  发短消息   编辑帖子
peter0605
银牌会员




积分 2083
发帖 2065
注册 2007-9-11
来自 宁波,杭州。。。
#2  

。。。汇编。。。啊。。。。啊。。。。。。
慢慢来。。。哈哈~

※ ※ ※ 本文纯属【peter0605】个人意见,与【 微点交流论坛 】立场无关※ ※ ※

我就是我,是颜色不一样的烟火
2007-12-9 16:36
查看资料  发送邮件  发短消息   编辑帖子
norman6810
版主





积分 3351
发帖 3303
注册 2007-4-4
#3  

纯技术的东东没研究过,还是顶下版主啦!

※ ※ ※ 本文纯属【norman6810】个人意见,与【 微点交流论坛 】立场无关※ ※ ※

灌水区版规
2007-12-10 00:26
查看资料  发短消息   编辑帖子
qq2008444
银牌会员

职业潜水艇


积分 5373
发帖 5291
注册 2007-7-7
来自 兰·基亚斯 兰古拉王国
#4  

拜.....再拜....
大哥太好了
知道我最近想学汇编的说

※ ※ ※ 本文纯属【qq2008444】个人意见,与【 微点交流论坛 】立场无关※ ※ ※

迅雷不及掩耳盗铃,以不变应万变不离其宗,成事不足挂齿,此物最相思风雨中,一屋不扫何以扫天下无敌,东边日出西边雨一直下,举头望明月几时有,呆若木鸡毛当令箭,杀鸡焉用牛刀小试,锋芒毕露春光,围魏救赵宝奎,Very good bye,八格牙鲁冰花,一泻千里共婵娟……
2007-12-10 15:08
查看资料  发送邮件  发短消息   编辑帖子



论坛跳转:

可打印版本 | 推荐 | 订阅 | 收藏


[ 联系我们 - 东方微点 ]


北京东方微点信息技术有限责任公司 福建东方微点信息安全有限责任公司

闽ICP备05030815号