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
| .model small
.code
nval=12; число вводимых 3 значных чисел
start: jmp beg
p1 db 13,10,"Input 12 3digit values:",13,10
db "001,002,003,004,005,006,007,008,009,010,011,012"
db 13,10,0; 0 - признак конца строки
badinp db 13,10,"Input error ? Place digits exactly to same positions",13,10,0
; Числа в файлах сохраняются в текстовом формате с разделителем CR,LF (13,10)
filename0 db "abc.txt",0; имена файлов
filename1 db "aaa.txt",0
filename2 db "bbb.txt",0
inputbuf db 128 dup (0); буфер ввода текста
outbuf db 128 dup (0); буфер вывода текста в файл
beg: push cs; ds=cs, es=cs
pop ds
push cs
pop es
mov ax,offset p1; подсказка
call printline
mov dx,offset inputbuf; ввод строки текста (но не более, чем 128 байт)
mov cx,128
mov bx,0; = stdin
mov ah,3Fh; чтение stdin (т е обычно клавиатуры)
int 21h
cmp ax,nval*4+1; не слишком ли короткий ввод
; (также учитываются байты CR,LF) ?
jc exit
cld
mov si,offset inputbuf; проверим, действительно ли введены цифры
mov cx,nval
m1: lodsb
call isdigit
jc nodigit
lodsb
call isdigit
jc nodigit
lodsb
call isdigit
jc nodigit
inc si ; 4й символ-разделитель не проверяем (т е числа можно вводить
; не через запятую, а например через пробел)
loop m1
mov dx,offset filename0; файл abc.txt - просто копируем
mov bx,offset task0 ; см ниже
call operate
mov dx,offset filename1; файл aaa.txt - по условию задачи
mov bx,offset task1
call operate
mov dx,offset filename2; файл bbb.txt - по условию задачи
mov bx,offset task2
call operate
exit: ; выход в DOS
mov ax,4c00h
int 21h
nodigit: mov ax,offset badinp ; подсказка, что неверный ввод
call printline
jmp exit
;=========
; Для всех файлов используется эта подпрограмма
; Вход dx - имя файла, bx - адрес функции, которая определяет копировать число в файл или нет
operate:mov si,offset inputbuf
mov di,offset outbuf
mov cx,nval
m2: push si
call bx; копировать ? (вызов подпрограммы по адресу bx)
jc m3 ; CY=1 - нет
movsb ; копировать 3 цифры
movsb
movsb
mov ax,0A0Dh; вместо 1 байта разделителя мы пишем перевод строки (2 байта)
stosw
m3: pop si
add si,4; следующие 4 символа (3 цифры и разделитель)
loop m2 ; конец цикла
mov al,0; 0 - признак конца файла
stosb
mov ah,3Ch ; создать файл с именем ds:dx для чтения-записи
int 21h
jc exit ; выход по ошибке
mov bx,ax ; bx=дескриптор файла
mov ax,offset outbuf; пишем outbuf в файл
call printlinefile
mov ah,3Eh ; закрыть файл
int 21h
ret
; task0, task1, task2
; вход - SI - указатель на 3 цифры (символа)
; выход CY=0 - да, CY=1 - нет
task1: push si ; задача 1
mov ah,0
lodsb ; если первую цифру ...
and al,0Fh
add ah,al
lodsb
and al,0Fh
add ah,al ; сложить со второй ...
lodsb
and al,0Fh
cmp ah,al ; и сравнить с третьей ...
pop si
jg task0 ; x1+x2>x3 ? то будет ли сумма больше (>), чем третья цифра ?
; (см учебник "Математика 1й класс", 1е полугодие)
stc ; нет, CY=1
ret
task0: clc ; да, CY=0 (эта же подпрограмма используется для простого копирования всех чисел в
ret ; файл "abc.txt", всегда возвращая "да")
task2: push si ; задача 2 аналогично
mov ah,0
lodsb
and al,0Fh
add ah,al
lodsb
and al,0Fh
add ah,al
lodsb
and al,0Fh
cmp ah,al
pop si
jl task0 ; x1+x2<x3 ?
stc
ret
; Это цифра ? Возвращает CY=0 - да, CY=1 - нет
isdigit:cmp al,"0"
jc idc1
cmp al,"9"+1
cmc
idc1: ret
; вывод текста на консоль или в файл
printline: mov bx,1 ; stdout
printlinefile:
; вывод текста на консоль - все равно, что запись в файл с дескриптором 1
; CS:AX - указатель на строку текста
push dx
push cx
push ax
mov cl,0 ; признак конца строки
call strlen; cx=длина строки
mov dx,ax; dx=указатель на строку
mov ah,40h; write
int 21h
pop ax
pop cx
pop dx
ret
; вычисление длины строки
; на входе: cl=байт признак конца строки
strlen: push ax; на выходе: cx=длина строки (но строка не должна быть длиннее 255 символов)
push di
mov di,ax
mov al,cl
mov cx,256
repne scasb
xor cl,255
mov ch,0
pop di
pop ax
ret
end start |