1
+ ; Basic Window, 64 bit. V1.02
2
+ COLOR_WINDOW EQU 5 ; Constants
3
+ CS_BYTEALIGNWINDOW EQU 2000h
4
+ CS_HREDRAW EQU 2
5
+ CS_VREDRAW EQU 1
6
+ CW_USEDEFAULT EQU 80000000h
7
+ IDC_ARROW EQU 7F00h
8
+ IDI_APPLICATION EQU 7F00h
9
+ IMAGE_CURSOR EQU 2
10
+ IMAGE_ICON EQU 1
11
+ LR_SHARED EQU 8000h
12
+ NULL EQU 0
13
+ SW_SHOWNORMAL EQU 1
14
+ WM_DESTROY EQU 2
15
+ WS_EX_COMPOSITED EQU 2000000h
16
+ WS_OVERLAPPEDWINDOW EQU 0CF0000h
17
+
18
+ WindowWidth EQU 640
19
+ WindowHeight EQU 480
20
+
21
+ extern CreateWindowExA ; Import external symbols
22
+ extern DefWindowProcA ; Windows API functions, not decorated
23
+ extern DispatchMessageA
24
+ extern ExitProcess
25
+ extern GetMessageA
26
+ extern GetModuleHandleA
27
+ extern IsDialogMessageA
28
+ extern LoadImageA
29
+ extern PostQuitMessage
30
+ extern RegisterClassExA
31
+ extern ShowWindow
32
+ extern TranslateMessage
33
+ extern UpdateWindow
34
+
35
+ global Start ; Export symbols. The entry point
36
+
37
+ section .data ; Initialized data segment
38
+ WindowName db "Basic Window 64" , 0
39
+ ClassName db "Window" , 0
40
+
41
+ section .bss ; Uninitialized data segment
42
+ alignb 8
43
+ hInstance resq 1
44
+
45
+ section .text ; Code segment
46
+ Start:
47
+ sub RSP , 8 ; Align stack pointer to 16 bytes
48
+
49
+ sub RSP , 32 ; 32 bytes of shadow space
50
+ xor ECX , ECX
51
+ call GetModuleHandleA
52
+ mov qword [ REL hInstance ], RAX
53
+ add RSP , 32 ; Remove the 32 bytes
54
+
55
+ call WinMain
56
+
57
+ .Exit:
58
+ xor ECX , ECX
59
+ call ExitProcess
60
+
61
+ WinMain:
62
+ push RBP ; Set up a stack frame
63
+ mov RBP , RSP
64
+ sub RSP , 136 + 8 ; 136 bytes for local variables. 136 is not
65
+ ; a multiple of 16 (for Windows API functions),
66
+ ; the + 8 takes care of this.
67
+
68
+ %define wc RBP - 136 ; WNDCLASSEX structure, 80 bytes
69
+ %define wc.cbSize RBP - 136 ; 4 bytes. Start on an 8 byte boundary
70
+ %define wc.style RBP - 132 ; 4 bytes
71
+ %define wc.lpfnWndProc RBP - 128 ; 8 bytes
72
+ %define wc.cbClsExtra RBP - 120 ; 4 bytes
73
+ %define wc.cbWndExtra RBP - 116 ; 4 bytes
74
+ %define wc.hInstance RBP - 112 ; 8 bytes
75
+ %define wc.hIcon RBP - 104 ; 8 bytes
76
+ %define wc.hCursor RBP - 96 ; 8 bytes
77
+ %define wc.hbrBackground RBP - 88 ; 8 bytes
78
+ %define wc.lpszMenuName RBP - 80 ; 8 bytes
79
+ %define wc.lpszClassName RBP - 72 ; 8 bytes
80
+ %define wc.hIconSm RBP - 64 ; 8 bytes. End on an 8 byte boundary
81
+
82
+ %define msg RBP - 56 ; MSG structure, 48 bytes
83
+ %define msg.hwnd RBP - 56 ; 8 bytes. Start on an 8 byte boundary
84
+ %define msg.message RBP - 48 ; 4 bytes
85
+ %define msg.Padding1 RBP - 44 ; 4 bytes. Natural alignment padding
86
+ %define msg.wParam RBP - 40 ; 8 bytes
87
+ %define msg.lParam RBP - 32 ; 8 bytes
88
+ %define msg.time RBP - 24 ; 4 bytes
89
+ %define msg.py.x RBP - 20 ; 4 bytes
90
+ %define msg.pt.y RBP - 16 ; 4 bytes
91
+ %define msg.Padding2 RBP - 12 ; 4 bytes. Structure length padding
92
+
93
+ %define hWnd RBP - 8 ; 8 bytes
94
+
95
+ mov dword [ wc.cbSize ], 80 ; [RBP - 136]
96
+ mov dword [ wc.style ], CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNWINDOW ; [RBP - 132]
97
+ lea RAX , [ REL WndProc ]
98
+ mov qword [ wc.lpfnWndProc ], RAX ; [RBP - 128]
99
+ mov dword [ wc.cbClsExtra ], NULL ; [RBP - 120]
100
+ mov dword [ wc.cbWndExtra ], NULL ; [RBP - 116]
101
+ mov RAX , qword [ REL hInstance ] ; Global
102
+ mov qword [ wc.hInstance ], RAX ; [RBP - 112]
103
+
104
+ sub RSP , 32 + 16 ; Shadow space + 2 parameters
105
+ xor ECX , ECX
106
+ mov EDX , IDI_APPLICATION
107
+ mov R8D , IMAGE_ICON
108
+ xor R9D , R9D
109
+ mov qword [ RSP + 4 * 8 ], NULL
110
+ mov qword [ RSP + 5 * 8 ], LR_SHARED
111
+ call LoadImageA ; Large program icon
112
+ mov qword [ wc.hIcon ], RAX ; [RBP - 104]
113
+ add RSP , 48 ; Remove the 48 bytes
114
+
115
+ sub RSP , 32 + 16 ; Shadow space + 2 parameters
116
+ xor ECX , ECX
117
+ mov EDX , IDC_ARROW
118
+ mov R8D , IMAGE_CURSOR
119
+ xor R9D , R9D
120
+ mov qword [ RSP + 4 * 8 ], NULL
121
+ mov qword [ RSP + 5 * 8 ], LR_SHARED
122
+ call LoadImageA ; Cursor
123
+ mov qword [ wc.hCursor ], RAX ; [RBP - 96]
124
+ add RSP , 48 ; Remove the 48 bytes
125
+
126
+ mov qword [ wc.hbrBackground ], COLOR_WINDOW + 1 ; [RBP - 88]
127
+ mov qword [ wc.lpszMenuName ], NULL ; [RBP - 80]
128
+ lea RAX , [ REL ClassName ]
129
+ mov qword [ wc.lpszClassName ], RAX ; [RBP - 72]
130
+
131
+ sub RSP , 32 + 16 ; Shadow space + 2 parameters
132
+ xor ECX , ECX
133
+ mov EDX , IDI_APPLICATION
134
+ mov R8D , IMAGE_ICON
135
+ xor R9D , R9D
136
+ mov qword [ RSP + 4 * 8 ], NULL
137
+ mov qword [ RSP + 5 * 8 ], LR_SHARED
138
+ call LoadImageA ; Small program icon
139
+ mov qword [ wc.hIconSm ], RAX ; [RBP - 64]
140
+ add RSP , 48 ; Remove the 48 bytes
141
+
142
+ sub RSP , 32 ; 32 bytes of shadow space
143
+ lea RCX , [ wc ] ; [RBP - 136]
144
+ call RegisterClassExA
145
+ add RSP , 32 ; Remove the 32 bytes
146
+
147
+ sub RSP , 32 + 64 ; Shadow space + 8 parameters
148
+ mov ECX , WS_EX_COMPOSITED
149
+ lea RDX , [ REL ClassName ] ; Global
150
+ lea R8 , [ REL WindowName ] ; Global
151
+ mov R9D , WS_OVERLAPPEDWINDOW
152
+ mov dword [ RSP + 4 * 8 ], CW_USEDEFAULT
153
+ mov dword [ RSP + 5 * 8 ], CW_USEDEFAULT
154
+ mov dword [ RSP + 6 * 8 ], WindowWidth
155
+ mov dword [ RSP + 7 * 8 ], WindowHeight
156
+ mov qword [ RSP + 8 * 8 ], NULL
157
+ mov qword [ RSP + 9 * 8 ], NULL
158
+ mov RAX , qword [ REL hInstance ] ; Global
159
+ mov qword [ RSP + 10 * 8 ], RAX
160
+ mov qword [ RSP + 11 * 8 ], NULL
161
+ call CreateWindowExA
162
+ mov qword [ hWnd ], RAX ; [RBP - 8]
163
+ add RSP , 96 ; Remove the 96 bytes
164
+
165
+ sub RSP , 32 ; 32 bytes of shadow space
166
+ mov RCX , qword [ hWnd ] ; [RBP - 8]
167
+ mov EDX , SW_SHOWNORMAL
168
+ call ShowWindow
169
+ add RSP , 32 ; Remove the 32 bytes
170
+
171
+ sub RSP , 32 ; 32 bytes of shadow space
172
+ mov RCX , qword [ hWnd ] ; [RBP - 8]
173
+ call UpdateWindow
174
+ add RSP , 32 ; Remove the 32 bytes
175
+
176
+ .MessageLoop:
177
+ sub RSP , 32 ; 32 bytes of shadow space
178
+ lea RCX , [ msg ] ; [RBP - 56]
179
+ xor EDX , EDX
180
+ xor R8D , R8D
181
+ xor R9D , R9D
182
+ call GetMessageA
183
+ add RSP , 32 ; Remove the 32 bytes
184
+ cmp RAX , 0
185
+ je .Done
186
+
187
+ sub RSP , 32 ; 32 bytes of shadow space
188
+ mov RCX , qword [ hWnd ] ; [RBP - 8]
189
+ lea RDX , [ msg ] ; [RBP - 56]
190
+ call IsDialogMessageA ; For keyboard strokes
191
+ add RSP , 32 ; Remove the 32 bytes
192
+ cmp RAX , 0
193
+ jne .MessageLoop ; Skip TranslateMessage and DispatchMessageA
194
+
195
+ sub RSP , 32 ; 32 bytes of shadow space
196
+ lea RCX , [ msg ] ; [RBP - 56]
197
+ call TranslateMessage
198
+ add RSP , 32 ; Remove the 32 bytes
199
+
200
+ sub RSP , 32 ; 32 bytes of shadow space
201
+ lea RCX , [ msg ] ; [RBP - 56]
202
+ call DispatchMessageA
203
+ add RSP , 32 ; Remove the 32 bytes
204
+ jmp .MessageLoop
205
+
206
+ .Done:
207
+ mov RSP , RBP ; Remove the stack frame
208
+ pop RBP
209
+ xor EAX , EAX
210
+ ret
211
+
212
+ WndProc:
213
+ push RBP ; Set up a stack frame
214
+ mov RBP , RSP
215
+
216
+ %define hWnd RBP + 16 ; Location of the shadow space setup by
217
+ %define uMsg RBP + 24 ; the calling function
218
+ %define wParam RBP + 32
219
+ %define lParam RBP + 40
220
+
221
+ mov qword [ hWnd ], RCX ; Free up RCX RDX R8 R9 by spilling the
222
+ mov qword [ uMsg ], RDX ; 4 passed parameters to the shadow space
223
+ mov qword [ wParam ], R8 ; We can now access these parameters by name
224
+ mov qword [ lParam ], R9
225
+
226
+ cmp qword [ uMsg ], WM_DESTROY ; [RBP + 24]
227
+ je WMDESTROY
228
+
229
+ DefaultMessage:
230
+ sub RSP , 32 ; 32 bytes of shadow space
231
+ mov RCX , qword [ hWnd ] ; [RBP + 16]
232
+ mov RDX , qword [ uMsg ] ; [RBP + 24]
233
+ mov R8 , qword [ wParam ] ; [RBP + 32]
234
+ mov R9 , qword [ lParam ] ; [RBP + 40]
235
+ call DefWindowProcA
236
+ add RSP , 32 ; Remove the 32 bytes
237
+
238
+ mov RSP , RBP ; Remove the stack frame
239
+ pop RBP
240
+ ret
241
+
242
+ WMDESTROY:
243
+ sub RSP , 32 ; 32 bytes of shadow space
244
+ xor ECX , ECX
245
+ call PostQuitMessage
246
+ add RSP , 32 ; Remove the 32 bytes
247
+
248
+ xor EAX , EAX ; WM_DESTROY has been processed, return 0
249
+ mov RSP , RBP ; Remove the stack frame
250
+ pop RBP
251
+ ret
0 commit comments