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

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

None.gif//Microsoft Visual C++ generated resource script.
None.gif//
None.gif#include "resource.h"
None.gif
None.gif#define IDR_MAINFRAME                    128
None.gif#define IDD_DEMO_DIALOG        102
None.gif#define IDD_ABOUTBOX                    103
None.gif#define IDS_APP_TITLE                    103
None.gif
None.gif#define IDM_ABOUT                        104
None.gif#define IDM_EXIT                        105
None.gif#define IDS_HELLO                        106
None.gif#define IDI_DEMO                107
None.gif#define IDI_SMALL                        108
None.gif#define IDC_DEMO                109
None.gif
None.gif#define IDC_MYICON                        2
None.gif#define IDC_STATIC                        -1
None.gif
None.gif/////////////////////////////////////////////////////////////////////////////
None.gif//
None.gif// Icon
None.gif//
None.gif// Icon with lowest ID value placed first to ensure application icon
None.gif// remains consistent on all systems.
None.gif
None.gifIDI_DEMO       ICON    DISCARDABLE     "demo.ICO"
None.gifIDI_SMALL               ICON    DISCARDABLE     "SMALL.ICO"
None.gif/////////////////////////////////////////////////////////////////////////////
None.gif//
None.gif// Menu
None.gif//
None.gifIDC_DEMO MENU DISCARDABLE
None.gifBEGIN
None.gif    POPUP "
&File"
None.gif    BEGIN
None.gif        MENUITEM "E
&xit",                IDM_EXIT
None.gif    END
None.gif    POPUP "
&Help"
None.gif    BEGIN
None.gif        MENUITEM "
&About dot.gif",           IDM_ABOUT
None.gif    END
None.gifEND
None.gif/////////////////////////////////////////////////////////////////////////////
None.gif//
None.gif// Accelerator
None.gif//
None.gifIDC_DEMO ACCELERATORS MOVEABLE PURE
None.gifBEGIN
None.gif    "?",            IDM_ABOUT,              ASCII,  ALT
None.gif    "/",            IDM_ABOUT,              ASCII,  ALT
None.gifEND
None.gif/////////////////////////////////////////////////////////////////////////////
None.gif//
None.gif// Dialog
None.gif//
None.gifIDD_ABOUTBOX DIALOG DISCARDABLE  22, 17, 230, 75
None.gifSTYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
None.gifCAPTION "About"
None.gifFONT 8, "System"
None.gifBEGIN
None.gif    ICON            IDI_DEMO,IDC_MYICON,14,9,16,16
None.gif    LTEXT           "HelloApp 1.0",IDC_STATIC,49,10,119,8,SS_NOPREFIX
None.gif    LTEXT           "Copyright (C) 2008",IDC_STATIC,49,20,119,8
None.gif    DEFPUSHBUTTON   "OK",IDOK,195,6,30,11,WS_GROUP
None.gifEND
None.gif
None.gif/////////////////////////////////////////////////////////////////////////////
None.gif//
None.gif// String Table
None.gif//
None.gif
None.gifSTRINGTABLE DISCARDABLE 
None.gifBEGIN
None.gif   IDC_DEMO   "DEMO"
None.gif   IDS_APP_TITLE       "demo"
None.gif   IDS_HELLO           "Hello World!"
None.gifEND
None.gif/////////////////////////////////////////////////////////////////////////////
None.gif

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

None.gifNAME = Hello
None.gifOBJS 
= $(NAME).obj
None.gifRES  
= $(NAME).res
None.gif
None.gif
$(NAME).exe: $(OBJS) $(RES)
None.gif    Link 
/SUBSYSTEM:WINDOWS $(OBJS) $(RES)
None.gif
$(RES)$(NAME).rc
None.gif    rc 
$(NAME).rc
None.gif
.asm.obj:
None.gif    ml 
//coff $(NAME).asm
None.gif

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

None.gif        .386
None.gif        .model flat,stdcall
None.gif        option 
casemap:none
None.gif
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
None.gif;
 Include 文件定义
None.gif;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> include        windows.inc
None.gif
include        gdi32.inc
None.gifincludelib    gdi32.lib
None.gifinclude        user32.
inc
None.gifincludelib    user32.lib
None.gifinclude        kernel32.
inc
None.gifincludelib    kernel32.lib
None.gif
None.gif
None.gifIDR_MAINFRAME            equ        
128
None.gifIDD_DEMO_DIALOG        equ 
102
None.gifIDD_ABOUTBOX            equ        
103
None.gifIDS_APP_TITLE            equ        
103
None.gifIDM_ABOUT                    equ    
104
None.gifIDM_EXIT                    equ    
105
None.gifIDS_HELLO                    equ    
106
None.gifIDI_DEMO            equ   
107
None.gifIDI_SMALL                    equ    
108
None.gifIDC_DEMO            equ    
109
None.gifIDC_MYICON                equ        
2
None.gifIDC_STATIC          equ    -
1
None.gif
None.gif
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
None.gif;
 数据段
None.gif;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
None.gif
        .data?
None.gifhInstance    dd        ?        
;应用程序句柄
None.gif
hWinMain    dd        ?        ;窗口句柄
None.gif
szCaptionMain        db  1024  dup (?)
None.gifszText          db  
1024  dup (?)
None.gif
None.gif        .const
None.gifszClassName    db    
'MyClass',0        ;窗口类名称
None.gif

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

None.gif_ProcWinMain    proc    uses ebx edi esi hWnd,uMsg,wParam,lParam            
;让汇编器保持子程序中使用到的寄存器的正确性 
None.gif
        local    @stPs:PAINTSTRUCT            
None.gif        local    
@stRect:RECT
None.gif        local    @hDc    
None.gif
None.gif        
mov    eax,uMsg
None.gif
;*************************************************************
None.gif
        .if eax ==    WM_PAINT
None.gif            invoke    BeginPaint,hWnd,addr @stPs
None.gif            
mov    @hDc,eax
None.gif
None.gif            invoke    GetClientRect,hWnd,addr @stRect
None.gif            invoke    DrawText,@hDc,addr szText,-
1,\     ;长度设置为-1,表示输出的字符串以'\0'结尾,且由函数自动计算出其长度
None.gif
                addr @stRect,\
None.gif                DT_SINGLELINE 
or DT_CENTER or DT_VCENTER
None.gif            invoke    EndPaint,hWnd,addr @stPs
None.gif
;*************************************************************
None.gif
        .elseif eax == WM_COMMAND
None.gif            
mov    eax,wParam
None.gif            
movzx    eax,ax
None.gif            .if eax == IDM_EXIT
None.gif                invoke    DestroyWindow,hWinMain
None.gif                invoke PostQuitMessage,NULL
None.gif            .elseif eax == IDM_ABOUT
None.gif                invoke DialogBoxParam,hInstance,IDD_ABOUTBOX,hWnd,_About,NULL
None.gif            .endif
None.gif            
None.gif
;*************************************************************
None.gif
        .elseif    eax ==    WM_CLOSE
None.gif            invoke    DestroyWindow,hWinMain
None.gif            invoke    PostQuitMessage,NULL
None.gif
;*************************************************************
None.gif
        .else
None.gif            invoke    DefWindowProc,hWnd,uMsg,wParam,lParam
None.gif            
ret
None.gif        .endif
None.gif
;*************************************************************
None.gif
        xor    eax,eax            ;eax寄存器清零
None.gif
        ret
None.gif
None.gif_ProcWinMain    endp
None.gif
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
None.gif;
WinMain函数
None.gif;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
None.gif

None.gif_WinMain    proc
None.gif        local    
@stWndClass:WNDCLASSEX
None.gif        local    
@stMsg:MSG
None.gif        
None.gif        invoke    GetModuleHandle,NULL   
;获取应用程序句柄,这在VC里是通过操作系统传递进来的,但是汇编中需要自己去获取
None.gif
        mov    hInstance,eax            ;获取到的应用程序句柄在eax中
None.gif
        invoke    RtlZeroMemory,addr @stWndClass,sizeof @stWndClass  ;清零
None.gif;
*************************************************************
None.gif;
 注册窗口类
None.gif;
*************************************************************
None.gif
        invoke    LoadCursor,0,IDC_ARROW    ;加载光标
None.gif
        mov    @stWndClass.hCursor,eax            
None.gif        invoke LoadIcon,hInstance,offset IDI_DEMO
None.gif        
mov @stWndClass.hIcon,eax
None.gif        invoke LoadString,hInstance,IDS_APP_TITLE,addr szCaptionMain,sizeof szCaptionMain
None.gif        invoke LoadString,hInstance,IDS_HELLO,addr szText,sizeof szText
None.gif        
push    hInstance
None.gif        
pop    @stWndClass.hInstance
None.gif        
mov    @stWndClass.cbSize,sizeof WNDCLASSEX
None.gif        
mov    @stWndClass.style,CS_HREDRAW or CS_VREDRAW
None.gif
None.gif        
mov    @stWndClass.lpfnWndProc,offset _ProcWinMain        ;设置窗口处理函数
None.gif
        ;invoke GetStockObject,WHITE_BRUSH
None.gif
        ;mov @stWndClass.hbrBackground,eax
None.gif
        mov    @stWndClass.hbrBackground,COLOR_WINDOW + 1
None.gif        
mov    @stWndClass.lpszClassName,offset szClassName
None.gif        
mov @stWndClass.lpszMenuName,offset IDC_DEMO
None.gif        invoke    RegisterClassEx,addr @stWndClass            
;注册窗口类
None.gif;
*************************************************************
None.gif;
 建立并显示窗口
None.gif;
*************************************************************
None.gif
        invoke    CreateWindowEx,WS_EX_CLIENTEDGE,offset szClassName,addr szCaptionMain,\
None.gif            WS_OVERLAPPEDWINDOW,\
None.gif            
100,100,600,400,\
None.gif            NULL,NULL,hInstance,NULL                    
;创建窗口,发出一个WM_CREATE消息
None.gif
        mov    hWinMain,eax                        ;保存窗口句柄
None.gif
        invoke    ShowWindow,hWinMain,SW_SHOWNORMAL                ;显示窗口
None.gif
        invoke    UpdateWindow,hWinMain                                        ;发出一个WM_PAINT消息
None.gif;
*************************************************************
None.gif;
 第一种消息循环,使用GetMessage,同步的
None.gif;
*************************************************************
None.gif
        ;.while    TRUE
None.gif
            ;invoke    GetMessage,addr @stMsg,NULL,0,0
None.gif
            ;.break    .if eax    == 0                    ;stMsg为0,即收到WM_QUIT消息时退出
None.gif
            ;invoke    TranslateMessage,addr @stMsg
None.gif
            ;invoke    DispatchMessage,addr @stMsg
None.gif
        ;.endw
None.gif;
*************************************************************
None.gif;
另一种消息循环,使用PeekMessage,异步的
None.gif;
*************************************************************
None.gif
        .while TRUE
None.gif            invoke PeekMessage,addr @stMsg,NULL,
0,0,PM_REMOVE
None.gif            .if eax != 
0
None.gif                    .break  .if @stMsg.message == WM_QUIT
None.gif                    invoke    TranslateMessage,addr @stMsg
None.gif                    invoke    DispatchMessage,addr @stMsg 
None.gif            .else
None.gif                    
;空闲时间,可以做其他处理工作
None.gif
            .endif
None.gif        .endw
None.gif        
ret
None.gif_WinMain endp
None.gif
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
None.gif;
程序入口点
None.gif;
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
None.gif
start:
None.gif        
call    _WinMain    
None.gif        invoke    ExitProcess,NULL
None.gif
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
None.gif
        end    start
None.gif

nmake编译后运行如下图:

2008030801.jpg