模仿win32的Hello,World程序:
.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 Window !',0 ;窗口标题
szText db ' Hello,Win32 Assembly!!',0 ;要显示的信息
szButton db 'button',0
szButtonText db '点我吧!!',0
szMsgTitle db '信息',0
szErrorMsg db '出错啦!!',0

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 出错处理过程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ErrorProc proc
invoke MessageBox,NULL,offset szErrorMsg,offset szMsgTitle,MB_OK
ret
_ErrorProc 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_CREATE
invoke CreateWindowEx,NULL,offset szButton,offset szButtonText,\
WS_CHILD or WS_VISIBLE,100,100,65,50,hWnd,1,hInstance,NULL
;********************************************************************
.elseif 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
invoke MessageBox,NULL,offset szText,offset szMsgTitle,MB_OK
;********************************************************************
.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
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
invoke RegisterClassEx,addr @stWndClass ;注册窗口类
;********************************************************************
; 建立并显示窗口
;********************************************************************
invoke CreateWindowEx,WS_EX_CLIENTEDGE,offset szClassName,offset 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



运行结果:

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述