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