-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathguess.asm
441 lines (290 loc) · 6.1 KB
/
guess.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
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
; Guessing game source code
; Beta 1.0
;
; Lim Ding Wen
; Singapore, 659442
section .text
global _start
_start:
; Get random number
call __open
mov ebx, _dev_random
mov ecx, 0 ; RDONLY
call __syscall
mov ebx, eax
push eax
call __read
mov ecx, randint
mov edx, 4 ; 4 bytes of random; 32-bit
call __syscall
call __close
pop ebx
call __syscall
mov eax, [randint]
jmp _modend
_modup:
add eax, maxrand
jmp _modend
_moddown:
sub eax, maxrand
_modend:
cmp eax, maxrand
jg _moddown
cmp eax, 1 ; Is it lower than 1?
jl _modup
mov [randint], eax
;call __write
;mov ebx, 1
;mov ecx, randint
;mov edx, 4
;call __syscall
; Write hello message
call __write
mov ebx, 1 ; Stdout
mov ecx, hello
mov edx, hello_len
call __syscall
_loop:
; Write prompt
mov eax, [tries]
mov ebx, 1 ; Optimization warning: May change. Do not use if tries > 9. Use standard __itoa instead.
mov ecx, 10 ; Optimized
call __itoa_knowndigits
mov ecx, eax
mov edx, ebx
call __write
mov ebx, 1 ; Stdout
call __syscall
call __write
mov ebx, 1 ; Stdout
mov ecx, prompt
mov edx, prompt_len
call __syscall
; Read input
call __read
mov ebx, 0 ; Stdin
mov ecx, inputbuf
mov edx, inputbuf_len
call __syscall
; Convert into integer
mov ecx, eax
sub ecx, 1 ; Get rid of extra newline
cmp ecx, 1 ; Is the length of the number less than 1? (invalid)
jl _reenter
mov ebx, ecx
mov eax, 0 ; Initalize eax
jmp _loopconvert_nomul
_loopconvert:
imul eax, 10 ; Multiply by 10
_loopconvert_nomul:
mov edx, ebx
sub edx, ecx
push eax
mov ah, [inputbuf+edx]
sub ah, 48 ; ASCII digits offset
cmp ah, 0 ; Less than 0?
jl _reenter
cmp ah, 9 ; More than 9?
jg _reenter
movzx edx, ah
pop eax
add eax, edx
loop _loopconvert
jmp _convertok
_reenter:
; Write message
call __write
mov ebx, 1 ; Stdout
mov ecx, reenter
mov edx, reenter_len
call __syscall
; Repeat enter
jmp _loop
_toohigh:
call __write
mov ebx, 1 ; Stdout
mov ecx, toohigh
mov edx, toohigh_len
call __syscall
jmp _again
_toolow:
call __write
mov ebx, 1 ; Stdout
mov ecx, toolow
mov edx, toolow_len
call __syscall
_again:
cmp dword [tries], 1 ; Is this the last try?
jle _lose
sub dword [tries], 1 ; Minus one try.
jmp _loop
_lose:
; You lose
call __write
mov ebx, 1 ; Stdout
mov ecx, youlose
mov edx, youlose_len
call __syscall
mov eax, [randint]
call __itoa
mov ecx, eax
mov edx, ebx
call __write
mov ebx, 1 ; Stdout
call __syscall
call __write
mov ebx, 1 ; Stdout
mov ecx, youlose2
mov edx, youlose2_len
call __syscall
mov ebx, 2 ; Exit code for OK, lose.
jmp _exit
_convertok:
; Compare input
cmp eax, [randint]
jg _toohigh
jl _toolow
; You win
call __write
mov ebx, 1 ; Stdout
mov ecx, youwin
mov edx, youwin_len
call __syscall
mov ebx, 1 ; Exit code for OK, win.
_exit:
push ebx
; Print normal goodbye
call __write
mov ebx, 1 ; Stdout
mov ecx, goodbye
mov edx, goodbye_len
call __syscall
mov ebx, 2 ; Stderr
call __syscall
; Report OK.
call __write
mov ebx, 1 ; Stdout
mov ecx, _ok
mov edx, _ok_len
call __syscall
mov ebx, 2 ; Stderr
call __syscall
; Exit
call __exit
pop ebx
call __syscall
; Procedures
__itoa_init:
; push eax
; push ebx
; We do not have to preserve as it will contain
; A return value
pop dword [_itoabuf]
push ecx
push edx
push dword [_itoabuf]
ret
__itoa: ; Accept eax (i), return eax (a), ebx (l)
call __itoa_init
mov ecx, 10 ; Start with 10 (first 2-digit)
mov ebx, 1 ; If less than 10, it has 1 digit.
__itoa_loop:
cmp eax, ecx
jl __itoa_loopend
imul ecx, 10 ; Then go to 100, 1000...
add ebx, 1 ; Then go to 2, 3...
jmp __itoa_loop
__itoa_knowndigits: ; Accept eax (i), ebx (d), ecx (m), return eax (a), ebx (l)
call __itoa_init
__itoa_loopend:
; Prepare for loop
; edx now contains m
; ecx is now ready to count.
; eax already has i
; ebx already has d.
mov edx, ecx
mov ecx, ebx
push ebx
__itoa_loop2:
push eax
; Divide m by 10 into m
mov eax, edx
mov edx, 0 ; Exponent is 0
mov ebx, 10 ; Divide by 10
idiv ebx
mov ebx, eax ; New m
; Divide number by new m into (1)
mov eax, [esp] ; Number
mov edx, 0 ; Exponent is 0
idiv ebx ; (1)
; Store into buffer
mov edx, [esp+4] ; Each dword has 4 bytes
sub edx, ecx
add eax, 48 ; Offset (1) as ASCII number
mov [_itoabuf+edx], eax
sub eax, 48 ; Un-offset (1) to prepare for next step
; Multiply (1) by m into (1)
imul eax, ebx
; Subtract number by (1) into number
mov edx, ebx ; Restore new-m back to edx as m
pop ebx ; Number
sub ebx, eax ; New number
mov eax, ebx
loop __itoa_loop2
; Return buffer array address and
; Pop preserved ebx as length
mov eax, _itoabuf
pop ebx
; Pop preserved registers and restore
pop edx
pop ecx
ret
__exit:
mov eax, 1 ; Exit syscall
ret
__read:
mov eax, 3 ; Read syscall
ret
__write:
mov eax, 4 ; Write syscall
ret
__open:
mov eax, 5 ; Open syscall
ret
__close:
mov eax, 6 ; Close syscall
ret
__syscall:
int 0x80 ; Interupt kernel
ret
; Data declaration
section .data
_dev_random db "/dev/random", 0x0
maxrand equ 100
tries dd 6
prompt db " tries left. Input number (1-100): "
prompt_len equ $-prompt
hello db 0xa, "Welcome to the guessing game!", 0xa, "I am now thinking of a number. What is it?", 0xa, "Take a guess, from one to one hundred.", 0xa, 0xa
hello_len equ $-hello
reenter db "? REENTER", 0xa, "Invalid unsigned integer. Please re-enter your input.", 0xa
reenter_len equ $-reenter
toohigh db "That was too high!", 0xa, 0xa
toohigh_len equ $-toohigh
toolow db "That was too low!", 0xa, 0xa
toolow_len equ $-toolow
youwin db 0x7, 0xa, "#^$&^@%#^@#! That was correct! You win!", 0xa, 0xa
youwin_len equ $-youwin
youlose db "You have no more tries left! You lose!", 0xa, "The answer was "
youlose_len equ $-youlose
youlose2 db "! Mwahahah!", 0xa, 0xa
youlose2_len equ $-youlose2
goodbye db "Goodbye.", 0xa
goodbye_len equ $-goodbye
_ok db "Exit OK. There were no errors.", 0xa, 0xa
_ok_len equ $-_ok
section .bss
randint resw 2
downsize resw 2
_itoabuf resb 1024
inputbuf resb 1024
inputbuf_len equ 1024