以前买了好大一堆书,都没几本看过。真是所谓的书非借而不能读也哎!看到满书柜上一堆一堆的书,满心的惭愧,所以打算把这些买回来的书都好好的看一番。 翻来翻去,翻到了罗云彬的Window32汇编语言程序开发。汇编也基本上忘记的7788了,就从这本书开始吧。那么首先要整的无疑就是学习的开发环境了。masm32这个东西,比较轻量级,有库,有汇编器,有连接器,外加一个记事本,基本上就能写代码编译成exe了。书上没指定固定的开发环境和编辑器,编译汇编代码的编译模式都是用的make文件,然后用VS的nmake进行编译。先说编辑器,编辑器,记事本就行了,不过系统自带的记事本比较简陋,所以就选择了Notepad++来作为代码编辑的工具,选他最主要的就是功能足够(支持多语法高亮,支持各种插件)。代码写好了,要编译生成可执行文件。这个可以用写批处理或者自己在命令行下根据ml,link等命令来生成对应的文件。这里就有我选择notepad++的一个最主要的原因了,因为NotePad++有一个插件叫做NppExec,使用这个插件写上相关的脚本,就可以设置快捷键,然后用快捷键自动来编译生成需要的东西了,相当方便。书上的建议是制作makefile的文件,然后用namek进行编译连接。由于我是个人学习,多数情况下都是单个单个的汇编文件,所以,个人就不采用make文件的方式了,因为独立文件多,每测试都要写make比较麻烦,所以主要就写两个执行脚本就行了,一个脚本用来连接生成lib,另一个脚本用来连接生成exe文件,这样就基本上能写大部分的程序了,然后再写一个通过扩展名来调用不同的脚本来编译连接文件的通用脚本。之后每次,就只用调用这个通用脚本就行了(设置一个快捷键,代码好了之后保存一下,一键就行了)。这几个脚本文件如下
先是.asm后缀的,用来生成exe的脚本
这个脚本保存为Compile@.asm,其中的
ENV_SET PATH = D:\Develop_Tools\Masm32\bin; D:\Develop_Tools\Masm32\include; D:\Develop_Tools\Masm32\lib
这个是设置环境变量路径的,这里设置成你自己电脑上的路径则可
然后在写一个.inc文件用来生成lib库的脚本
保存为Compile@.inc
最后一个通用脚本
随便取一个名字,写代码保存之后,我们直接调用这个脚本就行,注意,如果要编译生成lib,要打开对应的inc文件,要生成exe就打开asm文件,设置一个快捷键,于是此汇编环境配置完成
环境配置完成了之后,基本上就可以开始着手Win32的程序开发了,刚学习初步,就发现,有点麻烦,好些个代码基本上都是一种固定模式,虽然可以指定模版,但是每次拷贝来拷贝去,也比较麻烦,于是想着是否可以按照高级语言的特性对这些个比较常用的东西进行一个封装。就像Delphi有VCL,VC有MFC,于是就想着,何妨边学masm32边对Win32的汇编程序进行一个简单的封装,以达到引用Lib就能简单的实现一个Windows程序的开发(就像Delphi和VC那种方式一样)。
我们都知道VC和Delphi中都有对象的概念,对象空间中,默认eax是指向对象本身。汇编中没有对象的概念,不过好在masm32中还有struct这个东西,不妨用他来作为一个简单对象的模拟。比如,我们可以定义一个对象结构和窗体结构如下
这样,我们就可以通过DxApp这个来作为一个对象操作,因为是模拟对象操作,所以和Delphi,VC等高级语言一样,可以将DxApp地址放入Eax中,然后传递参数,之后可以用Call进行函数调用。
可以看到,在DxApp中定义的东西,有Run,运行本实例程序,有CreateForm用来创建窗体,MainFrom保存的是DxForm的数据地址,Forms保存的是程序中的创建的窗体列表,呵呵,熟悉Delphi的应该很明确,我这个是抄袭Delphi的模式来的。不多说,且看初步封装
上面的是inc文件
这样,这个最基本的Application的汇编程序库就完成了,于是写一个简单的Win32的窗体就可以
初步封装完成,下一步想做的是封装一个类是Delphi的TList的链表对象的汇编库,然后就是在Application中整合窗体的保存以及消息流通,然后实现类似Delphi的TControl,以及TGraphicControl的初步封装,之后是控件的封装。。。。呵呵
先是.asm后缀的,用来生成exe的脚本
代码:
cd $(CURRENT_DIRECTORY)
ENV_SET PATH = D:\Develop_Tools\Masm32\bin; D:\Develop_Tools\Masm32\include; D:\Develop_Tools\Masm32\lib
ml /c /coff /I D:\Develop_Tools\Masm32\include $(NAME_PART).asm
link /LIBPATH:D:\Develop_Tools\Masm32\lib /subsystem:windows $(NAME_PART).obj /out:$(NAME_PART).exe
NPP_RUN $(NAME_PART).exe
ENV_SET PATH = D:\Develop_Tools\Masm32\bin; D:\Develop_Tools\Masm32\include; D:\Develop_Tools\Masm32\lib
这个是设置环境变量路径的,这里设置成你自己电脑上的路径则可
然后在写一个.inc文件用来生成lib库的脚本
代码:
cd $(CURRENT_DIRECTORY)
ENV_SET PATH = D:\Develop_Tools\Masm32\bin; D:\Develop_Tools\Masm32\include; D:\Develop_Tools\Masm32\lib
ml /c /coff /I D:\Develop_Tools\Masm32\include $(NAME_PART).asm
link -lib *.obj /out:$(NAME_PART).lib
最后一个通用脚本
代码:
SET Compiler = Compile@$(EXT_PART)
NPP_EXEC "$(Compiler)"
环境配置完成了之后,基本上就可以开始着手Win32的程序开发了,刚学习初步,就发现,有点麻烦,好些个代码基本上都是一种固定模式,虽然可以指定模版,但是每次拷贝来拷贝去,也比较麻烦,于是想着是否可以按照高级语言的特性对这些个比较常用的东西进行一个封装。就像Delphi有VCL,VC有MFC,于是就想着,何妨边学masm32边对Win32的汇编程序进行一个简单的封装,以达到引用Lib就能简单的实现一个Windows程序的开发(就像Delphi和VC那种方式一样)。
我们都知道VC和Delphi中都有对象的概念,对象空间中,默认eax是指向对象本身。汇编中没有对象的概念,不过好在masm32中还有struct这个东西,不妨用他来作为一个简单对象的模拟。比如,我们可以定义一个对象结构和窗体结构如下
代码:
DxForm struct
Handle dd ?
Caption dd ?
WindowState byte ?
WndProc dd ?
DxForm ends
DxApp struct
hInstance dd ?;程序实例句柄
Run dd ?;运行过程
CreateForm dd ?
MainForm dd ?;地址
Forms dd ?;Forms数组结构
DefWndProc dd ?;默认的DefWindowProc
DxApp ends
可以看到,在DxApp中定义的东西,有Run,运行本实例程序,有CreateForm用来创建窗体,MainFrom保存的是DxForm的数据地址,Forms保存的是程序中的创建的窗体列表,呵呵,熟悉Delphi的应该很明确,我这个是抄袭Delphi的模式来的。不多说,且看初步封装
代码:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;Application头文件
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DxForm struct
Handle dd ?
Caption dd ?
WindowState byte ?
WndProc dd ?
DxForm ends
DxApp struct
hInstance dd ?;程序实力
Run dd ?;运行过程
CreateForm dd ?
MainForm dd ?;地址
Forms dd ?;Forms数组结构
DefWndProc dd ?;默认的DefWindowProc
DxApp ends
;创建一个应用程序对象,App由外部传入DxApp地址
CreateApplication proto App:ptr DWORD
RGB macro red,green,blue
xor eax,eax
mov ah,blue
shl eax,8
mov ah,green
mov al,red
endm
代码:
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;DxApplication对象库
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat,stdcall
option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;包含库信息
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include user32.inc
include kernel32.inc
include gdi32.inc
includelib user32.lib
includelib kernel32.lib
includelib gdi32.lib
include DxApplication.inc
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;数据定义区
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data
Application dd ?
className db 'DxForm',0
.code
;>>>>>>>>>>>>>>>>>>Application的函数
ApplicationRun proc uses esi
local msg:MSG
mov esi, Application
mov esi,[esi].DxApp.MainForm
.if [esi].DxForm.Handle==0
invoke ExitProcess,0
ret
.endif
invoke ShowWindow,[esi].DxForm.Handle,SW_SHOWNORMAL
invoke UpdateWindow,[esi].DxForm.Handle
.while TRUE
invoke GetMessage,addr msg,NULL,0,0
.break .if(!eax)
invoke TranslateMessage,addr msg
invoke DispatchMessage,addr msg
.endw
invoke ExitProcess,0
ret
ApplicationRun endp
DefWndProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
local ps:PAINTSTRUCT
local hdc:DWORD
local rec:RECT
.if uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
xor eax,eax
ret
.elseif uMsg==WM_PAINT
;invoke BeginPaint,hWnd,addr ps
;mov hdc,eax
;invoke GetClientRect,hWnd,addr rec
;RGB 255,0,0
;invoke SetTextColor,hdc,eax
;invoke DrawText,hdc,,-1,addr rec,DT_CENTER or DT_VCENTER or DT_SINGLELINE
;invoke EndPaint,hWnd,addr ps
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.else
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
xor eax,eax
ret
DefWndProc endp
CreateForm proc uses esi edi FormInfo:ptr DWORD
local wc:WNDCLASSEX
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style,CS_HREDRAW or CS_VREDRAW
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
mov edi,Application
push [edi].DxApp.hInstance
pop wc.hInstance
mov esi,FormInfo
.if (!esi)
mov esi,[edi].DxApp.MainForm ;esi为0,就表示为主窗体
.if([esi].DxForm.Handle);主窗体已经创建过了,创建失败!
mov eax,1
ret
.endif
.endif
.if([esi].DxForm.WndProc)
push [esi].DxForm.WndProc
pop wc.lpfnWndProc
.else
mov wc.lpfnWndProc,offset DefWndProc
.endif
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.hCursor,eax
invoke RegisterClassEx,ADDR wc
invoke CreateWindowEx,NULL,wc.lpszClassName,NULL,WS_OVERLAPPEDWINDOW,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,[edi].DxApp.hInstance,NULL
.if [esi].DxForm.Handle==0
mov [esi].DxForm.Handle,eax
.endif
xor eax,eax
ret
CreateForm endp
CreateApplication proc USES esi App:ptr DWORD
mov esi,App
invoke GetModuleHandle,NULL
mov [esi].DxApp.hInstance,eax
mov [esi].DxApp.Run, offset ApplicationRun
mov [esi].DxApp.CreateForm, offset CreateForm ;
mov [esi].DxApp.DefWndProc,offset DefWndProc ;指定系统默认的窗口过程
mov Application,esi
ret
CreateApplication endp
;>>>>>>>>>>>>>>>>>>Application的函数
end
代码:
.386
.model flat,stdcall
option casemap:none
include windows.inc
include DxApplication.inc
includelib DxApplication.lib
.data
Application DxApp <>
.code
winmain proc
local mform:DxForm
mov mform.Handle,0
mov mform.WndProc,0
mov Application.hInstance,0
lea esi,mform
mov Application.MainForm,esi
invoke CreateApplication,offset Application
push NULL;传递空,表示创建主窗体
call Application.CreateForm
mov eax,esi
call Application.Run
winmain endp
start:
call winmain
end start