-
Notifications
You must be signed in to change notification settings - Fork 0
/
lab.asm
482 lines (364 loc) · 9.52 KB
/
lab.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
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
; lab 6: iinterrrupts
.model TINY
.386
.code
org 80h
cmd_length db ?
cmd_line db ?
org 100h
begin:
jmp start_place
; ############################################## algorithms
; ################################################## / algorithms
; ################################################## support
prologue macro
push bp
mov bp, sp
endm
epilogue macro
mov sp, bp
pop bp
endm
; saves common registers
save_regs macro
push ax
push bx
push cx
push dx
push ds
push si
push es
push di
endm
; loads common registers
load_regs macro
pop di
pop es
pop si
pop ds
pop dx
pop cx
pop bx
pop ax
endm
; ################################################## / support
; ################################################################### I / O
; input : al - char to output
putc macro
save_regs
mov dl, al
mov ah, 02h
int 21h
load_regs
endm
; input : string - string adress
print_string macro string
save_regs
mov ah, 9
mov dx, offset string
int 21h
load_regs
endm
puts macro string
save_regs
print_string string
print_string newline
load_regs
endm
; char of number in al, ah
print_number proc far
push cx
mov cl, al
add cl, '0'
mov ch, attrib
mov word ptr es:bx, cx
add bx, 2
mov cl, ah
add cl, '0'
mov ch, attrib
mov word ptr es:bx, cx
add bx, 2
pop cx
ret
attrib db 050h
print_number endp
print_divider proc far
push cx
mov cl, ':'
mov ch, attrib
mov word ptr es:bx, cx
add bx, 2
pop cx
ret
div_attrib db 050h
print_divider endp
; prints time in x, y
print_time proc far
save_regs
; set up start cords
mov bx, 0b800h
mov es, bx
mov ax, 80 ; ax = 80 * 2
xor bx, bx ; bx = y
mov bl, time_y
mul bl ; ax = 80 * y * 2
mov bx, ax ; bx = 80 * y * 2
xor ax, ax
mov al, time_x ; ax = x
add bx, ax ; bx = 80 * y * 2 + 2 * x
; form address es:[bx] = b800h : [time_y * 80 * 2 + 2 * time_x]
mov ax, bx
mov bx, 2
mul bx
mov bx, ax
; print time directly in videobuffer
mov ah, 2ch
int 21h ; get system time ch hour, cl minute, dh second
xor ax, ax
mov al, ch
div base
call print_number
call print_divider
xor ax, ax
mov al, cl
div base
call print_number
call print_divider
xor ax, ax
mov al, dh
div base
call print_number
load_regs
ret
size_of_char db 2
base db 10
print_time endp
; ############################################################ / I / O
; ################################################## support
; string to integer
; get input askii string (c like) in es:si
; output in al
; if input is incorrect, set cf = 1
parse_decimal proc
push bx
mov ax, 0
mov bx, 0
mov parse_overflow, 0
get_char:
lodsb
cmp al, 0
je end_parsing_loop
cmp al, ' '
je get_char
cmp al, '0'
jb parse_decimal_error
cmp al, '9'
ja parse_decimal_error
sub al, '0'
add bx, ax ; bx = ax - '0' + bx * 10
lodsb ; crutch
cmp al, 0
je end_parsing_loop
dec si
mov ax, bx ; ax = bx
mov bx, 10
mul bl ; ax = bx * 10
jo parse_decimal_error
mov bx, ax ; bx = bx * 10
jmp get_char
end_parsing_loop:
mov ax, bx
cmp ax, limit
jge parse_decimal_error
jmp parse_decimal_end
parse_decimal_error:
mov parse_overflow, 1
parse_decimal_end:
pop bx
ret
limit dw 0fffh
parse_overflow db 0
parse_decimal endp
; prints decimal number to stdout
; input in ax
print_decimal proc
push ax
push cx
push dx
push di
std ; prepare string buffer to writing
lea di, buffer_end-1
mov cx, 10 ; set base of calculation system
pd_base equ cx
Repeat:
xor dx,dx
div pd_base ; dx stores residue, ax stores quotient
xchg ax,dx
add al,'0'
stosb ; add digit to output
xchg ax,dx
or ax,ax ; check if quotient is zero
jne Repeat
mov ah,9
lea dx,[di+1] ; output string (di + 1 is address of string start)
int 21h
pop di
pop dx
pop cx
pop ax
ret
buffer_string db 5 dup ('$')
buffer_end db '$'
print_decimal endp
get_argv proc
pusha
mov get_argv_error, 0
cld
mov cl, cmd_length ; check for emptyness
cmp cl, 1
jle incorrect_error
mov cx, -1 ; set up start position, make cx work line infinity
mov di, offset cmd_line
find_param:
mov al, ' '
repz scasb
dec di ; skip spaces
push di
inc word ptr argc ; save parameter
mov si, di
scan_params: ; get char, compare it to ends, handle ends
lodsb
cmp al, 0dh
je params_ended
cmp al, 20h
je end_scan_params
cmp al, '0'
jl incorrect_error
cmp al, '9'
jg incorrect_error
jmp scan_params
end_scan_params:
dec si
mov byte ptr [si], 0 ; set end of parameter as \0
mov di, si
inc di
jmp short find_param
params_ended:
dec si
mov byte ptr [si], 0
; parameters handling
cmp argc, 2
jne incorrect_error
parse_paramoters:
dec argc
pop si
mov limit, 25
call parse_decimal
cmp parse_overflow, 1
je overflow
mov time_y, al
dec argc
pop si
mov limit, 72
call parse_decimal
cmp parse_overflow, 1
je overflow
mov time_x, al
jmp get_argv_end
incorrect_error:
mov cx, argc
free_loop:
pop bx
loop free_loop
puts empty_error_text
mov get_argv_error, 1
jmp get_argv_end
overflow:
mov cx, argc
free_loop_2:
pop bx
loop free_loop_2
puts overflow_text
mov get_argv_error, 1
get_argv_end:
popa
ret
argc dw 0
empty_error_text db "input a cords of clock, example: 20 20", '$'
overflow_text db "your args are too big", '$'
debug db "debug", '$'
get_argv_error db 0
get_argv endp
; ################################################## / support
; ################################################## interrupts
old_timer_int dd ?
timer_int proc
pushf
call cs: old_timer_int
pusha
push ds
push es
push cs
pop ds ; setup ds
;
call print_time
;
pop es
pop ds
popa
iret
timer_int endp
timer_install proc
; get old interrupt
mov ah, 35h
mov al, 08h
int 21h
mov word ptr old_timer_int, bx
mov word ptr old_timer_int + 2, es
; set new interrupt
mov ah, 25h
mov al, 08h
lea dx, timer_int
int 21h
ret
timer_install endp
; ################################################## /interrupts
; ############################################################################# main
main proc
call get_argv
cmp get_argv_error, 1
jne not_main_end
jmp main_end
not_main_end:
puts processing_message
puts x_res
xor ax, ax
mov al, time_x
call print_decimal
print_string newline
puts y_res
xor ax, ax
mov al, time_y
call print_decimal
print_string newline
puts result_message
call timer_install
main_end:
ret
processing_message db "setup clock...", '$'
result_message db "successful", '$'
main endp
; ############################################################################# / main
start_place:
call main
mov ax, 3100h
mov dx, (start_place - begin + 10fh) / 16
int 21h
; ################### additional data
time_x db 0
time_y db 0
; support variables
newline db 0dh, 0ah, '$'
x_res db "your x cords:$"
y_res db "your y cords:$"
end begin