IDM下载时忘了填扩展名,exe文件打不开开,改回原来的扩展名也打不开

&&&&&&& 资源编译器用来把资源脚本文件(*.rc)编译成资源文件(*.res),MASM32 软件包中使用的是Visual C++附带的Rc.exe 程序,TASM软件包中使用的是BRC32.exe 或BRCC32.exe,两者的用法都比较简单,它们有相同的命令行语法:
Rc 或BRC32 [选项] 资源脚本文件名&&&&&&&&Rc 和BRC32 在使用中没有必需的选项,不像汇编编译器一样必须使用一些关键的选项。如果编译成功,就会产生以res 为扩展名的资源文件,两者生成的资源文件的格式是一样的。资源文件编写是PE 开发的标准步骤,不同的语言使用的资源编译器以及生成的 .res 文件格式都是一样的,没有汇编格式的资源文件和C 格式的资源文件之分,所以汇编开发包中的资源编译器实际上就是C 开发包中的资源编译器。由于C 语言的使用远比汇编广泛,所以资源脚本文件的语法是C 格式的,如等值定义语句使用#define 而不是汇编常用的equ,注释使用:&//&而不是&;&,头文件习惯使用 .h 扩展名而不是 .inc,参数定义有&或&操作时使用&|&操作符而不是汇编的&or&操作符等,这些在使用中必须注意,否则会引起语法错误。两种资源编译器在使用中稍微有所区别,BRC32.exe 内部可以解释Windows 的一些预定义值,所以不用附带头文件,只有遇到最新的预定义时才需要头文件,而Rc 并没有这个功能,所以在脚本文件中必须把头文件Resource.h 包括进去。
&&&&&&&& 说明,我们要写一个test.exe 文件,生成最后的可执行文件有4 个步骤:1. 汇编源文件x.asm,其中用到头文件common.inc,它们经Ml.exe 编译成x.obj;2. 汇编源文件y.asm,用到头文件common.inc 和y.inc,它们经Ml.exe 编译成y.obj;3. 资源脚本文件x.rc,经Rc.exe 编译成x.res;4. 最后用Link 将x.obj,y.obj 和x.res 链接成test.exe。&&&&&&&& 看出,当程序调试的时候,如果修改了x.asm,也就是说x.obj 的文件时间比x.asm要早,就需要重新进行步骤1 和4;如果修改了y.asm 或y.inc,那么需要重新执行步骤2 和4;如果修改的是x.rc,则步骤3 和4 必须重新执行;如果修改的是common.inc,因为x.asm 和y.asm 都和它有关,所以步骤1、2 和4 都要重新执行;如果同时修改了common.inc 和x.rc,那么必须重复全部步骤。在这个例子中,文件的依赖关系就是:1. test.exe 依赖于 x.obj,y.obj 和 x.res;2. x.res 依赖于 x.rc;3. x.obj 依赖于 x.asm 和 common.inc;4. y.obj 依赖于 y.asm,common.inc 和 y.inc。
&&&&&&&& ke 可以根据文件的时间正确判断文件的新旧并执行相应的步骤。但make 又是如何知道文件之间的依赖关系呢?这需要用户用一个描述文件来指定。前面提到的makefile 就是这个描述文件,执行make 工具的时候,它会默认用makefile 做描述文件名来进行相应的工作,书写描述文件有规定的语法,虽然语法不是很简单,但写好以后就省事多了。
&&&&&&&Ms的make 工具文件名为nmake.exe,它并不是MASM 软件包的一部分,但可以在Visual C++的Bin 目录下找到。Borland 公司的make 工具文件名是make.exe,它已经包括在TASM 5.0 工具包中。两者默认的描述文件名都是makefile,描述文件的语法也大同小异,只是使用时命令行参数有些不同。在命令行键入nmake /? 可以显示帮助信息,nmake 的语法为:nmake [选项] [/f 描述文件名] [/x 输出信息文件名] [宏定义] [目标]说明如下:/f 参数棗如果描述文件名不使用默认的 makefile,可以用/f 参数指定。/x 参数棗如果想把屏幕输出的信息存到一个文件中,可以用/x 参数指定(用 DOS下的管道操作符nmake & 文件名的方法无效)。
描述文件一般需要包含以下内容:● 注释● 宏定义● 显式规则● 隐含规则在这里,首先为2.4.1 节中有关test.exe 的例子写出一个描述文件,再逐步介绍各部分的书写语法。为了方便使用,一般都把描述文件的文件名取为默认文件名:makefile。这个例子的makefile 文件如下(注意前面括号里的是行号,不是文件的真正内容):(001) # nmake 工具的描述文件例子(002) EXE = Test.exe #指定输出文件(003) OBJS = x.obj \(004) y.obj #需要的目标文件(005) RES = x.res #需要的资源文件(006)(007) LINK_FLAG = /subsystem:windows #链接选项(008) ML_FLAG = /c /coff #编译选项(009)(010) #定义依赖关系和执行命令(011) $(EXE): $(OBJS) $(RES)(012) Link $(LINK_FLAG) /out:$(EXE) $(OBJS) $(RES)(013) $(OBJS): Common.inc(014) y.obj: y.inc(015)(016) #定义汇编编译和资源编译的默认规则(017) .asm.obj:(018) ml $(ML_FLAG) $&(019) .rc.res:(020) rc $&(021)(022) #清除临时文件(023) clean:(024) del *.obj(025) del *.res
1. 注释和换行makefile 中的注释是以#号开头一直到行尾的字符,当nmake 工具处理到这些字符的时候,它会完全忽略#号及全部注释字符。当一行的内容过长的时候,可以用换行符来继续,makefile 的换行符是\,如例子中的第三行和第四行可以合并为:OBJS = x.obj y.obj #需要的目标文件在使用换行符的时候要注意在?\?后面不能再加上其他字符,包括注释和空格,否则nmake 检测到?\?不在一行的最后,就不会把它当成换行符解释,就会出现错误。2. 宏定义makefile 中允许使用简单的宏定义指代源文件及其相关编译信息,可以把宏称为变量,在整个描述文件中,只要符合下面语法的行就是宏定义:变量名=变量内容如上面例子文件中的2 到8 就是宏定义,在引用宏时只需在变量前加$符号,但是要注意的是,如果变量名的长度超过一个字符,在引用时就必须加圆括号(),下面都是有效的宏引用:$(LINK_FLAG)$(EXE)$A$(A)其中最后两个引用是完全一致的。
3. 显式规则makefile 中包含有一些规则,这些规则定义了文件之间的依赖关系和产生命令,一个规则的格式是这样的:目标文件:依赖文件;命令 (方法1)或目标文件:依赖文件 (方法2)命令在规则定义和命令行中,不能包含注释,例子中的第11 和12 行把宏定义展开后就是:test.exe:x.obj y.obj x.resLink /subsystem:windows /out:test.exe x.obj y.obj x.res
&&&&&&&&这里的目标文件就是test.exe,它依赖于3 个文件x.obj,y.obj 和x.res,如果有必要,产生目标文件的命令就是下面的Link 命令,整个规则可以用两种方法,用第二种方法的时候,命令可以从第二行开始,第一行的?;?省略,但是这时命令前面必须有一个Tab 字符,否则nmake 无法区分这究竟是命令还是别的定义。目标文件可以有多个,依赖文件也可以有多个,同时命令也可以由多个命令行组成,当然这时候就必须用第二种方法定义了。
&&&&&&& 我们也可以用test.exe 生成的规则定义其他文件,如x.obj 或x.res 的生成方法,但nmake如何知道哪个是最终要make 的文件呢?实际上nmake 默认将整个描述文件的第一条规则中的目标文件认为是最终文件,如果我们把11,12 行放到第13 行后面,那么x.obj 和y.obj 的建立规则就成了第一条规则,nmake 建立了x.obj 和x.obj 之后就不理会test.exe 的建立了,所以我们必须把最终需要生成的文件放在第一条规则定义。当然,在nmake 的命令行参数中可以指定要make 的目标,如我们要生成x.res 文件,那么不必修改makefile 将x.res 的描述规则移动到最前面,而是直接在命令行键入以下命令即可:nmake x.res
4. 隐含规则&&&&&&& 隐含规则可以为某一类的文件指出建立的命令,它具体定义了如何将带一个特定扩展名的文件转换成具有另一种扩展名的文件,定义的格式是:.源扩展名.目标扩展名:;命令 (方法1)或.源扩展名.目标扩展名: (方法2)命令&&&&&&& 隐含规则的语法和显式规则相似,也是用?:?隔开,在?;?下面书写命令,也可以不用?;?而将命令写在第二行,同理,这时命令之前要加一个Tab 字符。&&&&&& 隐含规则不能有依赖文件,所以?:?下面没有内容,例子中的第17、18 行定义了从asm文件建立obj 文件的隐含规则,第19 和20 行定义了从rc 文件建立res 文件的隐含规则,隐含规则中无法指定确定的输入文件名,因为输入文件名是泛指的有相同扩展名的一整类文件,这时候就要用到几个特殊的内定宏来指定文件名,这些宏是$@,$*,$?和$&,它们的含义如下:$@&&& 全路径的目标文件。$*&&&&& 除去扩展名的全路径的目标文件。$?&&&& 所有源文件名。$&&&&& 源文件名(只能用在隐含规则中)。所以第19、20 行中的rc $& 用于x.rc 的时候就是rc x.rc。
&&&&&&& 读者可以注意到一些显式规则没有命令行,如第13 行的&$(OBJS): Common.inc&指出了所有的obj 文件全部依赖于Common.inc 文件,第14 行的&y.obj: y.inc&则指出了y.obj 同时也依赖于y.inc 和第13 行的规则合并,y.obj 依赖于Common.inc 也依赖于y.inc,但是这两条规则都没有指出产生这些obj 文件的命令,所以nmake 处理的时候会到隐含规则中去找命令行,最后会用第18 行的&ml $(ML_FLAG) $&&命令去产生这些obj 文件。
&&&&&&& 资源文件确实太麻烦了,不说那么多重复的代码,就说那些个x、y坐标,就令人十分的头痛了,仔细翻看一下书的第二章,推荐的是Resource Workshop和Visual C++编辑资源。比较了一下,还是用VC容易多了~,虽然生成的代码太多VC的东西,需要手工删除,但是他毕竟是所见即所得!
资源文件:
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#include&&&resource.h&//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#define&ICO_MAIN&&0×1000&//图标//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#define&IDM_MAIN&&0×2000&//菜单#define&IDA_MAIN&&0×2000&//加速键#define&IDM_OPEN&&0×4101#define&IDM_OPTION&&0×4102#define&IDM_EXIT&&0×4103&& #define&IDM_SETFONT&&0×4201#define&IDM_SETCOLOR&0×4202#define&IDM_INACT&&0×4203#define&IDM_GRAY&&0×4204#define&IDM_BIG&&&0×4205#define&IDM_SMALL&&0×4206#define&IDM_LIST&&0×4207#define&IDM_DETAIL&&0×4208#define&IDM_TOOLBAR&&0×4209#define&IDM_TOOLBARTEXT&0×4210#define&IDM_INPUTBAR&0×4211#define&IDM_STATUSBAR&0×4212#define&IDM_HELP&&0×4301#define&IDM_ABOUT&&0×4302//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ICO_MAIN&ICON&&&Main.ico&//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&IDM_MAIN&menu&discardableBEGIN&popup&&文件(&F)&&BEGIN&&menuitem&&打开文件(&O)…&,&IDM_OPEN&&menuitem&&关闭文件(&C)…&,&IDM_OPTION&&menuitem&separator&&menuitem&&退出(&X)&,&&IDM_EXIT&END&popup&&查看(&V)&&BEGIN&&menuitem&&字体(&F)…\tAlt+F&,IDM_SETFONT&&menuitem&&背景色(&B)…\tCtrl+Alt+B&,IDM_SETCOLOR&&menuitem&separator&&menuitem&&被禁用的菜单项&,&IDM_INACT,&INACTIVE&&menuitem&&被灰化的菜单项&,&IDM_GRAY,&GRAYED&&menuitem&separator&&menuitem&&大图标(&G)&,&&IDM_BIG&&menuitem&&小图标(&M)&,&&IDM_SMALL&&menuitem&&列表(&L)&,&&&IDM_LIST&&menuitem&&详细资料(&D)&,&&IDM_DETAIL&&menuitem&separator&&popup&&&工具栏(&T)&&&BEGIN&&&& menuitem&&标准按钮(&S)&,&&IDM_TOOLBAR&&&& menuitem&&文字标签(&C)&,&&IDM_TOOLBARTEXT&&&& menuitem&&命令栏(&I)&,&&IDM_INPUTBAR&&END&&menuitem&&状态栏(&U)&,&&IDM_STATUSBAR&END&popup&&帮助(&H)&&,HELP&BEGIN&&menuitem&&帮助主题(&H)\tF1&,&IDM_HELP&&menuitem&separator&&menuitem&&关于本程序(&A)…&,IDM_ABOUT&ENDEND//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&IDA_MAIN&acceleratorsBEGIN&&VK_F1,&IDM_HELP,&VIRTKEY&&&B&,&IDM_SETCOLOR,VIRTKEY,CONTROL,ALT&&&F&,&IDM_SETFONT,VIRTKEY,ALTEND//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
; Menu.asm; 菜单资源的使用例子;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; 使用 nmake 或下列命令进行编译和链接:; ml /c /coff Menu.asm; rc Menu.rc; Link /subsystem:windows Menu.obj Menu.res;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.386&&.model flat, stdcall&&option casemap :none;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; Include 文件定义;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&include&&windows.incinclude&&user32.incincludelib&user32.libinclude&&kernel32.incincludelib&kernel32.lib;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; Equ 等值定义;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ICO_MAIN&equ&&1000h&;图标IDM_MAIN&equ&&2000h&;菜单IDA_MAIN&equ&&2000h&;加速键IDM_OPEN&equ&&4101hIDM_OPTION&equ&&4102hIDM_EXIT&equ&&4103hIDM_SETFONT&equ&&4201hIDM_SETCOLOR&equ&&4202hIDM_INACT&equ&&4203hIDM_GRAY&equ&&4204hIDM_BIG&&equ&&4205hIDM_SMALL&equ&&4206hIDM_LIST&equ&&4207hIDM_DETAIL&equ&&4208hIDM_TOOLBAR&equ&&4209hIDM_TOOLBARTEXT&equ&&4210hIDM_INPUTBAR&equ&&4211hIDM_STATUSBAR&equ&&4212hIDM_HELP&equ&&4301hIDM_ABOUT&equ&&4302h;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; 数据段;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.data?hInstance&dd&&?hWinMain&dd&&?hMenu&&dd&&?hSubMenu&dd&&?;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; 数据段;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.constszClassName&db&’Menu Example’,0szCaptionMain&db&’Menu’,0szMenuHelp&db&’帮助主题(&H)’,0szMenuAbout&db&’关于本程序(&A)…’,0szCaption&db&’菜单选择’,0szFormat&db&’您选择了菜单命令:%08x’,0;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; 代码段;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.code;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&_DisplayMenuItem&proc&_dwCommandID&&&local&@szBuffer[256]:byte
&&pushad&&invoke&wsprintf,addr @szBuffer,addr szFormat,_dwCommandID&&invoke&MessageBox,hWinMain,addr @szBuffer,offset szCaption,MB_OK&&popad&&ret
_DisplayMenuItem&endp;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&_Quit&&proc
&&invoke&DestroyWindow,hWinMain&&invoke&PostQuitMessage,NULL&&ret
_Quit&&endp;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&_ProcWinMain&proc&uses ebx edi esi hWnd,uMsg,wParam,lParam&&local&@stPos:POINT&&local&@hSysMenu
&&mov&eax,uMsg&&.if&eax ==&WM_CREATE&&&invoke&GetSubMenu,hMenu,1&&&mov&hSubMenu,eax;********************************************************************;&在系统菜单中添加菜单项;********************************************************************&&&invoke&GetSystemMenu,hWnd,FALSE&&&mov&@hSysMenu,eax&&&invoke&,@hSysMenu,MF_SEPARATOR,0,NULL&&&invoke&AppendMenu,@hSysMenu,0,IDM_HELP,offset szMenuHelp&&&invoke&AppendMenu,@hSysMenu,0,IDM_ABOUT,offset szMenuAbout;********************************************************************; 处理菜单及加速键消息;********************************************************************&&.elseif&eax ==&WM_COMMAND&&&invoke&_DisplayMenuItem,wParam&&&mov&eax,wParam&&&movzx&eax,ax&&&.if&eax ==&IDM_EXIT&&&&call&_Quit&&&.elseif&eax &=&IDM_TOOLBAR && eax &= IDM_STATUSBAR&&&&mov&ebx,eax&&&&invoke&,hMenu,ebx,MF_BYCOMMAND&&&&.if&eax ==&MF_CHECKED&&&&&mov&eax,MF_UNCHECKED&&&&.else&&&&&mov&eax,MF_CHECKED&&&&.endif&&&&invoke,hMenu,ebx,eax&&&.elseif&eax &=&IDM_BIG && eax &= IDM_DETAIL&&&&invoke&,hMenu,IDM_BIG,IDM_DETAIL,eax,MF_BYCOMMAND&&&.endif;********************************************************************; 处理系统菜单消息;********************************************************************&&.elseif&eax == WM_SYSCOMMAND&&&mov&eax,wParam&&&movzx&eax,ax&&&.if&eax == IDM_HELP || eax == IDM_ABOUT&&&&invoke&_DisplayMenuItem,wParam&&&.else&&&&invoke&DefWindowProc,hWnd,uMsg,wParam,lParam&&&&ret&&&.endif;********************************************************************; 按下右键时弹出一个POPUP菜单;********************************************************************&&.elseif eax == WM_RBUTTONDOWN&&&invoke&,addr @stPos&&&invoke&,hSubMenu,TPM_LEFTALIGN,@stPos.x,@stPos.y,NULL,hWnd,NULL;********************************************************************&&.elseif&eax ==&WM_CLOSE&&&call&_Quit;********************************************************************&&.else&&&invoke&DefWindowProc,hWnd,uMsg,wParam,lParam&&&ret&&.endif;********************************************************************&&xor&eax,eax&&ret
_ProcWinMain&endp;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&_WinMain&proc&&local&@stWndClass:WNDCLASSEX&&local&@stMsg:MSG&&local&@hAccelerator
&&invoke&GetModuleHandle,NULL&&mov&hInstance,eax&&invoke&,hInstance,IDM_MAIN&&mov&hMenu,eax&&invoke&s,hInstance,IDA_MAIN&&mov&@hAccelerator,eax;********************************************************************; 注册窗口类;********************************************************************&&invoke&RtlZeroMemory,addr @stWndClass,sizeof @stWndClass&&invoke&LoadIcon,hInstance,ICO_MAIN&&mov&@stWndClass.hIcon,eax&&mov&@stWndClass.hIconSm,eax&&invoke&LoadCursor,0,IDC_ARROW&&mov&@stWndClass.hCursor,eax&&push&hInstance&&pop&@stWndClass.hInstance&&mov&@stWndClass.cbSize,sizeof WNDCLASSEX&&mov&@stWndClass.style,CS_HREDRAW or CS_VREDRAW&&mov&@stWndClass.lpfnWndProc,offset _ProcWinMain&&mov&@stWndClass.hbrBackground,COLOR_WINDOW + 1&&mov&@stWndClass.lpszClassName,offset szClassName&&invoke&RegisterClassEx,addr @stWndClass;********************************************************************; 建立并显示窗口;********************************************************************&&invoke&CreateWindowEx,WS_EX_CLIENTEDGE,\&&&offset szClassName,offset szCaptionMain,\&&&WS_OVERLAPPEDWINDOW,\&&&100,100,400,300,\&&&NULL,hMenu,hInstance,NULL&&mov&hWinMain,eax&&invoke&ShowWindow,hWinMain,SW_SHOWNORMAL&&invoke&UpdateWindow,hWinMain;********************************************************************; 消息循环;********************************************************************&&.while&TRUE&&&invoke&GetMessage,addr @stMsg,NULL,0,0&&&.break&.if eax&== 0&&&invoke&TranslateAccelerator,hWinMain,@hAccelerator,addr @stMsg&&&.if&eax == 0&&&&invoke&TranslateMessage,addr @stMsg&&&&invoke&DispatchMessage,addr @stMsg&&&.endif&&.endw&&ret
_WinMain&endp;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&start:&&call&_WinMain&&invoke&ExitProcess,NULL;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&end&start
The AppendMenu function appends a new item to the end of the specified menu bar, drop-down menu, submenu, or shortcut menu. You can use this function to specify the content, appearance, and behavior of the menu item.
The AppendMenu function has been superseded by the InsertMenuItem function. You can still use AppendMenu, however, if you do not need any of the extended features of InsertMenuItem.
BOOL AppendMenu(
HMENU hMenu,
// handle to menu to be changed
UINT uFlags,
// menu-item flags
UINT uIDNewItem,
// menu-item identifier or handle to drop-down menu or submenu
LPCTSTR lpNewItem // menu-item content
The GetMenuState function retrieves the menu flags associated with the specified menu
item. If the menu item opens a submenu, this function also returns the number of items in the submenu.
The GetMenuState function has been superseded by the GetMenuItemInfo function. You can still use
GetMenuState, however, if you do not need any of the extended features of GetMenuItemInfo.
UINT GetMenuState(
HMENU hMenu, // handle to menu
// menu item to query
UINT uFlags
// menu flags
The CheckMenuItem function sets the state of the specified menu item's check mark attribute
to either checked or unchecked.
The CheckMenuItem function has been superseded by the
function. You can still use
CheckMenuItem, however, if you do not need any of the extended features of SetMenuItemInfo.
DWORD CheckMenuItem(
HMENU hmenu,
// handle to menu
UINT uIDCheckItem,
// menu item to check or uncheck
UINT uCheck
// menu item flags
CheckMenuRadioItem function checks a specified menu item and makes it a radio item. At the
same time, the function unchecks all other menu items in the associated group and clears the
radio-item type flag for those items.
BOOL CheckMenuRadioItem(
HMENU hmenu,
UINT idFirst,
UINT idLast,
UINT idCheck,
UINT uFlags
GetCursorPos function retrieves the cursor's position, in screen coordinates.
BOOL GetCursorPos(
LPPOINT lpPoint
// address of structure for cursor position
TrackPopupMenu function displays a shortcut menu at the specified location and tracks the
selection of items on the menu. The shortcut menu can appear anywhere on the screen.
BOOL TrackPopupMenu(
HMENU hMenu,
// handle to shortcut menu
UINT uFlags,
// screen-position and mouse-button flags
// horizontal position, in screen coordinates
// vertical position, in screen coordinates
int nReserved,
// reserved, must be zero
HWND hWnd,
// handle to owner window
CONST RECT *prcRect
// ignored
LoadMenu function loads the specified menu resource from the executable (.EXE) file
associated with an application instance.
HMENU LoadMenu(
HINSTANCE hInstance,
// handle to application instance
LPCTSTR lpMenuName
// menu name string or menu-resource
// identifier
LoadAccelerators function loads the specified accelerator table.
HACCEL LoadAccelerators(
HINSTANCE hInstance,
// handle to application instance
LPCTSTR lpTableName
// address of table-name string
— dugu @ 9:28 pm
&&.386&&.model flat,stdcall&&option casemap:none;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; Include 文件定义;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&include&&windows.incinclude&&gdi32.incincludelib&gdi32.libinclude&&user32.incincludelib&user32.libinclude&&kernel32.incincludelib&kernel32.lib;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; 数据段;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.data?
hInstance&dd&&?hWinMain&dd&&?
szClassName&db&’MyClass’,0szCaptionMain&db&’My first Window !’,0szText&&db&’Win32 Assembly, Simple and powerful !’,0;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; 代码段;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.code;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; 窗口过程;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&_ProcWinMain&proc&uses ebx edi esi,hWnd,uMsg,wParam,lParam&&local&@stPs:PAINTSTRUCT&&local&@stRect:RECT&&local&@hDc
&&mov&eax,uMsg;********************************************************************&&.if&eax ==&WM_PAINT&&&invoke&BeginPaint,hWnd,addr @stPs&&&mov&@hDc,eax
&&&invoke&GetClientRect,hWnd,addr @stRect&&&invoke&DrawText,@hDc,addr szText,-1,\&&&&addr @stRect,\&&&&DT_SINGLELINE or DT_CENTER or DT_VCENTER
&&&invoke&EndPaint,hWnd,addr @stPs;********************************************************************&&.elseif&eax ==&WM_CLOSE&&&invoke&DestroyWindow,hWinMain&&&invoke&PostQuitMessage,NULL;********************************************************************&&.else&&&invoke&DefWindowProc,hWnd,uMsg,wParam,lParam&&&ret&&.endif;********************************************************************&&xor&eax,eax&&ret
_ProcWinMain&endp;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&_WinMain&proc&&local&@stWndClass:WNDCLASSEX&&local&@stMsg:MSG
&&invoke&GetModuleHandle,NULL&&mov&hInstance,eax&&invoke&RtlZeroMemory,addr @stWndClass,sizeof @stWndClass;********************************************************************; 注册窗口类;********************************************************************&&invoke&LoadCursor,0,IDC_ARROW&&mov&@stWndClass.hCursor,eax&&push&hInstance&&pop&@stWndClass.hInstance&&mov&@stWndClass.cbSize,sizeof WNDCLASSEX&&mov&@stWndClass.style,CS_HREDRAW or CS_VREDRAW&&mov&@stWndClass.lpfnWndProc,offset _ProcWinMain&&mov&@stWndClass.hbrBackground,COLOR_WINDOW + 1&&mov&@stWndClass.lpszClassName,offset szClassName&&invoke&RegisterClassEx,addr @stWndClass;********************************************************************; 建立并显示窗口;********************************************************************&&invoke&CreateWindowEx,WS_EX_CLIENTEDGE,offset szClassName,offset szCaptionMain,\&&&WS_OVERLAPPEDWINDOW,\&&&100,100,600,400,\&&&NULL,NULL,hInstance,NULL&&mov&hWinMain,eax&&invoke&ShowWindow,hWinMain,SW_SHOWNORMAL&&invoke&UpdateWindow,hWinMain;********************************************************************; 消息循环;********************************************************************&&.while&TRUE&&&invoke&GetMessage,addr @stMsg,NULL,0,0&&&.break&.if eax&== 0&&&invoke&TranslateMessage,addr @stMsg&&&invoke&DispatchMessage,addr @stMsg&&.endw&&ret
_WinMain&endp;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&start:&&call&_WinMain&&invoke&ExitProcess,NULL;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&end&start
程序的流程也就是常见的windows下的编程,这里简单回顾一下~
GetModuleHandle & RtlZeroMemory & LoadCursor & RegisterClassEx& CreateWindowEx & ShowWindow & UpdateWindow ;API调用顺序
GetMessage & TranslateMessage & DispatchMessage ;消息循环
(1)得到应用程序的句柄(GetModuleHandle)。(2)注册窗口类(RegisterClassEx)。在注册之前,要先填写RegisterClassEx 的参数WNDCLASSEX 结构。(3)建立窗口(CreateWindowEx)。(4)显示窗口(ShowWindows)。(5)刷新窗口客户区(UpdateWindow)。(6)进入无限的消息获取和处理的循环。首先获取消息(GetMessage),如果有消息到达,则将消息分派到回调函数处理(DispatchMessage),如果消息是WM_QUIT,则退出循环。&&&&&&& 程序的另一半_ProcWinMain 子程序是用来处理消息的,它就是窗口的回调函数(Callback),也叫做窗口过程,之所以是回调函数是因为它是由Windows 而不是我们自己调用的,我们调用DispatchMessage,而DispatchMessage 再回过来调用窗口过程。
&&&&&&& Windows 为每个程序(严格地说是每个线程)维护一个消息队列,Windows 检查系统消息队列里消息的发生位置,当位置位于某个应用程序的窗口范围内的时候,就把这个消息派送到应用程序的消息队列里,如图4.4 中的箭头c 所示。&&&&&&& 当应用程序还没有来取消息的时候,消息就暂时保留在消息队列里,当程序中的消息循环执行到GetMessage 的时候,控制权转移到GetMessage 所在的USER32.DLL 中(箭头1),USER32.DLL 从程序消息队列中取出一条消息(箭头2),然后把这条消息返回应用程序(箭头3)。应用程序可以对这条消息进行预处理,如可以用TranslateMessage 把基于键盘扫描码的按键消息转换成基于ASCII 码的键盘消息,以后也会用到TranslateAccelerator 把键盘快捷键转换成命令消息,但这个步骤不是必需的。&&&&&&& 然后应用程序将处理这条消息,但方法不是自己直接调用窗口过程来完成,而是通过DispatchMessage 间接调用窗口过程,Dispatch 的英文含义是&分派&,之所以是&分派&,是因为一个程序可能建有不止一个窗口,不同的窗口消息必须分派给相应的窗口过程。当控制权转移到USER32.DLL 中的DispatchMessage 时,DispatchMessage 找出消息对应窗口的窗口过程,然后把消息的具体信息当做参数来调用它(箭头5),窗口过程根据消息找到对应的分支去处理,然后返回(箭头6),这时控制权回到DispatchMessage,最后DispatchMessage 函数返回应用程序(箭头7)。这样,一个循环就结束了,程序又开始新一轮的GetMessage。
&&&&&&& 应用程序之间也可以互发消息,PostMessage 是把一个消息放到其他程序的消息队列中,如图4.4 中箭头d 所示,目标程序收到了这条消息就把它放入该程序的消息队列去处理;而SendMessage 则越过消息队列直接调用目标程序的窗口过程(箭头I 所示),窗口过程返回以后才从SendMessage 返回(箭头II 所示)。&&&&&&& 窗口过程是由Windows 回调的,Windows 又是怎么知道往哪里回调呢?答案是我们在调用RegisterClassEx 函数的时候告诉了Windows。
&&&&&&&&hbrBackground& 窗口客户区的背景色。前面的 hbr 表示它是一个刷子(Brush)的句柄,&刷子&一词形象地表示了填充一个区域的着色模式。Windows 预定义了一些刷子,如BLACK_BRUSH 和WHITE_BRUSH 等,可以用下列语句来得到它们的句柄:invoke GetStockObject, WHITE_BRUSH&&&&&&& 但在这里也可以使用颜色值,Windows 已经预定义了一些颜色值,分别对应窗口各部分的颜色,如COLOR_BACKGROUND,COLOR_HIGHLIGHT,COLOR_MENU 和COLOR_WINDOW等,使用颜色值的时候,Windows 规定必须在颜色值上加1,所以程序中的指令是:
mov @stWndClass.hbrBackground,COLOR_WINDOW + 1
!对于不同二进制位组合的计算,&加&和&或&的结果是一样的,在FirstWindow程序中用CS_HREDRAW or CS_VREDRAW 来代表两个组合,若用CS_HREDRAW+CS_VREDRAW 也并没有什么不同,但强烈建议使用or,因为如果不小心指定了两个同样的风格时:CS_HREDRAW or CS_VREDRAW or CS_VREDRAW和原来的数值是一样的,而CS_HREDRAW+CS_VREDRAW+ CS_VREDRAW就不对了,因为1 or 1=1,而1+1 就等于2 了。
窗口间的消息互发
invoke PostMessage,hWnd,Msg,wParam,lParaminvoke SendMessage,hWnd,Msg,wParam,lParam
对于不同的Msg,wParam 和lParam 的含义是不同的,如对于WM_SETTEXT 是:wParam = 0; // 未定义,必须为0lParam = (LPARAM)(LPCTSTR)lpsz; // 要设置的字符串地址
具体请看代码:; Receive.asm; 从一个程序向另一个窗口程序发送消息 之 消息接收程序;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; 使用 nmake 或下列命令进行编译和链接:; ml /c /coff Receive.asm; Link /subsystem:windows Receive.obj;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.386&&.model flat,stdcall&&option casemap:none;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; Include 文件定义;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&include&&windows.incinclude&&gdi32.incincludelib&gdi32.libinclude&&user32.incincludelib&user32.libinclude&&kernel32.incincludelib&kernel32.lib;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; 数据段;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.data?
hInstance&dd&?hWinMain&dd&?szBuffer&db&512 dup (?)
&&.constszClassName&db&’MyClass’,0szCaptionMain&db&’消息接收窗口’,0
szReceive1&db&’收到 WM_SETTEXT 消息!’,0dh,0ah,0dh,0ah&&db&’字符串地址: %08x’,0dh,0ah&&db&’字符串: %s’,0dh,0ah,0szReceive2&db&’收到 WM_COPYDATA 消息!’,0dh,0ah,0dh,0ah&&db&’数据地址: %d’,0dh,0ah&&db&’数据: %s’,0dh,0ah,0;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; 代码段;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.code;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; 窗口过程;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&_ProcWinMain&proc&uses ebx edi esi,hWnd,uMsg,wParam,lParam
&&mov&eax,uMsg;********************************************************************&&.if&eax ==&WM_CLOSE&&&invoke&DestroyWindow,hWinMain&&&invoke&PostQuitMessage,NULL;********************************************************************; 收到 WM_SETTEXT 消息则将消息字符串和字符串地址显示出来;********************************************************************&&.elseif&eax ==&WM_SETTEXT&&&invoke&wsprintf,addr szBuffer,addr szReceive1,\&&&&lParam,lParam&&&invoke&MessageBox,hWnd,offset szBuffer,addr szCaptionMain,MB_OK;********************************************************************; 收到 WM_COPYDATA 消息将消息附带的数据长度和字符串数据显示出来;********************************************************************&&.elseif&eax ==&WM_COPYDATA&&&mov&eax,lParam&&&assume&eax:ptr COPYDATASTRUCT&&&invoke&wsprintf,addr szBuffer,addr szReceive2,\&&&&[eax].lpData,[eax].lpData&&&invoke&MessageBox,hWnd,offset szBuffer,addr szCaptionMain,MB_OK&&&assume&eax:nothing;********************************************************************&&.else&&&invoke&DefWindowProc,hWnd,uMsg,wParam,lParam&&&ret&&.endif;********************************************************************&&xor&eax,eax&&ret
_ProcWinMain&endp
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&_WinMain&proc&&local&@stWndClass:WNDCLASSEX&&local&@stMsg:MSG
&&invoke&GetModuleHandle,NULL&&mov&hInstance,eax&&invoke&RtlZeroMemory,addr @stWndClass,sizeof @stWndClass;********************************************************************; 注册窗口类;********************************************************************&&invoke&LoadCursor,0,IDC_ARROW&&mov&@stWndClass.hCursor,eax&&push&hInstance&&pop&@stWndClass.hInstance&&mov&@stWndClass.cbSize,sizeof WNDCLASSEX&&mov&@stWndClass.style,CS_HREDRAW or CS_VREDRAW&&mov&@stWndClass.lpfnWndProc,offset _ProcWinMain&&mov&@stWndClass.hbrBackground,COLOR_WINDOW + 1&&mov&@stWndClass.lpszClassName,offset szClassName&&invoke&RegisterClassEx,addr @stWndClass;********************************************************************; 建立并显示窗口;********************************************************************&&invoke&CreateWindowEx,WS_EX_CLIENTEDGE or WS_EX_TOPMOST,offset szClassName,offset szCaptionMain,\&&&WS_OVERLAPPEDWINDOW,\&&&50,50,200,150,\&&&NULL,NULL,hInstance,NULL&&mov&hWinMain,eax&&invoke&ShowWindow,hWinMain,SW_SHOWNORMAL&&invoke&UpdateWindow,hWinMain;********************************************************************; 消息循环;********************************************************************&&.while&TRUE&&&invoke&GetMessage,addr @stMsg,NULL,0,0&&&.break&.if eax&== 0&&&invoke&TranslateMessage,addr @stMsg&&&invoke&DispatchMessage,addr @stMsg&&.endw&&ret
_WinMain&endp;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&start:&&call&_WinMain&&invoke&ExitProcess,NULL;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&end&start
; SendMessage.asm; 从一个程序向另一个窗口程序发送消息 之 发送程序;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; 使用 nmake 或下列命令进行编译和链接:; ml /c /coff SendMessage.asm; Link /subsystem:windows SendMessage.obj;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.386&&.model flat,stdcall&&option casemap:none;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; Include 文件定义;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&include&&windows.incinclude&&user32.incincludelib&user32.libinclude&&kernel32.incincludelib&kernel32.lib;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; 数据段;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.datahWnd&&dd&?szBuffer&db&512 dup (?)stCopyData&COPYDATASTRUCT &&
&&.constszCaption&db&’发送窗口’,0szDestClass&db&’MyClass’,0&;目标窗口的窗口类szStart1&db&’按下&确定&用 SendMessage 发送 WM_SETTEXT 消息!’,0dh,0ah,0dh,0ah&&db&’字符串地址:%08x’,0dh,0ah&&db&’字符串:%s’,0szStart2&db&’SendMessage 返回!’,0dh,0ah,0dh,0ah&&db&’接下来按&确定&用 SendMessage 发送 WM_COPYDATA 消息!’,0dh,0ah,0dh,0ah&&db&’数据地址:%d’,0dh,0ah&&db&’数据:%s’,0szReturn2&db&’SendMessage 返回!’,0
szText&&db&’这是发送的测试文本’,0szNotFound&db&’目标窗口未找到,请先运行Receive.exe!’,0;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; 代码段;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.codestart:&&invoke&FindWindow,addr szDestClass,NULL&&.if&eax&&&mov&hWnd,eax&;找到目标窗口则发送消息;********************************************************************&&&invoke&wsprintf,addr szBuffer,addr szStart1,addr szText,addr szText&&&invoke&MessageBox,NULL,offset szBuffer,offset szCaption,MB_OK&&&invoke&SendMessage,hWnd,WM_SETTEXT,0,addr szText;********************************************************************&&&invoke&wsprintf,addr szBuffer,addr szStart2,addr szText,addr szText&&&invoke&MessageBox,NULL,offset szBuffer,offset szCaption,MB_OK&&&mov&stCopyData.cbData,sizeof szText&&&mov&stCopyData.lpData,offset szText&&&invoke&SendMessage,hWnd,WM_COPYDATA,0,addr stCopyData&&&invoke&MessageBox,NULL,offset szReturn2,offset szCaption,MB_OK&&.else&&&invoke&MessageBox,NULL,offset szNotFound,offset szCaption,MB_OK&&.endif&&invoke&ExitProcess,NULL;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&end&start
WM_COPYDATA
The WM_COPYDATA message is sent when an application passes data to another application.
WM_COPYDATA
wParam = (WPARAM) (HWND)
// handle of sending window
lParam = (LPARAM) (PCOPYDATASTRUCT) // pointer to structure with data
WM_SETTEXT
An application sends a WM_SETTEXT message to set the text of a window.
WM_SETTEXT
wParam = 0;
// must be zero
lParam = (LPARAM)(LPCTSTR) // address of window-text string
COPYDATASTRUCT
The COPYDATASTRUCT structure contains data to be passed to another application by the WM_COPYDATA message.
typedef struct tagCOPYDATASTRUCT {
} COPYDATASTRUCT;
FindWindow
The FindWindow function retrieves a handle to the top-level window whose class name and window name match the
specified strings. This function does not search child windows. This function does not perform a case-sensitive search.
HWND FindWindow(
LPCTSTR lpClassName,
// pointer to class name
LPCTSTR lpWindowName
// pointer to window name
; MsgWindow.asm
; 将窗口的消息流程显示到 Notepad 进程的编辑窗口中;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; 使用 nmake 或下列命令进行编译和链接:; ml /c /coff MsgWindow.asm; Link /subsystem:windows MsgWindow.obj;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.386&&.model flat,stdcall&&option casemap:none;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; Include 文件定义;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&include&&windows.incinclude&&gdi32.incincludelib&gdi32.libinclude&&user32.incincludelib&user32.libinclude&&kernel32.incincludelib&kernel32.lib;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; 数据段;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.data?
hInstance&dd&?hWinMain&dd&?
&&.constszClassName&db&'MyClass',0szCaptionMain&db&'Message Tester',0;********************************************************************; 消息ID列表;********************************************************************dwMsgTable&dd&WM_NULL&&dd&WM_CREATE&&dd&WM_DESTROY&&dd&WM_MOVE&&dd&WM_SIZE&&dd&WM_ACTIVATE&&dd&WM_SETFOCUS&&dd&WM_KILLFOCUS&&dd&WM_ENABLE&&dd&WM_SETREDRAW&&dd&WM_SETTEXT&&dd&WM_GETTEXT&&dd&WM_GETTEXTLENGTH&&dd&WM_PAINT&&dd&WM_CLOSE&&dd&WM_QUERYENDSESSION&&dd&WM_QUIT&&dd&WM_QUERYOPEN&&dd&WM_ERASEBKGND&&dd&WM_SYSCOLORCHANGE&&dd&WM_ENDSESSION&&dd&WM_SHOWWINDOW&&dd&WM_WININICHANGE&&dd&WM_DEVMODECHANGE&&dd&WM_ACTIVATEAPP&&dd&WM_FONTCHANGE&&dd&WM_TIMECHANGE&&dd&WM_CANCELMODE&&dd&WM_SETCURSOR&&dd&WM_MOUSEACTIVATE&&dd&WM_CHILDACTIVATE&&dd&WM_QUEUESYNC&&dd&WM_GETMINMAXINFO&&dd&WM_PAINTICON&&dd&WM_ICONERASEBKGND&&dd&WM_NEXTDLGCTL&&dd&WM_SPOOLERSTATUS&&dd&WM_DRAWITEM&&dd&WM_MEASUREITEM&&dd&WM_DELETEITEM&&dd&WM_VKEYTOITEM&&dd&WM_CHARTOITEM&&dd&WM_SETFONT&&dd&WM_GETFONT&&dd&WM_SETHOTKEY&&dd&WM_GETHOTKEY&&dd&WM_QUERYDRAGICON&&dd&WM_COMPAREITEM&&dd&WM_GETOBJECT&&dd&WM_COMPACTING&&dd&WM_OTHERWINDOWCREATED&&dd&WM_OTHERWINDOWDESTROYED&&dd&WM_COMMNOTIFY&&dd&WM_WINDOWPOSCHANGING&&dd&WM_WINDOWPOSCHANGED&&dd&WM_POWER&&dd&WM_COPYDATA&&dd&WM_CANCELJOURNAL&&dd&WM_NOTIFY&&dd&WM_INPUTLANGCHANGEREQUEST&&dd&WM_INPUTLANGCHANGE&&dd&WM_TCARD&&dd&WM_HELP&&dd&WM_USERCHANGED&&dd&WM_NOTIFYFORMAT&&dd&WM_CONTEXTMENU&&dd&WM_STYLECHANGING&&dd&WM_STYLECHANGED&&dd&WM_DISPLAYCHANGE&&dd&WM_GETICON&&dd&WM_SETICON&&dd&WM_NCCREATE&&dd&WM_NCDESTROY&&dd&WM_NCCALCSIZE&&dd&WM_NCHITTEST&&dd&WM_NCPAINT&&dd&WM_NCACTIVATE&&dd&WM_GETDLGCODE&&dd&WM_SYNCPAINT&&dd&WM_NCMOUSEMOVE&&dd&WM_NCLBUTTONDOWN&&dd&WM_NCLBUTTONUP&&dd&WM_NCLBUTTONDBLCLK&&dd&WM_NCRBUTTONDOWN&&dd&WM_NCRBUTTONUP&&dd&WM_NCRBUTTONDBLCLK&&dd&WM_NCMBUTTONDOWN&&dd&WM_NCMBUTTONUP&&dd&WM_NCMBUTTONDBLCLK&&dd&WM_KEYDOWN&&dd&WM_KEYUP&&dd&WM_CHAR&&dd&WM_DEADCHAR&&dd&WM_SYSKEYDOWN&&dd&WM_SYSKEYUP&&dd&WM_SYSCHAR&&dd&WM_SYSDEADCHAR&&dd&WM_KEYLAST&&dd&WM_INITDIALOG&&dd&WM_COMMAND&&dd&WM_SYSCOMMAND&&dd&WM_TIMER&&dd&WM_HSCROLL&&dd&WM_VSCROLL&&dd&WM_INITMENU&&dd&WM_INITMENUPOPUP&&dd&WM_MENUSELECT&&dd&WM_MENUCHAR&&dd&WM_ENTERIDLE&&dd&WM_CTLCOLORMSGBOX&&dd&WM_CTLCOLOREDIT&&dd&WM_CTLCOLORLISTBOX&&dd&WM_CTLCOLORBTN&&dd&WM_CTLCOLORDLG&&dd&WM_CTLCOLORSCROLLBAR&&dd&WM_CTLCOLORSTATIC&&dd&WM_MOUSEMOVE&&dd&WM_LBUTTONDOWN&&dd&WM_LBUTTONUP&&dd&WM_LBUTTONDBLCLK&&dd&WM_RBUTTONDOWN&&dd&WM_RBUTTONUP&&dd&WM_RBUTTONDBLCLK&&dd&WM_MBUTTONDOWN&&dd&WM_MBUTTONUP&&dd&WM_MBUTTONDBLCLK&&dd&WM_MOUSELAST&&dd&WM_PARENTNOTIFY&&dd&WM_ENTERMENULOOP&&dd&WM_EXITMENULOOP&&dd&WM_MDICREATE&&dd&WM_MDIDESTROY&&dd&WM_MDIACTIVATE&&dd&WM_MDIRESTORE&&dd&WM_MDINEXT&&dd&WM_MDIMAXIMIZE&&dd&WM_MDITILE&&dd&WM_MDICASCADE&&dd&WM_MDIICONARRANGE&&dd&WM_MDIGETACTIVE&&dd&WM_MDISETMENU&&dd&WM_DROPFILES&&dd&WM_MDIREFRESHMENU&&dd&WM_CUT&&dd&WM_COPY&&dd&WM_PASTE&&dd&WM_CLEAR&&dd&WM_UNDO&&dd&WM_RENDERFORMAT&&dd&WM_RENDERALLFORMATS&&dd&WM_DESTROYCLIPBOARD&&dd&WM_DRAWCLIPBOARD&&dd&WM_PAINTCLIPBOARD&&dd&WM_VSCROLLCLIPBOARD&&dd&WM_SIZECLIPBOARD&&dd&WM_ASKCBFORMATNAME&&dd&WM_CHANGECBCHAIN&&dd&WM_HSCROLLCLIPBOARD&&dd&WM_QUERYNEWPALETTE&&dd&WM_PALETTEISCHANGING&&dd&WM_PALETTECHANGED&&dd&WM_HOTKEY&&dd&WM_PRINT&&dd&WM_PRINTCLIENT&&dd&WM_PENWINFIRST&&dd&WM_PENWINLAST&&dd&WM_MENURBUTTONUP&&dd&WM_MENUDRAG&&dd&WM_MENUGETOBJECT&&dd&WM_UNINITMENUPOPUP&&dd&WM_MENUCOMMAND&&dd&WM_NEXTMENU&&dd&WM_SIZING&&dd&WM_CAPTURECHANGED&&dd&WM_MOVING&&dd&WM_POWERBROADCAST&&dd&WM_DEVICECHANGE&&dd&WM_ENTERSIZEMOVE&&dd&WM_EXITSIZEMOVEMSG_TABLE_LEN&equ&($ - dwMsgTable)/sizeof dword;********************************************************************; 消息名称字符串列表;********************************************************************MSG_STRING_LEN&equ&sizeof szStringTableszStringTable&db&'WM_NULL&&&&&&&&&&&&&&&&& ',0&&db&'WM_CREATE&&&&&&&&&&&&&&& ',0&&db&'WM_DESTROY&&&&&&&&&&&&&& ',0&&db&'WM_MOVE&&&&&&&&&&&&&&&&& ',0&&db&'WM_SIZE&&&&&&&&&&&&&&&&& ',0&&db&'WM_ACTIVATE&&&&&&&&&&&&& ',0&&db&'WM_SETFOCUS&&&&&&&&&&&&& ',0&&db&'WM_KILLFOCUS&&&&&&&&&&&& ',0&&db&'WM_ENABLE&&&&&&&&&&&&&&& ',0&&db&'WM_SETREDRAW&&&&&&&&&&&& ',0&&db&'WM_SETTEXT&&&&&&&&&&&&&& ',0&&db&'WM_GETTEXT&&&&&&&&&&&&&& ',0&&db&'WM_GETTEXTLENGTH&&&&&&&& ',0&&db&'WM_PAINT&&&&&&&&&&&&&&&& ',0&&db&'WM_CLOSE&&&&&&&&&&&&&&&& ',0&&db&'WM_QUERYENDSESSION&&&&&& ',0&&db&'WM_QUIT&&&&&&&&&&&&&&&&& ',0&&db&'WM_QUERYOPEN&&&&&&&&&&&& ',0&&db&'WM_ERASEBKGND&&&&&&&&&&& ',0&&db&'WM_SYSCOLORCHANGE&&&&&&& ',0&&db&'WM_ENDSESSION&&&&&&&&&&& ',0&&db&'WM_SHOWWINDOW&&&&&&&&&&& ',0&&db&'WM_WININICHANGE&&&&&&&&& ',0&&db&'WM_DEVMODECHANGE&&&&&&&& ',0&&db&'WM_ACTIVATEAPP&&&&&&&&&& ',0&&db&'WM_FONTCHANGE&&&&&&&&&&& ',0&&db&'WM_TIMECHANGE&&&&&&&&&&& ',0&&db&'WM_CANCELMODE&&&&&&&&&&& ',0&&db&'WM_SETCURSOR&&&&&&&&&&&& ',0&&db&'WM_MOUSEACTIVATE&&&&&&&& ',0&&db&'WM_CHILDACTIVATE&&&&&&&& ',0&&db&'WM_QUEUESYNC&&&&&&&&&&&& ',0&&db&'WM_GETMINMAXINFO&&&&&&&& ',0&&db&'WM_PAINTICON&&&&&&&&&&&& ',0&&db&'WM_ICONERASEBKGND&&&&&&& ',0&&db&'WM_NEXTDLGCTL&&&&&&&&&&& ',0&&db&'WM_SPOOLERSTATUS&&&&&&&& ',0&&db&'WM_DRAWITEM&&&&&&&&&&&&& ',0&&db&'WM_MEASUREITEM&&&&&&&&&& ',0&&db&'WM_DELETEITEM&&&&&&&&&&& ',0&&db&'WM_VKEYTOITEM&&&&&&&&&&& ',0&&db&'WM_CHARTOITEM&&&&&&&&&&& ',0&&db&'WM_SETFONT&&&&&&&&&&&&&& ',0&&db&'WM_GETFONT&&&&&&&&&&&&&& ',0&&db&'WM_SETHOTKEY&&&&&&&&&&&& ',0&&db&'WM_GETHOTKEY&&&&&&&&&&&& ',0&&db&'WM_QUERYDRAGICON&&&&&&&& ',0&&db&'WM_COMPAREITEM&&&&&&&&&& ',0&&db&'WM_GETOBJECT&&&&&&&&&&&& ',0&&db&'WM_COMPACTING&&&&&&&&&&& ',0&&db&'WM_OTHERWINDOWCREATED&&& ',0&&db&'WM_OTHERWINDOWDESTROYED& ',0&&db&'WM_COMMNOTIFY&&&&&&&&&&& ',0&&db&'WM_WINDOWPOSCHANGING&&&& ',0&&db&'WM_WINDOWPOSCHANGED&&&&& ',0&&db&'WM_POWER&&&&&&&&&&&&&&&& ',0&&db&'WM_COPYDATA&&&&&&&&&&&&& ',0&&db&'WM_CANCELJOURNAL&&&&&&&& ',0&&db&'WM_NOTIFY&&&&&&&&&&&&&&& ',0&&db&'WM_INPUTLANGCHANGEREQUEST',0&&db&'WM_INPUTLANGCHANGE&&&&&& ',0&&db&'WM_TCARD&&&&&&&&&&&&&&&& ',0&&db&'WM_HELP&&&&&&&&&&&&&&&&& ',0&&db&'WM_USERCHANGED&&&&&&&&&& ',0&&db&'WM_NOTIFYFORMAT&&&&&&&&& ',0&&db&'WM_CONTEXTMENU&&&&&&&&&& ',0&&db&'WM_STYLECHANGING&&&&&&&& ',0&&db&'WM_STYLECHANGED&&&&&&&&& ',0&&db&'WM_DISPLAYCHANGE&&&&&&&& ',0&&db&'WM_GETICON&&&&&&&&&&&&&& ',0&&db&'WM_SETICON&&&&&&&&&&&&&& ',0&&db&'WM_NCCREATE&&&&&&&&&&&&& ',0&&db&'WM_NCDESTROY&&&&&&&&&&&& ',0&&db&'WM_NCCALCSIZE&&&&&&&&&&& ',0&&db&'WM_NCHITTEST&&&&&&&&&&&& ',0&&db&'WM_NCPAINT&&&&&&&&&&&&&& ',0&&db&'WM_NCACTIVATE&&&&&&&&&&& ',0&&db&'WM_GETDLGCODE&&&&&&&&&&& ',0&&db&'WM_SYNCPAINT&&&&&&&&&&&& ',0&&db&'WM_NCMOUSEMOVE&&&&&&&&&& ',0&&db&'WM_NCLBUTTONDOWN&&&&&&&& ',0&&db&'WM_NCLBUTTONUP&&&&&&&&&& ',0&&db&'WM_NCLBUTTONDBLCLK&&&&&& ',0&&db&'WM_NCRBUTTONDOWN&&&&&&&& ',0&&db&'WM_NCRBUTTONUP&&&&&&&&&& ',0&&db&'WM_NCRBUTTONDBLCLK&&&&&& ',0&&db&'WM_NCMBUTTONDOWN&&&&&&&& ',0&&db&'WM_NCMBUTTONUP&&&&&&&&&& ',0&&db&'WM_NCMBUTTONDBLCLK&&&&&& ',0&&db&'WM_KEYDOWN&&&&&&&&&&&&&& ',0&&db&'WM_KEYUP&&&&&&&&&&&&&&&& ',0&&db&'WM_CHAR&&&&&&&&&&&&&&&&& ',0&&db&'WM_DEADCHAR&&&&&&&&&&&&& ',0&&db&'WM_SYSKEYDOWN&&&&&&&&&&& ',0&&db&'WM_SYSKEYUP&&&&&&&&&&&&& ',0&&db&'WM_SYSCHAR&&&&&&&&&&&&&& ',0&&db&'WM_SYSDEADCHAR&&&&&&&&&& ',0&&db&'WM_KEYLAST&&&&&&&&&&&&&& ',0&&db&'WM_INITDIALOG&&&&&&&&&&& ',0&&db&'WM_COMMAND&&&&&&&&&&&&&& ',0&&db&'WM_SYSCOMMAND&&&&&&&&&&& ',0&&db&'WM_TIMER&&&&&&&&&&&&&&&& ',0&&db&'WM_HSCROLL&&&&&&&&&&&&&& ',0&&db&'WM_VSCROLL&&&&&&&&&&&&&& ',0&&db&'WM_INITMENU&&&&&&&&&&&&& ',0&&db&'WM_INITMENUPOPUP&&&&&&&& ',0&&db&'WM_MENUSELECT&&&&&&&&&&& ',0&&db&'WM_MENUCHAR&&&&&&&&&&&&& ',0&&db&'WM_ENTERIDLE&&&&&&&&&&&& ',0&&db&'WM_CTLCOLORMSGBOX&&&&&&& ',0&&db&'WM_CTLCOLOREDIT&&&&&&&&& ',0&&db&'WM_CTLCOLORLISTBOX&&&&&& ',0&&db&'WM_CTLCOLORBTN&&&&&&&&&& ',0&&db&'WM_CTLCOLORDLG&&&&&&&&&& ',0&&db&'WM_CTLCOLORSCROLLBAR&&&& ',0&&db&'WM_CTLCOLORSTATIC&&&&&&& ',0&&db&'WM_MOUSEMOVE&&&&&&&&&&&& ',0&&db&'WM_LBUTTONDOWN&&&&&&&&&& ',0&&db&'WM_LBUTTONUP&&&&&&&&&&&& ',0&&db&'WM_LBUTTONDBLCLK&&&&&&&& ',0&&db&'WM_RBUTTONDOWN&&&&&&&&&& ',0&&db&'WM_RBUTTONUP&&&&&&&&&&&& ',0&&db&'WM_RBUTTONDBLCLK&&&&&&&& ',0&&db&'WM_MBUTTONDOWN&&&&&&&&&& ',0&&db&'WM_MBUTTONUP&&&&&&&&&&&& ',0&&db&'WM_MBUTTONDBLCLK&&&&&&&& ',0&&db&'WM_MOUSELAST&&&&&&&&&&&& ',0&&db&'WM_PARENTNOTIFY&&&&&&&&& ',0&&db&'WM_ENTERMENULOOP&&&&&&&& ',0&&db&'WM_EXITMENULOOP&&&&&&&&& ',0&&db&'WM_MDICREATE&&&&&&&&&&&& ',0&&db&'WM_MDIDESTROY&&&&&&&&&&& ',0&&db&'WM_MDIACTIVATE&&&&&&&&&& ',0&&db&'WM_MDIRESTORE&&&&&&&&&&& ',0&&db&'WM_MDINEXT&&&&&&&&&&&&&& ',0&&db&'WM_MDIMAXIMIZE&&&&&&&&&& ',0&&db&'WM_MDITILE&&&&&&&&&&&&&& ',0&&db&'WM_MDICASCADE&&&&&&&&&&& ',0&&db&'WM_MDIICONARRANGE&&&&&&& ',0&&db&'WM_MDIGETACTIVE&&&&&&&&& ',0&&db&'WM_MDISETMENU&&&&&&&&&&& ',0&&db&'WM_DROPFILES&&&&&&&&&&&& ',0&&db&'WM_MDIREFRESHMENU&&&&&&& ',0&&db&'WM_CUT&&&&&&&&&&&&&&&&&& ',0&&db&'WM_COPY&&&&&&&&&&&&&&&&& ',0&&db&'WM_PASTE&&&&&&&&&&&&&&&& ',0&&db&'WM_CLEAR&&&&&&&&&&&&&&&& ',0&&db&'WM_UNDO&&&&&&&&&&&&&&&&& ',0&&db&'WM_RENDERFORMAT&&&&&&&&& ',0&&db&'WM_RENDERALLFORMATS&&&&& ',0&&db&'WM_DESTROYCLIPBOARD&&&&& ',0&&db&'WM_DRAWCLIPBOARD&&&&&&&& ',0&&db&'WM_PAINTCLIPBOARD&&&&&&& ',0&&db&'WM_VSCROLLCLIPBOARD&&&&& ',0&&db&'WM_SIZECLIPBOARD&&&&&&&& ',0&&db&'WM_ASKCBFORMATNAME&&&&&& ',0&&db&'WM_CHANGECBCHAIN&&&&&&&& ',0&&db&'WM_HSCROLLCLIPBOARD&&&&& ',0&&db&'WM_QUERYNEWPALETTE&&&&&& ',0&&db&'WM_PALETTEISCHANGING&&&& ',0&&db&'WM_PALETTECHANGED&&&&&&& ',0&&db&'WM_HOTKEY&&&&&&&&&&&&&&& ',0&&db&'WM_PRINT&&&&&&&&&&&&&&&& ',0&&db&'WM_PRINTCLIENT&&&&&&&&&& ',0&&db&'WM_PENWINFIRST&&&&&&&&&& ',0&&db&'WM_PENWINLAST&&&&&&&&&&& ',0&&db&'WM_MENURBUTTONUP&&&&&&&& ',0&&db&'WM_MENUDRAG&&&&&&&&&&&&& ',0&&db&'WM_MENUGETOBJECT&&&&&&&& ',0&&db&'WM_UNINITMENUPOPUP&&&&&& ',0&&db&'WM_MENUCOMMAND&&&&&&&&&& ',0&&db&'WM_NEXTMENU&&&&&&&&&&&&& ',0&&db&'WM_SIZING&&&&&&&&&&&&&&& ',0&&db&'WM_CAPTURECHANGED&&&&&&& ',0&&db&'WM_MOVING&&&&&&&&&&&&&&& ',0&&db&'WM_POWERBROADCAST&&&&&&& ',0&&db&'WM_DEVICECHANGE&&&&&&&&& ',0&&db&'WM_ENTERSIZEMOVE&&&&&&&& ',0&&db&'WM_EXITSIZEMOVE&&&&&&&&& ',0;********************************************************************szDestClass&db&'Notepad',0szFormat&db&'WndProc: [%04x]%s %08x %08x',0dh,0szCreateWindow1&db&'Creating Window...',0dh,0szCreateWindow2&db&'CreateWindow end',0dh,0szShowWindow1&db&'Showing Window...',0dh,0szShowWindow2&db&'ShowWindow end',0dh,0szUpdateWindow1&db&'Updating Window...',0dh,0szUpdateWindow2&db&'UpdateWindow end',0dh,0szGetMsg1&db&'Getting Message...',0dh,0szGetMsg2&db&'[%04x]Message gotten',0dh,0szDispatchMsg1&db&'Dispatching Message...',0dh,0szDispatchMsg2&db&'DispatchMessage end',0dh,0;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; 代码段;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.code;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&_SendtoNotepad&proc&_lpsz&&local&@hWinNotepad
&&pushad&&invoke&FindWindow,addr szDestClass,NULL&&.if&eax&&&mov&ecx,eax&&&invoke&ChildWindowFromPoint,ecx,20,20&&.endif&&.if&eax&&&mov&@hWinNotepad,eax&&&mov&esi,_lpsz&&&@@:&&&lodsb&&&or&al,al&&&jz&@F&&&movzx&eax,al&&&invoke&PostMessage,@hWinNotepad,WM_CHAR,eax,1&&&jmp&@B&&&@@:&&.endif&&popad&&ret
_SendtoNotepad&endp;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&_ShowMessage&proc&_uMsg,_wParam,_lParam&&local&@szBuffer[128]:byte
&&pushad;********************************************************************; 查找消息的说明字符串;********************************************************************&&mov&eax,_uMsg&&mov&edi,offset dwMsgTable&&mov&ecx,MSG_TABLE_LEN&&cld&&repnz&scasd&&.if&ZERO?&&&sub&edi,offset dwMsgTable + sizeof dword&&&shr&edi,2&&&mov&eax,edi&&&mov&ecx,MSG_STRING_LEN&&&mul&ecx&&&add&eax,offset szStringTable;********************************************************************; 翻译格式并发送到 Notepad 窗口;********************************************************************&&&invoke&wsprintf,addr @szBuffer,addr szFormat,\&&&&_uMsg,eax,_wParam,_lParam&&&invoke&_SendtoNotepad,addr @szBuffer&&.endif&&popad&&ret
_ShowMessage&endp;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; 窗口过程;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&_ProcWinMain&proc&uses ebx edi esi,hWnd,uMsg,wParam,lParam
&&invoke&_ShowMessage,uMsg,wParam,lParam&&mov&eax,uMsg;********************************************************************&&.if&eax ==&WM_CLOSE&&&invoke&DestroyWindow,hWinMain&&&invoke&PostQuitMessage,NULL;********************************************************************&&.else&&&invoke&DefWindowProc,hWnd,uMsg,wParam,lParam&&&ret&&.endif;********************************************************************&&xor&eax,eax&&ret
_ProcWinMain&endp
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&_WinMain&proc&&local&@szBuffer[128]:byte&&local&@stWndClass:WNDCLASSEX&&local&@stMsg:MSG
&&invoke&GetModuleHandle,NULL&&mov&hInstance,eax&&invoke&RtlZeroMemory,addr @stWndClass,sizeof @stWndClass;********************************************************************; 注册窗口类;********************************************************************&&invoke&LoadCursor,0,IDC_ARROW&&mov&@stWndClass.hCursor,eax&&push&hInstance&&pop&@stWndClass.hInstance&&mov&@stWndClass.cbSize,sizeof WNDCLASSEX&&mov&@stWndClass.style,CS_HREDRAW or CS_VREDRAW&&mov&@stWndClass.lpfnWndProc,offset _ProcWinMain&&mov&@stWndClass.hbrBackground,COLOR_WINDOW + 1&&mov&@stWndClass.lpszClassName,offset szClassName&&invoke&RegisterClassEx,addr @stWndClass;********************************************************************; 建立并显示窗口;********************************************************************&&invoke&_SendtoNotepad,addr szCreateWindow1&&invoke&CreateWindowEx,WS_EX_CLIENTEDGE&,offset szClassName,offset szCaptionMain,\&&&WS_OVERLAPPEDWINDOW,\&&&50,50,100,100,\&&&NULL,NULL,hInstance,NULL&&mov&hWinMain,eax&&invoke&_SendtoNotepad,addr szCreateWindow2
&&invoke&_SendtoNotepad,addr szShowWindow1&&invoke&ShowWindow,hWinMain,SW_SHOWNORMAL&&invoke&_SendtoNotepad,addr szShowWindow2
&&invoke&_SendtoNotepad,addr szUpdateWindow1&&invoke&UpdateWindow,hWinMain&&invoke&_SendtoNotepad,addr szUpdateWindow2;********************************************************************; 消息循环;********************************************************************&&.while&TRUE&&&invoke&_SendtoNotepad,addr szGetMsg1&&&invoke&GetMessage,addr @stMsg,NULL,0,0&&&push&eax&&&invoke&wsprintf,addr @szBuffer,addr szGetMsg2,@stMsg.message&&&invoke&_SendtoNotepad,addr @szBuffer&&&pop&eax&&&.break&.if eax&== 0
&&&invoke&TranslateMessage,addr @stMsg
&&&invoke&_SendtoNotepad,addr szDispatchMsg1&&&invoke&DispatchMessage,addr @stMsg&&&invoke&_SendtoNotepad,addr szDispatchMsg2&&.endw&&ret
_WinMain&endp;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&start:&&call&_WinMain&&invoke&ExitProcess,NULL;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&end&start
— dugu @ 10:40 pm
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; Hello.asm; 使用 Win32ASM 写的 Hello, world 程序;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; 使用 nmake 或下列命令进行编译和链接:; ml /c /coff Hello.asm; Link /subsystem:windows Hello.obj;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
.386.model flat,stdcalloption casemap:none
include& windows.incinclude& user32.incincludelib user32.libinclude& kernel32.incincludelib kernel32.lib
szCaption db ‘A MessageBox !’,0szText& db ‘Hello, World !’,0
& .codestart:& invoke MessageBox,NULL,offset szText,offset szCaption,MB_YESNO& invoke ExitProcess,NULLend start&&.386& ;指定指令集,若是带有.386p的话,则表示可使用特权指令&
&.model flat,stdcall&;定义程序的工作模式,对于Win32程序来说,只有一种内存模式,即flat模式。如果定义了 .model flat,MASM 自动为各种段寄存器做了如下定义(Assume cs:FlAT,ds:Flat,ss:FALT,es:FLAT,fs:ERROR,gs:ERROR)。也就是说,CS,DS,ES 和SS 段全部使用平坦模式,FS 和GS 寄存器默认不使用,这时若在源程序中使用FS 或GS,在编译时会报错。如果有必要使用它们,只需在使用前用下面的语句声明一下就可以了(Assume fs:nothing,gs:nothing或者是Assume fs:flat,gs:flat)。而stdcall指出了调用子程序或Win32 API 时参数传递的次序和堆栈平衡的方法,相对于stdcall,不同的语言类型还有C,SysCall,BASIC,FORTRAN 和PASCAL,虽然各种高级语言在调用子程序时都是使用堆栈来传递参数,但它们的处理方法各有不同。&&option casemap:none;用option 语句定义的选项有很多,如option language 定义和option segment 定义等,在Win32 汇编程序中,需要的只是定义option casemap:none,这个语句定义了程序中的变量和子程序名是否对大小写敏感,由于Win32 API 中的API 名称是区分大小写的,所以必须指定这个选项,否则在调用API 的时候会有问题。;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; Include 文件定义;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&include& windows.inc;inc文件包含一些函数声明include& user32.incincludelib user32.lib ;告诉链接程序使用了哪些函数库include& kernel32.incincludelib kernel32.lib
;为了使程序更有移植性,在源程序中一般不直接指明使用Unicode 还是ANSI 版本,而是使用宏汇编中的条件汇编功能来统一替换,如在源程序中使用Messagebox,但在头文件中定义:if UNICODEMessageBox equ &MessageBoxW&elseMessageBox equ &MessageBoxA&endif所有涉及版本问题的API 都可以按此方法定义,然后在源程序的头部指定UNICODE=1 或UNICODE=0,重新编译后就能产生不同的版本。;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; 数据段;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
;Win32 中实际上只有代码和数据之分,.data,.data?和 .const 是数据段,.code 是代码段,和DOS 汇编不同,Win32 汇编不必考虑堆栈,系统会为程序分配一个向下扩展的、足够大的段作为堆栈段,所以 .stack 段定义常常被忽略。
;程序中的数据定义一般可以归纳为3 类:
;第一类是可读可写的已定义变量。这些数据在源程序中已经被定义了初始值,而且在程序的执行中有可能被更改,如一些标志等,这些数据必须定义在 .data 段中,.data 段是已初始化数据段,其中定义的数据是可读可写的,在程序装入完成的时候,这些值就已经在内存中了,.data 段存放在可执行文件的_DATA 节区内。
;第二类是可读可写的未定义变量。这些变量一般是当做缓冲区或者在程序执行后才开始使用的,这些数据可以定义在 .data 段中,也可以定义在 .data?段中,但一般把它放到 .data?段中。虽然定义在这两种段中都可以正常使用,但定义在 .data?段中不会增大 .exe 文件的大小。
;第三类数据是一些常量。如一些要显示的字符串信息,它们在程序装入的时候也已经有效,但在整个执行过程中不需要修改,这些数据可以放在 .const 段中,.const 段是常量段,它是可读不可写的。。一般为了方便起见,在小程序中常常把常量一起定义到 .data 段中,而不另外定义一 .const 段。在程序中如果不小心写了对 .const 段中的数据做写操作的指令,会引起保护错误,Windows 会显示一个如图3.2 所示的提示框并结束程序。
;如果不怕程序可读性不佳的话,把 .const 段中定义的东西混到 .code 段中去也可以正常使用,因为 .code 段也是可以读的。&&.data
szCaption&db&’A MessageBox !’,0szText&&db&’Hello, World !’,0;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&; 代码段;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
;.code 段是代码段,所有的指令都必须写在代码段中,在可执行文件中,代码段是放在_TEXT 节区中的。Win32 环境中的数据段是不可执行的,只有代码段有可执行的属性。对于工作在特权级3 的应用程序来说,.code 段是不可写的。&&.codestart: ;相当于程序入口
;一个源程序不必非要指定入口标号,这时候可以把开始地址忽略不写,这种情况发生在编写多模块程序的单个模块的时候。当分开写多个程序模块时,每个模块的源程序中也可以包括 .data,.data?,.const 和 .code 段,结构就和上面的Win32 Hello World 一样,只是其他模块最后的end 语句必须不带开始地址。当最后把多个模块链接在一起的时候,只能有一个主模块指定入口地址,在多个模块中指定入口地址或者没有一个模块指定了入口地址,链接程序都会报错。&&invoke&MessageBox,NULL,offset szText,offset szCaption,MB_YESNO&&invoke&ExitProcess,NULL ;利用invoke伪指令,实现调用API;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&end&start ;所有的代码都必须在end 之前完成
变量的类型
&十字节BCD 码
&有符号字节
&有符号双字
&signdword
&单精度浮点数
&双精度浮点数
&10 字节浮点数
&&&&&&&& 全局变量的作用域是整个程序,Win32 汇编的全局变量定义在 .data 或 .data?段内,可以同时定义变量的类型和长度,格式是:变量名 类型 初始值1,初始值2,&&变量名 类型 重复数量 dup (初始值1,初始值2,&&)
&&&&&&&& 所有使用到变量类型的情况中,只有定义全局变量的时候类型才可以用缩写。
&&&&&&&& 全局变量在定义中既可以指定初值,也可以只用问号预留空间,在 .data?段中,只能用问号预留空间,因为 .data?不能指定初始值,这里就有一个问题:既然可以用问号预留空间,那么在实际运行的时候,这个未初始化的值是随机的还是确定的呢?在全局变量中,这个值就是0,所以用问号指定的全局变量如果要以0 为初始值的话,在程序中可以不必为它赋值。
&&&&&&&& 局部变量的作用域是单个子程序,在进入子程序的时候,通过修改堆栈指针esp 来预留出需要的空间,在用ret 指令返回主程序之前,同样通过恢复esp 丢弃这些空间,这些变量就随之无效了。它的缺点就是因为空间是临时分配的,所以无法定义含有初始化值的变量,对局部变量的初始化一般在子程序中由指令完成。
&&&&&&&& local 变量名1[[重复数量]][:类型],变量名2[[重复数量]][:类型]&&
local loc1[1024]:byte ;例1,定义了一个 1 024 字节长的局部变量 loc1。local loc2 ;例2,定义了一个名为 loc2 的局部变量,类型是默认值 dword。local loc3:WNDCLASS ;例3,定义了一个 WNDCLASS 数据结构,名为 loc3。
&&&&&&&& 需要注意的是,既然局部变量的空间临时分配的,那么必然需要在堆栈上进行操作,以便完成变量的赋值与释放。下面这两段代码展示了局部变量是如何在堆栈中操作的:
TestProc proc& ;由call调用,这时call指令会把返回地址堆入栈(返回地址存放在ebp+4),之后,原来的ebp值也会入栈,地址为ebplocal @loc1:dword,@loc2:word local @loc3:bytemov eax,@loc1;第一个局部变量,入栈地址为ebp-4mov ax,@loc2;第二个局部变量,入栈地址为ebp-6mov al,@loc3;第三个局部变量,入栈地址为ebp-7retTestProc endp
: push ebp ;保护ebp值,入栈:BEC mov ebp, esp ;由于进入子程序后,esp值经常会被改变,故程序使用ebp作指针:C4F8 add esp, FFFFFFF8:B45FC mov eax, dword ptr [ebp-04]:B45FA mov ax, word ptr [ebp-06]:A45F9 mov al, byte ptr [ebp-07]: leave ;伪指令,完成mov esp,ebp,pop ebp操作: ret
&&&&&&&& 在程序退出的时候,必须把正确的esp 设置回去,否则,ret 指令会从堆栈中取出错误的地址返回,看程序可以发现,ebp 就是正确的esp 值,因为子程序开始的时候已经有一句movebp,esp,所以要返回的时候只要先mov esp,ebp,然后再pop ebp,堆栈就是正确的了。&&&&&&&&&在80386 指令集中有一条指令可以在一句中实现这个功能,就是leave 指令,所以,编译器在ret 指令之前只使用了一句leave 指令。明白了局部变量使用的原理,就很容易理解使用时的注意点:ebp 寄存器是关键,它起到保存原始esp 的作用,并随时用做存取局部变量的指针基址,所以在任何时刻,不要尝试把ebp 用于别的用途,否则会带来意想不到的后果。&&&&&&&& Win32 汇编中局部变量的使用方法可以解释一个很有趣的现象:在DOS 汇编的时候,如果在子程序中的push 指令和pop 指令不配对,那么返回的时候ret 指令从堆栈里得到的肯定是错误的返回地址,程序也就死掉了。但在Win32 汇编中,push 指令和pop指令不配对可能在逻辑上产生错误,却不会影响子程序正常返回,原因就是在返回的时候esp 不是靠相同数量的push 和pop 指令来保持一致的,而是靠leave 指令从保存在ebp中的原始值中取回来的,也就是说,即使把esp 改得一塌糊涂也不会影响到子程序的返回,当然,&窍门&就在ebp,把ebp 改掉,程序就玩完了!
&&&&&&&& 局部变量是无法在定义的时候指定初始化值的,因为local 伪指令只是简单地把空间给留出来,那么开始使用时它里面是什么值呢?和全局变量不一样,局部变量的起始值是随机的,是其他子程序执行后在堆栈里留下的垃圾,所以,对局部变量的值一定要初始化,特别是定义为结构后当参数传递给API 函数的时候。
sizeof 伪指令可以取得变量、数据类型或数据结构以字节为单位的长度,lengthof 可以取得变量中数据的项数。;注意二者不同的使用范围!
!如果为了把Hello 和World 分两行定义,szHello 是这样定义的:szHello db ‘Hello’,0dh,0ahdb ‘World’,0那么sizeof szHello 是多少呢?注意!是7 而不是13,MASM 中的变量定义只认一行,后一行db ‘World’,0 实际上是另一个没有名称的数据定义,编译器认为sizeof szHello 是第一行字符的数量。虽然把szHello 的地址当参数传给MessageBox 等函数显示时会把两行都显示出来,但严格地说这是越界使用变量。虽然在实际的应用中这样定义长字符串的用法很普遍,因为如果要显示一屏幕帮助,一行是不够的,但要注意的是:要用到这种字符串的长度时,千万不要用sizeof 去表示,最好是在程序中用lstrlen 函数去计算。
获取变量地址
&&&&&&&& 对于全局变量,它的地址在编译的时候已经由编译器确定了,它的用法大家都不陌生:mov 寄存器,offset 变量名&&&&&&&& 其中offset 是取变量地址的伪操作符,和sizeof 伪操作符一样,它仅把变量的地址代到指令中去,这个操作是在编译时而不是在运行时完成的。
&&&&&&&& 但是对于局部变量,它的地址空间是在程序执行时动态给态给定的,所以不可能由offset来取地址!而使用:
lea eax,[ebp-4]该指令可以在运行时按照ebp 的值实际计算出地址放到eax 中。
如果要在invoke 伪指令的参数中用到一个局部变量的地址,该怎么办呢?参数中是不可能写入lea 指令的,用offset 又是不对的。MASM 对此有一个专用的伪操作符addr,其格式为:addr 局部变量名和全局变量名当addr 后跟全局变量名的时候,用法和offset 是相同的;当addr 后面跟局部变量名的时候,编译器会自动用lea 指令先把地址取到eax 中,然后用eax 来代替变量地址使用。注意addr 伪操作符只能在invoke 的参数中使用,不能用在类似于下列的场合:mov eax,addr 局部变量名 ;注意:错误用法
!假设在一个子程序中有如下invoke 指令:invoke Test,eax,addr szHello其中Test 是一个需要两个参数的子程序,szHello 是一个局部变量,会发生什么结果呢?编译器会把invoke 伪指令和addr 翻译成下面这个模样:lea eax,[ebp-4]push eax ;参数2:addr szHellopush eax ;参数1:eaxcall Test发现了什么?到push 第一个参数eax 之前,eax 的值已经被lea eax,[ebp-4]指令覆盖了!也就是说,要用到的eax 的值不再有效,所以,当在invoke 中使用addr 伪操作符时,注意在它的前面不能用eax,否则eax 的值会被覆盖掉,当然eax 在addr 的后面的参数中用是可以的。幸亏MASM 编译器对这种情况有如下错误提示:error A2133: register value overwritten by INVOKE否则,不知道又会引出多少莫名其妙的错误!
1、条件测试语句
&&、||、!等各种在C中存在的逻辑符号都可以使用。
除了这些和高级语言类似的条件测试伪操作,汇编语言还有特殊的要求,就是程序中常常要根据系统标志寄存器中的各种标志位来做条件跳转,这些在高级语言中是用不到的,所以又增加了以下一些标志位的状态指示,它们本身相当于一个表达式:CARRY? 表示Carry 位是否置位OVERFLOW? 表示Overflow 位是否置位PARITY? 表示Parity 位是否置位SIGN? 表示Sign 位是否置位ZERO? 表示Zero 位是否置位要测试eax 等于ebx 同时Zero 位置位,条件表达式可以写为:(eax==ebx) && ZERO?要测试eax 等于ebx 同时Zero 位清零,条件表达式可以写为:(eax==ebx) && ! ZERO?
.if 条件表达式1表达式1 为&真&时执行的指令[.elseif 条件表达式2]表达式2 为&真&时执行的指令[.elseif 条件表达式3]表达式3 为&真&时执行的指令&[.else]所有表达式为&否&时执行的指令.endif
注意:关键字if/elseif/else/endif 的前面有个小数点,如果不加小数点,就变成宏汇编中的条件汇编伪操作了,结果可是天差地别。
.while 条件测试表达式指令[.break [.if 退出条件]][.continue].endw或.repeat指令[.break [.if 退出条件]][.continue].until 条件测试表达式 (或.untilcxz [条件测试表达式])
&&&&&&&&.while/.endw 循环首先判断条件测试表达式,如果结果是&真&,则执行循环体内的指令,结束后再回到 .while 处判断表达式,如此往复,一直到表达式结果为&假&为止。.while/.endw指令有可能一遍也不会执行到循环体内的指令,因为如果第一次判断表达式时就遇到结果为&假&的情况,那么就直接退出循环。&&&&&&&&.repeat/.until 循环首先执行一遍循环体内的指令,然后再判断条件测试表达式,如果结果为&真&的话,就退出循环,如果为&假&,则返回 .repeat 处继续循环,可以看出,.repeat/.until不管表达式的值如何,至少会执行一遍循环体内的指令。&&&&&&& 也可以把条件表达式直接设置为固定值,这样就可以构建一个无限循环,对于.while/.end直接使用TRUE,对 .repeat/.until 直接使用FALSE 来当表达式就是如此,这种情况下,可以使用 .break 伪指令强制退出循环,如果 .break 伪指令后面跟一个 .if 测试伪指令的话,那么当退出条件为&真&时才执行 .break 伪指令。&&&&&&& 在循环体中也可以用 .continue 伪指令忽略以后的指令,遇到 .continue 伪指令时,不管下面还有没有其他循环体中的指令,都会直接回到循环头部开始执行。
— dugu @ 10:23 pm
windows日志的保护与伪造
原创:netone(cexo)
windows日志的保护与伪造日志对于系统安全的作用是显而易见的,无论是网络管理员还是黑客都非常重视日志,一个有经验的管理员往往能够迅速通过日志了解到系统的安全性能,而一个聪明的黑客往往会在入侵成功后迅速清除掉对自己不利的日志。下面我们就来讨论一下日志的安全和创建问题。一:概述:Windows2000的系统日志文件有应用程序日志,安全日志、系统日志、DNS服务器日志等等,应用程序日志、安全日志、系统日志、DNS日志默认位置:%systemroot%\system32\config,默认文件大小512KB。安全日志文件:%systemroot%\system32\config\SecEvent.EVT 系统日志文件:%systemroot%\system32\config\SysEvent.EVT 应用程序日志文件:%systemroot%\system32\config\AppEvent.EVT 这些LOG文件在注册表中的: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Eventlog 有的管理员很可能将这些日志重定位。其中EVENTLOG下面有很多的子表,里面可查到以上日志的定位目录。
二:作为网络管理员:1。日志的安全配置:默认的条件下,日志的大小为512KB大小,如果超出则会报错,并且不会再记录任何日志。所以首要任务是更改默认大小,具体方法:注册表中HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Eventlog对应的每个日志如系统,安全,应用程序等均有一个maxsize子键,修改即可。下面给出一个来自微软站点的一个脚本,利用VMI来设定日志最大25MB,并允许日志自行覆盖14天前的日志:该脚本利用的是WMI对象, WMI(Windows Management Instrumentation)技术是微软提供的Windows下的系统管理工具。通过该工具可以在本地或者管理客户端系统中几乎一切的信息。很多专业的网络管理工具都是基于WMI开发的。该工具在Win2000以及WinNT下是标准工具,在Win9X下是扩展安装选项。所以以下的代码在2000以上均可运行成功。
strComputer = &.&Set objWMIService = GetObject(&winmgmts:& _& &{impersonationLevel=impersonate,(Security)}!\\& & _strComputer & &\root\cimv2&) ‘获得VMI对象Set colLogFiles = objWMIService.ExecQuery _ (&Select * from Win32_NTEventLogFile&)For each objLogfile in colLogFilesstrLogFileName = objLogfile.NameSet wmiSWbemObject = GetObject _(&winmgmts:{impersonationLevel=Impersonate}!\\.\root\cimv2:& _& &Win32_NTEventlogFile.Name=’& & strLogFileName & &’&)wmiSWbemObject.MaxFileSize = wmiSWbemObject.OverwriteOutdated = 14wmiSWbemObject.Put_ Next将上述脚本用记事本存盘为vbs为后缀的即可使用。另外需要说明的是代码中的strComputer=&.&在windows脚本中的含义相当于localhost,如果要在远程主机上执行代码,只需要把&.&改动为主机名,当然首先得拥有对方主机的管理员权限并建立IPC连接.本文中的代码所出现的strComputer均可作如此改动.2。日志的查询与备份:一个优秀的管理员是应该养成备份日志的习惯,如果有条件的话还应该把日志转存到备份机器上或直接转储到打印机上,笔者还有一篇文章《利用脚本编程格式化输出系统日志》,详细的讲述了利用windows脚本把日志转储并输出成html页已便于查询,有兴趣的可以查看,在这里推荐微软的resourceKit工具箱中的dumpel.exe,他的常用方法:dumpel -f filename -s
-l log -f filename 输出日志的位置和文件名-s
输出远程计算机日志-l log log 可选的为system,security,application,可能还有别的如DNS等如要把目标服务器server上的系统日志转存为backupsystem.log可以用以下格式:dumpel
-l

我要回帖

更多关于 exe文件打不开 的文章

 

随机推荐