用Visual Studio 2015 编写 MASM 汇编程序(二)从头开发一个Win32汇编程序

时间:2023-02-02 01:19:12

一,建立一个VC的控制台类型的空工程:

1,从VS菜单中选择“文件”->“新建”->“项目”。

用Visual Studio 2015 编写 MASM 汇编程序(二)从头开发一个Win32汇编程序

2,在新建项目中选择:“Visual c++”->"Win32"->"Win32控制台应用程序",随后输入工程名称,随后点击“确定”按钮。

用Visual Studio 2015 编写 MASM 汇编程序(二)从头开发一个Win32汇编程序

3,随后点击“下一步”按钮。

用Visual Studio 2015 编写 MASM 汇编程序(二)从头开发一个Win32汇编程序

4,随后选择“控制台应用程序”->"空项目",随后点击“完成”按钮。

用Visual Studio 2015 编写 MASM 汇编程序(二)从头开发一个Win32汇编程序

到这里,我们就创建了一个VC的控制台类型的空项目。

二,编写第一个MASM的Win32汇编窗口程序。

1,在工程名称上面鼠标右键,随后在右键菜单上点击“添加”->“新建项”。

用Visual Studio 2015 编写 MASM 汇编程序(二)从头开发一个Win32汇编程序

2,在“添加新项”对话框中选择“C++文件(.cpp)”,随后在下面的文件名称中输入你想要的文件名,注意文件的扩展名一定是“asm”,我使用的文件名称是“FirstWindow.asm”,随后点击“添加”按钮。

用Visual Studio 2015 编写 MASM 汇编程序(二)从头开发一个Win32汇编程序

3,这是创建了我要创建的汇编程序的截图,已经创建了一个空白的汇编程序,需要在这里加入汇编程序代码。

用Visual Studio 2015 编写 MASM 汇编程序(二)从头开发一个Win32汇编程序

 三,对Win32汇编工程设置,编写汇编程序,编译这个汇编程序。

 1,设置工程的依赖性。

A,鼠标右键工程名称,在右键菜单中选择“生成依赖项”->“生成自定义”。

用Visual Studio 2015 编写 MASM 汇编程序(二)从头开发一个Win32汇编程序

B,随后选中“masm”,随后点击“确定”按钮。

用Visual Studio 2015 编写 MASM 汇编程序(二)从头开发一个Win32汇编程序

 2,添加汇编程序文件,编写汇编程序。

A,工程名称上面鼠标右键,在右键菜单中点击“添加”->"新建项"。

用Visual Studio 2015 编写 MASM 汇编程序(二)从头开发一个Win32汇编程序

B,选择“C++文件(.cpp)”,随后在下面的名称中输入我们要使用的程序文件名称,注意这个文件扩展名必须是“asm”,我使用的文件名是"FirstWindow.asm",随后点击“添加”按钮。

用Visual Studio 2015 编写 MASM 汇编程序(二)从头开发一个Win32汇编程序

C,编写汇编代码。

用Visual Studio 2015 编写 MASM 汇编程序(二)从头开发一个Win32汇编程序

全部汇编源码:

.386
.model flat,stdcall
option casemap:none
;---------------------------------------------------------------------------------
; Include 文件定义

comment * 多行注释
include     \masm32\include\windows.inc
include    \masm32\include\gdi32.inc
includelib  \masm32\includelib\gdi32.lib
include     \masm32\include\user32.inc
includelib  \masm32\includelib\user32.lib
include    \masm32\include\kernel32.inc
includelib  \masm32\includelib\kernel32.lib
*

;当前正在引入的inc和lib
include     windows.inc
include     gdi32.inc
includelib  gdi32.lib
include     user32.inc
includelib  user32.lib
include    kernel32.inc
includelib  kernel32.lib



;---------------------------------------------------------------------------------
; 数据段(未初始化的变量) 
.data?
hInstance dd ?
hWinMain dd ?

bResult dd ? ;运行结果

.const
   szClassName db  'MyClass',0
   szCaptionMain  db  'My first Window !',0
   szText db  'Win32 Assembly, Simple and powerful !',0

   szRegisterSuccess db '注册窗口成功!',0 ;操作成功的提示信息

   szAppName db 'FirstMASM',0

;---------------------------------------------------------------------------------
; 代码段
.code

;---------------------------------------------------------------------------------
;windows窗口程序的入口函数
WinMainProc 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  ;从eax中取出光标句柄,并设置到窗口类中
        push    hInstance
        pop @stWndClass.hInstance
        mov @stWndClass.cbSize,sizeof WNDCLASSEX
        mov @stWndClass.style,CS_HREDRAW or CS_VREDRAW
        mov @stWndClass.lpfnWndProc,offset DoMessageProc
        mov @stWndClass.hbrBackground,COLOR_WINDOW + 1
        mov @stWndClass.lpszClassName,offset szClassName

        invoke  RegisterClassEx,addr @stWndClass ;注册窗口类

        mov bResult,eax ;得到注册窗口结果

        ;对注册窗口类结果判断
        .if bResult==0
           invoke ExitProcess,NULL ;注册窗口类失败,直接退出当前程序
        .else
           invoke  MessageBox,NULL,offset szRegisterSuccess,offset szAppName,MB_OK
        .endif

;---------------------------------------------------------------------------------
; 建立并显示窗口
        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

            .if eax == 0
              .break
            .endif

            invoke  TranslateMessage,addr @stMsg
            invoke  DispatchMessage,addr @stMsg
        .endw
        ret

WinMainProc endp

;---------------------------------------------------------------------------------
; 处理windows消息的过程,Windows的回调函数
DoMessageProc    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

DoMessageProc endp

;---------------------------------------------------------------------------------
;程序入口点,启动WinMainProc函数
start:
    call WinMainProc
    invoke ExitProcess,NULL
end start

到这里,建立一个汇编工程,并且编写了汇编程序代码,但是还是不能编译,需要进一步对工程设置。

 3,对"Microsoft Macro Assembler"的设置。