-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathproblem41.asm
executable file
·338 lines (254 loc) · 4.73 KB
/
problem41.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
.386
.MODEL FLAT
.STACK 4096
EXTRN _HeapFree@12:NEAR32
EXTRN _HeapAlloc@12:NEAR32
EXTRN _GetProcessHeap@0:NEAR32
EXTRN _GetStdHandle@4:NEAR32
EXTRN _ExitProcess@4:NEAR32
EXTRN _WriteConsoleA@20:NEAR32
.DATA
prime_table DWORD 0
stdout DWORD 0
written DWORD 0
arr BYTE "987654321"
arr_end BYTE 0Dh, 0Ah, 0
.CODE
writeln MACRO ; Destroys eax, ecx, edx; put buffer in eax
local _loop, _end
mov ecx, eax
_loop:
cmp BYTE PTR [ecx], 0
je _end
inc ecx
jmp _loop
_end:
sub ecx, eax
mov edx, stdout
pushd 0
push OFFSET written
push ecx
push eax
push edx
call _WriteConsoleA@20
ENDM
sieve MACRO ; Destroys eax, ecx, edx
local aaa, _outer_loop, _inner_loop, _skip, _end
mov ecx, 2
_outer_loop:
cmp ecx, 987654321
ja _end
push ecx
call get_bit
pop ecx
cmp eax, 0
jne _skip
mov eax, ecx
_inner_loop:
add eax, ecx
cmp eax, 987654321
ja _skip
push ecx
push eax
call put_bit
pop eax
pop ecx
jmp _inner_loop
_skip:
inc ecx
jmp _outer_loop
_end:
ENDM
_start:
pushd -11 ; STD_OUTPUT_HANDLE
call _GetStdHandle@4
mov stdout, eax
call _GetProcessHeap@0
pushd 123456791
pushd 8 ; HEAP_ZERO_MEMORY
push eax
call _HeapAlloc@12
mov prime_table, eax
sieve
lea ebx, arr
main_loop:
push ebx
call str_to_int
add esp, 4
push eax
call is_prime
add esp, 4
cmp eax, 1
je success
push ebx
call next_perm
add esp, 4
cmp eax, 1
je main_loop
call reset
inc ebx
lea eax, arr_end
cmp ebx, eax
jb main_loop
success:
mov eax, ebx
writeln
call _GetProcessHeap@0
mov ebx, prime_table
push ebx
pushd 0
push eax
call _HeapFree@12
pushd 0
call _ExitProcess@4
;; All of these procedures are cdecl, unless explicitly stated otherwise
;; void reset();
reset PROC
pushfd
mov cl, '9'
lea eax, arr
reset_loop:
mov [eax], cl
dec cl
inc eax
cmp cl, '0'
jne reset_loop
popfd
ret
reset ENDP
;; uint32_t next_perm(uint32_t start); // Returns whether there was a next permutation
next_perm PROC
push ebp
mov ebp, esp
pushfd
push ebx
;; Initialize
mov eax, 0
mov ebx, [ebp + 8]
lea ecx, arr_end
sub ecx, 2
;; Identify pivot
next_perm_pivot:
cmp ecx, ebx
jb next_perm_end
mov dl, [ecx]
mov dh, [ecx + 1]
cmp dl, dh
ja next_perm_has_pivot
dec ecx
jmp next_perm_pivot
next_perm_has_pivot:
lea eax, arr_end
dec eax
;; Identify swap point
next_perm_locate_swap:
mov dh, [eax]
cmp dl, dh
ja next_perm_locate_has_swap
dec eax
jmp next_perm_locate_swap
next_perm_locate_has_swap:
xchg dl, [eax]
xchg dh, [ecx]
;; Reverse the suffix
lea eax, arr_end
next_perm_rev_loop:
dec eax
inc ecx
cmp ecx, eax
jae next_perm_end_loop
mov dl, [eax]
xchg dl, [ecx]
mov [eax], dl
next_perm_end_loop:
mov eax, 1
next_perm_end:
pop ebx
popfd
pop ebp
ret
next_perm ENDP
;; uint32_t get_bit(uint32_t n);
get_bit PROC
push ebp
mov ebp, esp
push ebx
pushfd
mov eax, [ebp + 8]
mov ebx, prime_table
mov edx, 0
mov ecx, 8
div ecx
add ebx, eax
mov al, [ebx]
mov cl, dl
shr al, cl
and eax, 1
popfd
pop ebx
pop ebp
ret
get_bit ENDP
;; void put_bit(uint32_t n);
put_bit PROC
push ebp
mov ebp, esp
push ebx
pushfd
mov eax, [ebp + 8]
mov ebx, prime_table
mov edx, 0
mov ecx, 8
div ecx
add ebx, eax
mov al, [ebx]
mov cl, dl
mov edx, 1
shl dl, cl
or al, dl
mov [ebx], al
popfd
pop ebx
pop ebp
ret
put_bit ENDP
;; uint32_t is_prime(uint32_t n);
is_prime PROC
push ebp
mov ebp, esp
pushfd
mov eax, [ebp + 8]
push eax
call get_bit
add esp, 4
xor eax, 1
popfd
pop ebp
ret
is_prime ENDP
;; uint32_t str_to_int(uint32_t ptr);
str_to_int PROC
push ebp
mov ebp, esp
pushfd
mov eax, 0
mov ecx, [ebp + 8]
sti_loop:
mov dl, 0Dh
cmp [ecx], dl
je sti_end
mov edx, 10
mul edx
mov dl, [ecx]
sub dl, '0'
movzx edx, dl
add eax, edx
inc ecx
jmp sti_loop
sti_end:
popfd
pop ebp
ret
str_to_int ENDP
PUBLIC _start
END _start