一个完整win32汇编窗口程序的分析

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

 

;该部分指出了该汇编程序所用的指令集为386,类似的还有486,586等

;内存模式为平坦型,也就是内存范围为4GB空间,不会担心在使用内存时有任何限制,同时指出了

;函数调用的约定stdcall表示函数参数从右向左压入堆栈

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

.386

.model    flat,   stdcall

.option    casemap:none

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

;include  文件定义,表示该程序运行时包含的头文件

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

include                    windows.inc

include                    user32.inc

include lib               user32.lib

include                    kernel32.inc

includelib                kernel32.lib

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

;Equ等值定义

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

ICO_MAIN                               equ                            1000h ;图标
IDM_MAIN                              equ                           2000h ;菜单
IDA_MAIN                               equ                           2000h ;加速键
IDM_OPEN                             equ                          4101h
IDM_OPTION                          equ                            4102h
IDM_EXIT                                equ                         4103h
IDM_SETFONT                      equ                          4201h
IDM_SETCOLOR                    equ                         4202h
IDM_INACT                              equ                          4203h
IDM_GRAY                               equ                          4204h
IDM_BIG                                    equ                        4205h
IDM_SMALL                             equ                          4206h
IDM_LIST                                  equ                          4207h
IDM_DETAIL                            equ                        4208h
IDM_TOOLBAR                       equ                        4209h
IDM_TOOLBARTEXT             equ                        4210h
IDM_INPUTBAR                       equ                       4211h
IDM_STATUSBAR                   equ                       4212h
IDM_HELP                                equ                       4301h
IDM_ABOUT                             equ                       4302h
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  .data?                         ;表示定义的变量为未初始化的变量
hInstance                    dd                ?              ;定义32位(4字节)实例化句柄,一般数据对象
hWinMain                   dd                ?              ;定义32位(4字节)主窗口句柄,主对象
hMenu                         dd                ?              ;定义32位(4字节)菜单句柄,菜单对象
hSubMenu                  dd                ?              ;定义32位(4字节)子菜单句柄,子菜单对象

;所谓句柄就是指向指针的指针,指针指向内存单元的地址,而指针的指针指的是指向地址的地址,

;这个类似于目录章节编号和与此对应的页码编号一样,在windows系统中专门在内存区域中

;开辟了一段区域用于储存"章节编号"的地址.句柄的设计是windows系统内存管理的结果,句柄和

;相应数据对象一一对应。

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  .const                          ;定义常量
szClassName                  db 'Menu Example',0                 ;定义以0结尾的字符串
szCaptionMain                db 'Menu',0
szMenuHelp                     db '帮助主题(&H)',0
szMenuAbout                   db '关于本程序(&A)...',0
szCaption                         db '菜单选择',0
szFormat                          db '您选择了菜单命令:%08x',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  .code

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

;定义子程序(函数)以下划线开始,伪指令proc代表对该程序(函数)的声明,

;之后参数为该函数所需的参数,类似于C语言中的add(int x,int y)

;addr可以处理局部变量而   offset   则不能。局部变量只是在运行时在堆栈中分配内存空间。而   offset   则是在编译时由编译器解释,这显然不能用offset   在运行时来分配内存空间。编译器对   addr   的处理是先检查处理的是全局还是局部变量,若是全局变量则把其地址放到目标文件中,这一点和   offset   相同,若是局部变量,就在执行   invoke   语句前产生如下指令序列:    
  lea   eax,   LocalVar  
  push   eax  
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_DisplayMenuItem proc _dwCommandID                       //显示菜单项目的函数
   local @szBuffer[256]:byte                     ;定义常量,以@开头,定义256字节缓冲区

  pushad                                                     ;pushad      按照EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX的顺序将寄存器压入堆栈

                                                                                         用于临时保存寄存器中的值,保护现场

  invoke wsprintf,addr @szBuffer,addr szFormat,_dwCommandID                 ;函数作用:
                                                                                                                    函数wsprintf()将一系列的字符和数值输入到缓冲区
                                                                                                                    输出缓冲区里的的值取决于格式说明符(即"%")。
                                                                                                                    如果写入的是文字,此函数给写入的文字的末尾追加一个'\0'。
                                                                                                                    函数的返回值是写入的长度,但不包括最后的'\0'

 invoke MessageBox,hWinMain,addr @szBuffer,offset szCaption,MB_OK      ;

                                                                                                   调用子窗口消息函数,建立窗口,hWinMain(父类句柄,主窗口句 柄),

                                                                                                                         该参数表明该窗口消息实现的窗口所从属的父类对象

                                                                                                                           
  popad                                          ;与popad对应,主要用于恢复现场
  ret                                           ;返回子程序

_DisplayMenuItem endp                                                 //子程序结束
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;退出窗口函数,

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

_Quit  proc

  invoke DestroyWindow,hWinMain             //销毁窗口函数,参数hWinMain指代该函数对象(主窗口句柄)

  invoke PostQuitMessage,NULL                //函数功能:该函数向系统表明有个线程有终止请求。通常用来响应WM_DESTROY消息
  ret

_Quit  endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

;定义子程序,uses的使用相当于在该程序的开始和结尾处自动加上pushad和popad

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_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 AppendMenu,@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                            //movzx主要用于实现16位向32位数据的转换
   .if eax == IDM_EXIT
    call _Quit
   .elseif eax >= IDM_TOOLBAR && eax <= IDM_STATUSBAR
    mov ebx,eax
    invoke GetMenuState,hMenu,ebx,MF_BYCOMMAND
    .if eax == MF_CHECKED
     mov eax,MF_UNCHECKED
    .else
     mov eax,MF_CHECKED
    .endif
    invoke CheckMenuItem,hMenu,ebx,eax
   .elseif eax >= IDM_BIG && eax <= IDM_DETAIL
    invoke CheckMenuRadioItem,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 GetCursorPos,addr @stPos
   invoke TrackPopupMenu,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              //

                                                                                          GetModuleHandle,lpModuleName
                                                                                          函数的作用是返回指定模块名的句柄,如果为NULL,则返回本模块的句柄。
                                                                                          返回的句柄值存放在寄存器eax中。
                                                                                          lpModuleName参数是一个指向含有模块名称字符串的 指针


  mov hInstance,eax                                            //hInstance通用句柄,主要作为存放一般数据对象
  invoke LoadMenu,hInstance,IDM_MAIN                   //loadmenu

                                                                  函数功能:该函数从与应用程序实例相联系的 可执行文件(.EXE)中加载指定的菜单资源。


  mov hMenu,eax
  invoke LoadAccelerators,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         //调用退出程序函数ExitProcess,NULL参数默认指退出的为本窗口
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  end start

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值