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
| oursg segment
assume cs:oursg, ds:oursg ;определение адреса сегмента в регистр
FileName db 'file.txt',0 ; наименование файла
Handle dw ? ; описатель файла
Buffer db 7 dup(?) ; буфер для записи данных в файл
mas db 15*15 dup(?) ; массив
N dw ? ; размерность массива
CrLf db 13,10 ; последовательность для перевода строки
Mn_10 dw 10 ; основание системы счисления
max_el db ?
i dw ?
j dw ?
imax dw ?
jmax dw ?
; выводимые сообщения
mInpMas db 13,10,'Input massiv:',13,10,'$'
mN db 10,13,'N(1..15)= $'
mLine db 'Line $'
mErrCr db 'Error create file$'
mDone db 'Done$'
maxElem db 13,10,'Максимальный элемент массива: $'
ErrCr: ; ошибка создания файла
lea dx,mErrCr ; адрес выводимого сообщения
jmp Print ; переход к выводу сообщения
begin:
mov ax,oursg ; настройка сегментных регистров
mov ds,ax
mov es,ax
; создание файла
mov ah,3ch ; функция создания файла
xor cx,cx ; аттрибут создаваемого файла
lea dx,FileName ; имя файла
int 21h ; создать файл
jc ErrCr
mov Handle,ax ; сохранить описатель файла
; ввод размерности массива
readN: ; ввод размерности N
mov ah,9 ; функция вывода сообщения
lea dx,mN ; адрес выводимого сообщения
int 21h ; вывод сообщения
call in_int ; ввод числа с клавиатуры
cmp ax,1 ; если введенное число меньше 1
jl readN ; тогда ввести заново
cmp ax,15 ; если число больше 15
ja readN ; тогда ввести заново
mov N,ax ; сохранить размерность массива
lea di,mas ; адрес начала массива
; ввод массива
mov si,1 ; SI =1 - индекс вводимой строки
mov ah,9 ; функция вывода сообщения на экран
lea dx,mInpMas ; адрес выводимого сообщения
int 21h ; вывод сообщения
inp_el_line:
mov ah,9 ; функция вывода сообщения на экран
lea dx,mLine ; адрес выводимого сообщения
int 21h ; вывод сообщения
mov ax,si ; номер вводимой строки
call out_Scr ; вывести номер строки на экран
mov cx,N ; количество элементов в строке
inp_el: ; цикл ввода элементов строки
call in_int ; вызываем процедуру ввода целого числа
stosb ; сохраняем значение AL -> ES:DI, DI=DI+1
call out_File ; записать введенное число в файл
loop inp_el ; цикл ввода элементов строки массива
call NewLine ; переход на новую строку
inc si ; следующая строка
cmp si,N ; сравнить номер строки с размерностью массива
jbe inp_el_line ; если номер строки не вышел из диапозона, то перейти
call NewLine ; переход на новую строку
mov bx, 0
lea di, Mas[bx] ; адрес элемента ВХ в первой строке
mov bh, byte ptr [di]
mov i, 0
mov cx,N ;число для внешнего
;цикла (по строкам)
external: ;внешний цикл по строкам
push cx ;сохранение в стеке счётчика
;внешнего цикла
mov cx,N ;число для внутреннего цикла
;(по столбцам)
mov j,0
iternal:
inc di
cmp bh, byte ptr [di]
jng metka
mov bh, byte ptr [di]
mov dx, i
MOV imax, dx
;xor dx, dx
mov dx, j
MOV jmax, dx
metka:
inc j
loop iternal
move_next: ;продвижение в матрице
pop cx ;восстанавливаем CX из стека (5)
inc i ;передвигаемся на следующую строку
loop external ;цикл (внешний)
mov max_el, bh
call NewLine
mov ax, max_el
call out_file
call NewLine
mov ax, imax
call out_file
call NewLine
mov ax, jmax
call out_file
call NewLine
call NewLine
mov ax, i
call out_file
call NewLine
mov ax, j
call out_file
mov ah,9 ; функция вывода сообщения на экран
lea dx, max_el ; адрес выводимого сообщения
int 21h ; вывод сообщения
lea dx,mDone ; адрес выводимого сообщения
CloseFile:
; закрытие файла
mov ah,3eh ; функция закрытия файла
mov bx,Handle ; описатель файла
int 21h ; закрыть файл
Print:
; вывод сообщения
mov ah,9 ; функция вывода сообщения
int 21h ; вывод сообщения
mov ah,8 ; очистка буфера ввода
mov al,1 ; с последующим вводом символа с клавиатуры
int 21h ; чистим буфер, ждем ввода
mov ah,4ch ; функция завершения программы
int 21h ; завершить программу
; ===========================================
out_scr proc
; процедура выводит значение регистра АХ на экран
push bx ; сохранить значение регистра
mov bx,1 ; Handle экрана
call out_int ; вывод регистра АХ в файл с описателем из ВХ
pop bx ; восстановить значение регистра из стека
ret ; возврат из процедуры
out_scr endp
; ===========================================
out_File proc
; процедура выводит значение регистра АХ в файл
push bx ; сохранить значение регистра
mov bx,Handle ; Handle файла
call out_int ; вывод регистра АХ в файл с описателем из ВХ
pop bx ; восстановить значение регистра из стека
ret ; возврат из процедуры
out_File endp
; ============================================
out_int proc
; процедура производит вывод числа из регистра АХ в файл с описателем из ВХ
push cx ; сохранение используемых регистров в стеке
push dx
push di
lea di,Buffer ; адрес формируемой строки для вывода
mov cx,0 ; cx - счетчик количества цифр в числе AX
;выделение цифр из числа
cmp ax,0 ; проверка на отрицательность
jge vyd_char ; перейти на метку, если число положительное
mov byte ptr [di],'-' ; иначе поместить в формируемую строку минус
inc di ; установить указатель на следующую позиция
neg ax ; поменять знак числа
vyd_char:
mov dx,0 ; делимое находится в регистровой паре DX:AX, DX = 0
div Mn_10 ; разделить на Mn (=10), АХ - частное от деления, DX - остаток от деления
; в DL содержится правая цифра, AX - старшие разряды числа
add dl,'0' ; преобразуем цифру в соответствующий символ
push dx ; и сохраняем в стеке для последующего вывода в обратном порядке
inc cx ; увеличиваем количество символов в числе на 1
cmp ax,0 ; если остаточное число не равно 0
jne vyd_char ; тогда выделяем следующую цифру
;формирование строки из выделенных цифр
char2buffer:
pop ax ; АL - код выводимого символа (ранее сохраненый)
stosb ; записать в формируемую строку, AL->DS:[di], di=di+1
loop char2buffer ; повторять СХ раз - количество выделенных цифр
mov byte ptr [di],9 ; поместить код табуляции после числа
mov ah,40h ; функция записи в файл через его описатель из ВХ
lea dx,Buffer ; адрес начала записываемой строки
mov cx,di ; вычисление длины строки
sub cx,dx
inc cx
int 21h ; записываем в файл
pop di ;восстановление значений
pop dx ;регистров сохраненные в начале процедуры
pop cx
ret ;возрат из процедуры
out_int endp
;=========================================================
NewLine Proc
; процедура производит переход на следующую строку на экране и в файле
push ax ; сохранение используемых регистров
push bx
push cx
push dx
; запись перевода строки в файл
mov ah,40h ; функция записи в файл
lea dx,CrLf ; записываемые данные
mov cx,2 ; длиной 2 байта
mov bx,Handle ; описатель файла
int 21h ; записать в файл
; запись перевода строки на экран
mov ah,40h ; функция записи в файл
mov bx,1 ; Handle экрана
int 21h ; вывод на экран, DX и CX остались с предшествующего вызова
pop dx ; восстановить значение регистров из стека
pop cx
pop bx
pop ax
ret
NewLine endp
;=========================================================
in_int proc
;процедура ввода целочисленного числа с клавиатуры. Признаком окончания ввода является
; нажатие любой,не цифровой клавиши
;Вход: -
;Выход: АХ - введенное число
push dx ; сохранить в стэке значения регистров
push cx ; используемых в процедуре
push bx
xor cx,cx ; начальное число - ноль
mov bx,cx ; признак положительного числа
mov ah,01h ; функция ввода символа с клавиатуры
int 21h ; вызов прерывания DOS, в AL - код нажатой клавиши
cmp al,'-' ; первый символ минус?
jne no_in_minus ; если нет то перейти на метку
mov bx,1 ; иначе установить признак отрицательного числа
inp_int:
mov ah,01h ; функция ввода символа с клавиатуры
int 21h ; вызов прерывания DOS, в AL - код нажатой клавиши
no_in_minus:
sub al,'0' ; преобразовываем код в соответствующую цифру
jb in_no_number ; если меньше ноля - значит нажата не цифра, переходим
cmp al,9 ; сравниваем с 9
ja in_no_number ; если больше - значит нажата не цифра, переходим
xchg ax,cx ; обмениваем значения регистров AX и CX между собой
mul Mn_10 ; умножаем ранее введенное число на 10 - "сдвигаем влево", результат в DX:AX
mov ch,0
add cx,ax ; добавляем к введенной цифре ранее введенные разряды
jmp inp_int ; вводим следующую цифру
in_no_number:
mov ax,cx ; помещаем в АХ введенное число
cmp bx,0 ; проверка признака отрицательного числа
jz in_plus
neg ax ; если отрицательное - изменить знак
in_plus:
pop bx
pop cx ; восстанавливаем из стэка, значения регистров
pop dx ; сохранненые в начале процедуры
ret ; возврат из процедуры
in_int endp
;=========================================================
oursg ends
END begin ; точка входа - начало выполнения программы |