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
|
;Кодировка input файла windows-866
code_seg segment
assume cs:code_seg,ds:code_seg,ss:code_seg
org 100h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
start:
jmp begin
get_vector macro vector, DD_for_save_vector
mov AX,35&vector ; получить
; вектор
int 21h ; прерывания 2Fh
mov word ptr DD_for_save_vector,BX ; ES:BX - вектор
mov word ptr DD_for_save_vector+2,ES ;
;
endm
;
set_vector macro vector, handler
mov DX,offset handler ; получить смещение точки входа в новый
; ; обработчик на DX
mov AX,25&vector ; функция установки прерывания
; ; изменить вектор 2Fh
int 21h ; AL - номер прерыв. DS:DX - указатель программы обработки прер.
endm
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;----------------------------------------------------------------------------
;flag DB 0
high_Y DB 0
left_X DB 0
low_Y DB 23
right_X DB 80
;
page_num DB 0
coord_Y DB 11
coord_X DB 57
st_coord_Y DB 24
st_coord_X DB 5
;============================================================================
;----------------------------------------------------------------------------
int_2Fh_vector DD ?
old_09h DD ?
FileName DB 14,0,14 dup ('$')
handle DW ? ;ячейка для дескриптора
new_09h proc near
push ax
in AL,60h ; Введем scan-code
cmp AL, 11h
je hotkey
cmp AL, 1Fh
je hotkey
mov combo_key, 0
go_out:
pop ax
jmp CS:old_09h ; В системный обработчик без возврата
hotkey:
cmp combo_key, AL
je go_out
cmp combo_key, 0
mov combo_key, AL
je go_out
sti ; Не будем мешать таймеру
in AL,61h ; Введем содержимое порта B
or AL,80h ; Установим старший бит
out 61h,AL ; и вернем в порт B.
and AL,7Fh ; Снова разрешим работу клавиатуры,
out 61h,AL ; сбросив старший бит порта B.
;
;-------------------- Вывод окна средствами BIOS ---------------------------
;inc CS:flag ; Признак вывода окна
push BX
push CX
push DX
lea DX, CS:FileName + 2
mov AX, 3D02h ; Open file for read/write
int 21h
mov err_code, AL
mov AX, 0600h ; Задание окна
mov BH, 70h ; Атрибут черный по серому
mov CH, CS:high_Y ; Ко-
mov CL, CS:left_X ; ор-
mov DH, CS:low_Y ; ди-
mov DL, CS:right_X ; наты окна
int 10h
;----------------------------------------------------------------------------
; ------------------------ Позиционируем курсор -----------------------------
mov AH, 03h
mov BH,CS:page_num
int 10h
mov st_coord_Y, DH
mov st_coord_X, DL
mov AH,02h ; Функция позиционирования
mov BH,CS:page_num ; Видеостраница
mov DH,CS:coord_Y ; Строка
mov DL,CS:coord_X ; Столбец
int 10h
; Выведем в окно строку символов без задания атрибутов (с атрибутами окна)
xor CX, CX
mov CL,6 ; Длина строки
mov BX, offset CS:FileName + 2 ; Адрес строки
mov AH,0Eh ; Функция вывода одного символа
add err_code, '0'
mov AL, err_code
int 10h
next_sym:
mov AL,CS:[BX] ; Символ в AL
inc BX ; Сдвиг по строке
int 10h ;
loop next_sym ; Цикл по строкеs
mov AH,02h ; Функция позиционирования
mov BH,CS:page_num ; Видеостраница
mov DH,CS:st_coord_Y ; Строка
mov DL,CS:st_coord_X ; Столбец
int 10h
;============================================================================
;
pop DX
pop CX
pop BX
;--------------------------------------------------------------------------
cli
mov AL, 20h ; Пошлем
out 20h,AL ; приказ EOI
pop ax
iret
new_09h endp
;==================================================================================
;
int_2Fh proc far
cmp AH,0C7h ; Наш номер?
jne Pass_2Fh ; Нет, на выход
cmp AL,00h ; Подфункция проверки на повторную установку?
je inst ; Программа уже установлена
cmp AL,01h ; Подфункция выгрузки?
je unins ; Да, на выгрузку
jmp short Pass_2Fh ; Неизвестная подфункция - на выход
inst:
mov AL,0FFh ; Сообщим о невозможности повторной установки
iret
Pass_2Fh:
jmp dword PTR CS:[int_2Fh_vector]
;
; -------------- Проверка - возможна ли выгрузка программы из памяти ? ------
unins:
push BX
push CX
push DX
push ES
;
mov CX,CS ; Пригодится для сравнения, т.к. с CS сравнивать нельзя
mov AX,3509h ; Проверить вектор 09h
int 21h ; Функция 35h в AL - номер прерывания. Возврат-вектор в ES:BX
;
mov DX,ES
cmp CX,DX
jne Not_remove
;
cmp BX, offset CS:new_09h
jne Not_remove
;
mov AX,352Fh ; Проверить вектор 2Fh
int 21h ; Функция 35h в AL - номер прерывания. Возврат-вектор в ES:BX
;
mov DX,ES
cmp CX,DX
jne Not_remove
;
cmp BX, offset CS:int_2Fh
jne Not_remove
; ---------------------- Выгрузка программы из памяти ---------------------
;
push DS
;
lds DX, CS:old_09h ; Эта команда эквивалентна следующим двум
; mov DX, word ptr old_09h
; mov DS, word ptr old_09h+2
mov AX,2509h ; Заполнение вектора старым содержимым
int 21h
;
lds DX, CS:int_2Fh_vector ; Эта команда эквивалентна следующим двум
; mov DX, word ptr int_2Fh_vector
; mov DS, word ptr int_2Fh_vector+2
mov AX,252Fh
int 21h
;
pop DS
;
mov ES,CS:2Ch ; ES -> окружение
mov AH, 49h ; Функция освобождения блока памяти
int 21h
;
mov AX, CS
mov ES, AX ; ES -> PSP выгрузим саму программу
mov AH, 49h ; Функция освобождения блока памяти
int 21h
;
mov AL,0Fh ; Признак успешной выгрузки
jmp short pop_ret
Not_remove:
mov AL,0F0h ; Признак - выгружать нельзя
pop_ret:
pop ES
pop DX
pop CX
pop BX
;
iret
int_2Fh endp
;============================================================================
begin:
mov CL,ES:80h ; Длина хвоста в PSP
cmp CL,0 ; Длина хвоста=0?
je check_install ; Да, программа запущена без параметров,
; попробуем установить
xor CH,CH ; CX=CL= длина хвоста
cld ; DF=0 - флаг направления вперед
mov DI, 81h ; ES:DI-> начало хвоста в PSP
mov AL,' ' ; Уберем пробелы из начала хвоста
repe scasb ; Сканируем хвост пока пробелы
; AL - (ES:DI) -> флаги процессора
; повторять пока элементы равны
dec DI ; DI-> на первый символ после пробелов
mov console_com, DI
mov SI, offset key3
mov CX, 7
repe cmpsb
jne check_key2
;---------------------------------------------------------------
lea DX, CS:FileName
mov BX,DX
mov AL,51
mov [BX], AL
mov AH, 0Ah
int 21h
xor bx, bx
mov BL, CS:FileName[1]
mov CS:FileName[bx+2], 0
lea DX, CS:FileName + 2
mov AX, 3D02h ; Open file for read/write
int 21h
jc file_error
mov bx, ax
mov AX, 3E00h
int 21h
lea DX, msg_success
call print
int 20h
check_key2:
mov DI, console_com
mov SI, offset key2
mov CX, 5
repe cmpsb
jne check_key
lea DX, msg_help
call print
;lea DX, CS:FileName + 2
;call print
int 20h
check_key:
mov DI, console_com
mov SI,offset key ; DS:SI-> поле key
mov CX, 4 ; ожидаемая длина команды
repe cmpsb ; Сравниваем введенный хвост с ожидаемым
; (DS:SI)-(ES:DI) -> флаги процессора
jne check_install ; Неизвестная команда - попробуем установить
inc flag_off
; Проверим, не установлена ли уже эта программа
check_install:
mov AX,0C700h ; AH=0C7h номер процесса C7h
; AL=00h -дать статус установки процесса
int 2Fh ; мультиплексное прерывание
cmp AL,0FFh
je already_ins ; возвращает AL=0FFh если установлена
;----------------------------------------------------------------------------
cmp flag_off,1
je xm_stranno
jmp vectors
;-----------------------------------------------------------------------------
file_error:
lea DX, msg_error
call print
int 20h
vectors:
get_vector 2Fh, int_2Fh_vector
set_vector 2Fh, int_2Fh
get_vector 09h, old_09h
set_vector 09h, new_09h
mov DX,offset begin ; оставить программу ...
int 27h ; ... резидентной и выйти
;============================================================================
already_ins:
cmp flag_off,1 ; Запрос на выгрузку установлен?
je uninstall ; Да, на выгрузку
lea DX,msg ; Вывод на экран сообщения: already installed!
call print
int 20h
; ------------------ Выгрузка -----------------------------------------------
uninstall:
mov AX,0C701h ; AH=0C7h номер процесса C7h, подфункция 01h-выгрузка
int 2Fh ; мультиплексное прерывание
cmp AL,0F0h
je not_sucsess
cmp AL,0Fh
jne not_sucsess
mov DX,offset msg2 ; Сообщение о выгрузке
call print
int 20h
not_sucsess:
mov DX,offset msg3 ; Сообщение, что выгрузка невозможна
call print
int 20h
xm_stranno:
mov DX,offset msg4 ; Сообщение, программы нет, а пользователь
call print ; дает команду выгрузки
int 20h
;----------------------------------------------------------------------------
key DB '/off'
key2 DB '/help'
key3 DB '/update'
flag_off DB 0
msg DB 'already '
msg1 DB 'installed',13,10,'$'
msg4 DB 'just '
msg3 DB 'not '
msg2 DB 'uninstalled',13,10,'$'
;msg_help DB '/off to uninstall',13,10
;msg_help1 DB '/update to update file',13,10
msg_help DB 'S+W to show file',13,10,'$'
msg_error DB 'File ERROR',13,10,'$'
msg_success DB 'File successfully added',13,10,'$'
;============================================================================
PRINT PROC NEAR
MOV AH,09H
INT 21H
RET
PRINT ENDP
;;============================================================================
;FileName DB ' in.txt',0
buf DB 1000 dup('$')
err_code DB 0
combo_key DB ?
console_com DW ?
code_seg ends
end start |