Win32汇编学习笔记(四)

前面几篇文章中都没有使用到菜单,对话框等资源,这次就演练如何在应用程序中加入这些资源。我们就以将VC6.0默认生成的Win32程序移植为32位汇编为例。

首先用VC6.0生成一个默认Win32版的Hello,World程序,将Hello.rcdemo.ico,small.ico都拷贝到项目目录下,去掉VC6.0相关的部分,最后Hello.rc修改如下:

//Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define IDR_MAINFRAME                    128
#define IDD_DEMO_DIALOG        102
#define IDD_ABOUTBOX                    103
#define IDS_APP_TITLE                    103

#define IDM_ABOUT                        104
#define IDM_EXIT                        105
#define IDS_HELLO                        106
#define IDI_DEMO                107
#define IDI_SMALL                        108
#define IDC_DEMO                109

#define IDC_MYICON                        2
#define IDC_STATIC                        -1

/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.

IDI_DEMO       ICON    DISCARDABLE     "demo.ICO"
IDI_SMALL               ICON    DISCARDABLE     "SMALL.ICO"
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDC_DEMO MENU DISCARDABLE
BEGIN
    POPUP "
&File "
    BEGIN
        MENUITEM "E
&xit ",                IDM_EXIT
    END
    POPUP "
&Help "
    BEGIN
        MENUITEM "
&About  ",           IDM_ABOUT
    END
END
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
IDC_DEMO ACCELERATORS MOVEABLE PURE
BEGIN
    "?",            IDM_ABOUT,              ASCII,  ALT
    "/",            IDM_ABOUT,              ASCII,  ALT
END
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_ABOUTBOX DIALOG DISCARDABLE  22, 17, 230, 75
STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION "About"
FONT 8, "System"
BEGIN
    ICON            IDI_DEMO,IDC_MYICON,14,9,16,16
    LTEXT           "HelloApp 1.0",IDC_STATIC,49,10,119,8,SS_NOPREFIX
    LTEXT           "Copyright (C) 2008",IDC_STATIC,49,20,119,8
    DEFPUSHBUTTON   "OK",IDOK,195,6,30,11,WS_GROUP
END

/////////////////////////////////////////////////////////////////////////////
//
// String Table
//

STRINGTABLE DISCARDABLE 
BEGIN
   IDC_DEMO   "DEMO"
   IDS_APP_TITLE       "demo"
   IDS_HELLO           "Hello World!"
END
/////////////////////////////////////////////////////////////////////////////

然后创建一个MakFile文件,内容如下:

NAME  =  Hello
OBJS 
=   $( NAME ). obj
RES  
=   $( NAME ). res

$( NAME ). exe:  $( OBJS )   $( RES )
    Link 
/ SUBSYSTEM :WINDOWS   $( OBJS )   $( RES )
$( RES ) $( NAME ). rc
    rc 
$( NAME ). rc
. asm . obj:
    ml 
/ / coff  $( NAME ). asm

最后仿照VC++代码编写汇编代码如下:

        . 386
        .model flat,stdcall
        option 
casemap: none
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;
 Include 文件定义
;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> include        windows.inc
include        gdi32. inc
includelib    gdi32.lib
include        user32.
inc
includelib    user32.lib
include        kernel32.
inc
includelib    kernel32.lib


IDR_MAINFRAME            equ        
128
IDD_DEMO_DIALOG        equ 
102
IDD_ABOUTBOX            equ        
103
IDS_APP_TITLE            equ        
103
IDM_ABOUT                    equ    
104
IDM_EXIT                    equ    
105
IDS_HELLO                    equ    
106
IDI_DEMO            equ   
107
IDI_SMALL                    equ    
108
IDC_DEMO            equ    
109
IDC_MYICON                equ        
2
IDC_STATIC          equ    -
1

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;
 数据段
;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        .data?
hInstance    dd        ?        
; 应用程序句柄
hWinMain    dd        ?         ; 窗口句柄
szCaptionMain        db   1024   dup (?)
szText          db  
1024   dup (?)

        .const
szClassName    db    
' MyClass ' , 0          ; 窗口类名称

; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;
 代码段
;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        .code
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;
About对话框处理函数
;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_About proc uses ebx edi esi,hDlg,uMsg,wParam,lParam
        
mov  eax,uMsg
        .if eax == WM_COMMAND
            
mov  eax,wParam
            
movzx  eax,ax
            .if eax == IDOK
                invoke EndDialog,hDlg,eax
                
; invoke MessageBox,NULL,addr szText,addr szCaptionMain,MB_OK
            .endif
        .elseif eax == WM_INITDIALOG
                
mov  eax, 1
                
ret
        .endif
        
xor  eax,eax   ; 这句非常重要,清零eax,相当于返回false
         ret
_About endp
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;
 窗口过程
;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

_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 ,\      ; 长度设置为-1,表示输出的字符串以'\0'结尾,且由函数自动计算出其长度
                addr @stRect,\
                DT_SINGLELINE 
or  DT_CENTER  or  DT_VCENTER
            invoke    EndPaint,hWnd,addr @stPs
; *************************************************************
        .elseif eax == WM_COMMAND
            
mov     eax,wParam
            
movzx     eax,ax
            .if eax == IDM_EXIT
                invoke    DestroyWindow,hWinMain
                invoke PostQuitMessage,NULL
            .elseif eax == IDM_ABOUT
                invoke DialogBoxParam,hInstance,IDD_ABOUTBOX,hWnd,_About,NULL
            .endif
            
; *************************************************************
        .elseif    eax ==    WM_CLOSE
            invoke    DestroyWindow,hWinMain
            invoke    PostQuitMessage,NULL
; *************************************************************
        .else
            invoke    DefWindowProc,hWnd,uMsg,wParam,lParam
            
ret
        .endif
; *************************************************************
         xor     eax,eax             ; eax寄存器清零
         ret

_ProcWinMain    endp
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;
WinMain函数
;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

_WinMain    proc
        local    
@stWndClass: WNDCLASSEX
        local    
@stMsg: MSG
        
        invoke    GetModuleHandle,NULL   
; 获取应用程序句柄,这在VC里是通过操作系统传递进来的,但是汇编中需要自己去获取
         mov     hInstance,eax             ; 获取到的应用程序句柄在eax中
        invoke    RtlZeroMemory,addr @stWndClass,sizeof @stWndClass   ; 清零
;
*************************************************************
;
 注册窗口类
;
*************************************************************
        invoke    LoadCursor, 0 ,IDC_ARROW     ; 加载光标
         mov     @stWndClass.hCursor,eax            
        invoke LoadIcon,hInstance,offset IDI_DEMO
        
mov  @stWndClass.hIcon,eax
        invoke LoadString,hInstance,IDS_APP_TITLE,addr szCaptionMain,sizeof szCaptionMain
        invoke LoadString,hInstance,IDS_HELLO,addr szText,sizeof szText
        
push     hInstance
        
pop     @stWndClass.hInstance
        
mov     @stWndClass.cbSize,sizeof WNDCLASSEX
        
mov     @stWndClass.style,CS_HREDRAW  or  CS_VREDRAW

        
mov     @stWndClass.lpfnWndProc,offset _ProcWinMain         ; 设置窗口处理函数
         ; invoke GetStockObject,WHITE_BRUSH
         ; mov @stWndClass.hbrBackground,eax
         mov     @stWndClass.hbrBackground,COLOR_WINDOW +  1
        
mov     @stWndClass.lpszClassName,offset szClassName
        
mov  @stWndClass.lpszMenuName,offset IDC_DEMO
        invoke    RegisterClassEx,addr @stWndClass            
; 注册窗口类
;
*************************************************************
;
 建立并显示窗口
;
*************************************************************
        invoke    CreateWindowEx,WS_EX_CLIENTEDGE,offset szClassName,addr szCaptionMain,\
            WS_OVERLAPPEDWINDOW,\
            
100 , 100 , 600 , 400 ,\
            NULL,NULL,hInstance,NULL                    
; 创建窗口,发出一个WM_CREATE消息
         mov     hWinMain,eax                         ; 保存窗口句柄
        invoke    ShowWindow,hWinMain,SW_SHOWNORMAL                 ; 显示窗口
        invoke    UpdateWindow,hWinMain                                         ; 发出一个WM_PAINT消息
;
*************************************************************
;
 第一种消息循环,使用GetMessage,同步的
;
*************************************************************
         ; .while    TRUE
             ; invoke    GetMessage,addr @stMsg,NULL,0,0
             ; .break    .if eax    == 0                    ;stMsg为0,即收到WM_QUIT消息时退出
             ; invoke    TranslateMessage,addr @stMsg
             ; invoke    DispatchMessage,addr @stMsg
         ; .endw
;
*************************************************************
;
另一种消息循环,使用PeekMessage,异步的
;
*************************************************************
        .while TRUE
            invoke PeekMessage,addr @stMsg,NULL,
0 , 0 ,PM_REMOVE
            .if eax != 
0
                    .break  .if @stMsg.message == WM_QUIT
                    invoke    TranslateMessage,addr @stMsg
                    invoke    DispatchMessage,addr @stMsg 
            .else
                    
; 空闲时间,可以做其他处理工作
            .endif
        .endw
        
ret
_WinMain endp
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;
程序入口点
;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
        
call     _WinMain    
        invoke    ExitProcess,NULL
; >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        end    start

nmake编译后运行如下图:

2008030801.jpg

你可能感兴趣的:(Win32)