1 2;--- a simple 16-bit Windows "hello world". Public Domain. 3;--- assemble: JWasm Win16_1.asm 4;--- link: wlink format windows file Win16_1.obj op st=5120,heapsize=1024 5;--- 6;--- alternatively the MS OMF linker can be used as well: 7;--- link16 /A:16 Win16_1.obj,,,,Win16_1.def; 8;--- 9;--- libw.lib is the name of the import library for Win16 API calls. 10;--- if libw.lib isn't available, create one with Open Watcom WLIB: 11;--- wlib -ino -p=16 libw.lib + krnl386.exe + user.exe + gdi.exe 12;--- (files krnl386.exe, user.exe and gdi.exe can be found in the Windows 13;--- system directory). 14 15 .286 16 .model small 17 .386 18 option casemap:none 19 20 includelib <libw.lib> 21 22;--- menu commands 23IDM_EXIT EQU 100 24 25;--- Windows API definitions 26WINAPI equ <FAR PASCAL> 27 28UINT typedef WORD 29HINSTANCE typedef WORD 30HWND typedef WORD 31HMENU typedef WORD 32HDC typedef WORD 33WPARAM typedef WORD 34LPARAM typedef DWORD 35LPSTR typedef FAR PTR BYTE 36 37NULL EQU 0 38 39WS_OVERLAPPED EQU 000000000h 40WS_MAXIMIZEBOX EQU 000010000h 41WS_MINIMIZEBOX EQU 000020000h 42WS_THICKFRAME EQU 000040000h 43WS_SYSMENU EQU 000080000h 44WS_CAPTION EQU 000C00000h 45WS_OVERLAPPEDWINDOW EQU WS_OVERLAPPED + WS_CAPTION + WS_SYSMENU + WS_THICKFRAME + WS_MINIMIZEBOX + WS_MAXIMIZEBOX 46 47CS_VREDRAW EQU 0001h 48CS_HREDRAW EQU 0002h 49 50WM_DESTROY EQU 0002h 51WM_PAINT EQU 000Fh 52WM_COMMAND EQU 0111h 53 54CW_USEDEFAULT EQU 8000h 55SW_SHOWNORMAL EQU 1 56COLOR_WINDOW EQU 5 57IDC_ARROW EQU 32512 58 59DT_CENTER EQU 01h 60DT_VCENTER EQU 04h 61DT_SINGLELINE EQU 20h 62 63MF_ENABLED EQU 0 64MF_STRING EQU 0 65MF_POPUP EQU 10h 66 67MSG struct 68hwnd HWND ? 69message UINT ? 70wParam WPARAM ? 71lParam LPARAM ? 72time dd ? 73pt dd ? 74MSG ends 75 76WNDCLASS struct 77style dw ? 78lpfnWndProc dd ? 79cbClsExtra dw ? 80cbWndExtra dw ? 81hInstance HINSTANCE ? 82hIcon dw ? 83hCursor dw ? 84hbrBackground dw ? 85lpszMenuName LPSTR ? 86lpszClassName LPSTR ? 87WNDCLASS ends 88 89RECT struct 90left dw ? 91top dw ? 92right dw ? 93bottom dw ? 94RECT ends 95 96PAINTSTRUCT struct 97hdc HDC ? 98fErase dw ? 99rcPaint RECT <> 100fRestore dw ? 101fIncUpdate dw ? 102rgbReserved db 16 dup(?) 103PAINTSTRUCT ends 104 105AppendMenu proto WINAPI :HMENU, :WORD, :WORD, :LPSTR 106BeginPaint proto WINAPI :HWND, :far ptr PAINTSTRUCT 107CreateMenu proto WINAPI 108CreatePopupMenu proto WINAPI 109CreateWindow proto WINAPI lpszClass:LPSTR, lpszName:LPSTR, style:DWORD, 110 x:WORD, y:WORD, cx_:WORD, cy:WORD, 111 parent:HWND, menu:HMENU, hInst:HINSTANCE, lParam:LPARAM 112DefWindowProc proto WINAPI :HWND, msg:UINT, wParam:WPARAM, lParam:LPARAM 113DestroyMenu proto WINAPI :HMENU 114DestroyWindow proto WINAPI :HWND 115DispatchMessage proto WINAPI :far ptr MSG 116DrawText proto WINAPI :HDC, :LPSTR, :WORD, :far ptr RECT, :WORD 117EndPaint proto WINAPI :HWND, :far ptr PAINTSTRUCT 118GetClientRect proto WINAPI :HWND, :far ptr RECT 119GetMessage proto WINAPI :far ptr MSG, hWnd:HWND, msgfrom:WORD, msgto:WORD 120InitApp proto WINAPI :HINSTANCE 121InitTask proto WINAPI 122LoadCursor proto WINAPI :HINSTANCE, :LPSTR 123PostQuitMessage proto WINAPI :WORD 124RegisterClass proto WINAPI :far ptr WNDCLASS 125ShowWindow proto WINAPI :HWND, :WORD 126TranslateMessage proto WINAPI :far ptr MSG 127WaitEvent proto WINAPI :WORD 128 129 .data 130 131 dw 0,0,5,0,0,0,0,0 ;DGROUP first 16 bytes used by Windows 132 133 .const 134 135szClass db "WndClassName",0 136szWnd db "Windows 16-bit sample in ASM",0 137szHello db "Hello, world",0 138 139szMFile db "&File",0 140szMExit db "E&xit",0 141 142 .code 143 144;*** WM_COMMAND handler 145 146OnCommand proc stdcall hWnd:HWND,wParam:WPARAM,lParam:LPARAM 147 148 .if wParam == IDM_EXIT 149 invoke DestroyWindow, hWnd 150 .endif 151 xor ax, ax 152 cwd 153 ret 154OnCommand endp 155 156;*** window procedure - must be FAR PASCAL 157 158WndProc proc WINAPI <LOADDS> hWnd:HWND,message:UINT,wParam:WPARAM,lParam:LPARAM 159 160local ps:PAINTSTRUCT 161 162 mov ax,message 163 .if (ax == WM_COMMAND) 164 invoke OnCommand,hWnd,wParam,lParam 165 .elseif (ax == WM_PAINT) 166 invoke BeginPaint, hWnd, addr ps 167 invoke GetClientRect, hWnd, addr ps.rcPaint 168 invoke DrawText, ps.hdc, addr szHello, -1, addr ps.rcPaint, DT_CENTER or DT_VCENTER or DT_SINGLELINE 169 invoke EndPaint, hWnd, addr ps 170 xor ax, ax 171 cwd 172 .elseif (ax == WM_DESTROY) 173 invoke PostQuitMessage, 0 174 xor ax,ax 175 cwd 176 .else 177 invoke DefWindowProc, hWnd,message,wParam,lParam 178 .endif 179 ret 180WndProc endp 181 182;*** InitApplication: register window class 183 184InitApplication proc stdcall hInstance:HINSTANCE 185 186local wc:WNDCLASS 187 188 mov wc.style, CS_HREDRAW or CS_VREDRAW 189 190 mov word ptr wc.lpfnWndProc+0, offset WndProc 191 mov word ptr wc.lpfnWndProc+2, cs 192 193 xor ax,ax 194 mov wc.cbClsExtra,ax 195 mov wc.cbWndExtra,ax 196 197 mov ax,hInstance 198 mov wc.hInstance,ax 199 200 mov wc.hIcon, NULL 201 202 invoke LoadCursor, 0, IDC_ARROW 203 mov wc.hCursor,ax 204 205 mov ax,COLOR_WINDOW + 1 206 mov wc.hbrBackground,ax 207 208 xor eax,eax 209 mov wc.lpszMenuName,eax 210 211 mov word ptr wc.lpszClassName+0, offset szClass 212 mov word ptr wc.lpszClassName+2, ds 213 214 invoke RegisterClass, addr wc 215exit: 216 ret 217InitApplication endp 218 219;*** InitInstance: create application window and show it 220 221InitInstance proc stdcall hInstance:HINSTANCE 222 223local hMenu:HMENU 224 225;--- "usually" a menu is loaded as a resource via LoadMenu(). 226;--- here a menu is created on the fly. 227;--- it will be "destroyed" automatically when the window is "destroyed". 228 invoke CreateMenu 229 mov hMenu, ax 230 invoke CreatePopupMenu 231 push ax 232 invoke AppendMenu, ax, MF_ENABLED or MF_STRING, IDM_EXIT, addr szMExit 233 pop ax 234 invoke AppendMenu, hMenu, MF_ENABLED or MF_POPUP, ax, addr szMFile 235 236;--- create the main window 237 invoke CreateWindow, addr szClass, addr szWnd, 238 WS_OVERLAPPEDWINDOW, 239 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 240 NULL, hMenu, hInstance, 0 241 .if (ax) 242 push ax 243 invoke ShowWindow, ax, SW_SHOWNORMAL 244 pop ax 245 .endif 246 ret 247 248InitInstance endp 249 250;--- WinMain: create application window, enter message loop 251 252WinMain proc pascal hInstance:HINSTANCE,hPrevInstance:HINSTANCE,lpszCmdline:LPSTR,cmdshow:UINT 253 254local msg:MSG 255 256 .if hPrevInstance == 0 ;1. Instance? 257 invoke InitApplication, hInstance 258 and ax,ax 259 jz exit 260 .endif 261 262 invoke InitInstance, hInstance 263 and ax,ax 264 jz exit 265 .while 1 266 invoke GetMessage, addr msg, 0, 0, 0 267 .break .if (ax == 0) 268 invoke TranslateMessage, addr msg 269 invoke DispatchMessage, addr msg 270 .endw 271exit: 272 ret 273 274WinMain endp 275 276;--- program entry: SS=DS=DGROUP 277 278start: 279 invoke InitTask 280 and ax,ax 281 jz error 282 push es ;es:bx -> cmdline 283 pusha 284 invoke WaitEvent, 0 285 invoke InitApp, di 286 popa 287 pop es 288 invoke WinMain, di, si, es::bx, dx 289 mov ah,4ch 290 int 21h 291error: 292 mov ax,4c01h 293 int 21h 294 295 end start 296