Assembly

在 Win10 下如何用 VS2019 编译汇编及 win32 汇编程序

zeronohacker · 2月22日 · 2021年 · · 120次已读

1 环境

操作系统:windows 10 2004

工具:VS2019、MASM32

2 如何编译汇编程序

启动 VS2019,点击创建新项目,再点击创建空项目,如下所示:

创建好了之后,先不要急着创建新文件,这时需要先做一个操作,右键项目,在生成依赖中点击生成自定义,如下所示:

在弹出的生成自定义选项中在 masm 前面打上勾,因为后面我们创建的 asm 文件需要 masm 编译器,如下所示:

下面我们就可以创建 asm 文件写汇编代码了,如下所示:

为了更好的阅读我们写的汇编代码,需要安装一个汇编语言的语法高亮插件,点击扩展菜单栏中管理扩展选项,在插件市场中下载,插件名为 AsmDude,如下所示:

安装会要求重启 VS2019,重启后便可以开始愉快编写汇编代码了,最终尝试编译链接,如下所示:

示例代码:

.386

.model flat,stdcall
.stack 4096
ExitProcess PROTO, dwExitCode:DWORD


.code
main PROC
    
    mov eax, 5
    add eax, 6

    invoke ExitProcess, 0
main ENDP
END main

如何调试

在需要调试的地方打上断点,按 F5 启动调试,如下所示:

下面来说下 win32 汇编程序。

3 如何编译 win32 汇编程序

win32 汇编程序比上面简单的汇编程序有所不同,因为此类程序必须涉及到 win32 API,所以在编写这类程序时需要用到 MASM32 SDK 工具包,此工具包下载地址:http://www.masm32.com/download.htm,工具包安装也很简单,一路同意 next 即可,安装好目录如下所示:

其中 include 和 lib 这两个文件夹里的文件待会就会用到。include 文件夹里包含了各种 inc 文件,而 inc 文件里包含了 API 函数的声明;lib 文件夹则包含了许多 lib 文件,这此 lib 文件是存放着 API 函数的信息,在链接时需要用到。在 VS2019 中新建一个空项目,生成自定义项中勾上 masm,再新建一个 asm 文件,在文件中输入以下示例代码:

.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

; 数据段
.data?
hInstance dd ?
hWinMain dd ?

; 常量
.const
szClassName db 'MyClass',0
szCaptionMain db 'My first Windows !',0
szText 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

在编译链接前需要做几个设置,首先在项目属性上,在 Microsoft Macro Assembler 中的 Include Paths 选项中,将 MASM32 SDK 安装目录下的 include 路径填在该处,如下所示:

同时将 lib 所在的目录填写在链接器中的附加库目录中,如下所示:

上述一切准备就绪,编译链接,一定会失败,为什么,我们来看下出错提示:

其实这个问题当时也困扰了我好久,在这里我来说明下原因,问题出在 MSVC 的版本,过高的 MSVC,masm 不支持,所以只需把 MSVC 降版本号就可以了,如何降,在项目属性页中高级,MSVC 工具集版本,选择低于 14.26 以下即可,如下所示:

如果看不到这些下拉选项,说明你没安装,这时你需要退出 vs2019,打开 vs installer,在单个组件里选择相应 MSVC 版本然后进行修改即可,除了此问题外,还有一个小问题,是语法高亮插件,此插件会提示你找不到相应的 inc 文件,这种你只要把它忽略就可以,因为这是插件的 BUG,目前已有人在插件的 Github 上提了 issue,待作者改善修复。编译链接后如下所示:

运行如下所示:

Release 版的仅为 4KB 大。

(本文完)

1 条回应

必须 注册 为本站用户, 登录 后才可以发表评论!

  1. wiser广东·深圳2021-3-25 · 14:38

    学习了