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】个人意见,与【 微点交流论坛 】立场无关※ ※ ※
|
 有点点才会放心 |
 |
|