Turbo Assembler	 Version 3.1	    05/22/18 24:10:23	    Page 1
17.asm



      1	0000			     code segment 'code'
      2					 assume	 CS:code, DS:code
      3					 org 100h
      4
      5	0100			     _start:
      6	0100  E9 0580			 jmp _initTSR				     ; на начало программы
      7
      8	0103  61 62 63 64 65 66	67+	 ignoredChars		     DB	'abcdefghijklmnopqrstuvwxyz' ; игнорируемые символы
      9	      68 69 6A 6B 6C 6D	6E+
     10	      6F 70 71 72 73 74	75+
     11	      76 77 78 79 7A
     12	011D  1A			 ignoredLength		     DB	26	     ; длина строки ignoredChars
     13	011E  FF			 ignoreEnabled		     DB	true	     ; флаг функции игнорирования ввода
     14	011F  54 50 3A 42 52		 translateFrom		     DB	'TP:BR'	    ; заменяемые символы
     15	0124  C5 C7 C6 C8 CA		 translateTo		     DB	'ЕЗЖИК'	    ; символы, на которые будет	происходить замена
     16	0129  06			 translateLength	     DB	6	     ; длина строки translateFrom
     17	012A  00			 translateEnabled	     DB	0	     ; флаг функции перевода
     18
     19	012B  00			 signaturePrintingEnabled    DB	0	     ; флаг вывода подписи
     20	012C  0000			 counter		     DW	0
     21	      =0005			 printDelay		     EQU 5	     ; задержка	перед выводом "подписи"	в секундах
     22
     23	012E  0034			 signatureLineLength	     DW	 52	     ; длина одной строчки подписи
     24	0130  B3 D1 E8 EB E0 E5	E2+	 signatureLine1		     DB	 179, 'Силаев Андрей Владимирович			 ', +
     25	      20 C0 ED E4 F0 E5	E9+  179
     26	      20 C2 EB E0 E4 E8	EC+
     27	      E8 F0 EE E2 E8 F7	20+
     28	      20 20 20 20 20 20	20+
     29	      20 20 20 20 20 20	20+
     30	      20 20 20 20 20 20	20+
     31	      20 20 B3
     32	0164  B3 C8 D3 35 2D 34	33+	 signatureLine2		     DB	 179, 'ИУ5-43						 ', +
     33	      20 20 20 20 20 20	20+  179
     34	      20 20 20 20 20 20	20+
     35	      20 20 20 20 20 20	20+
     36	      20 20 20 20 20 20	20+
     37	      20 20 20 20 20 20	20+
     38	      20 20 20 20 20 20	20+
     39	      20 20 B3
     40	0198  B3 C2 E0 F0 E8 E0	ED+	 signatureLine3		     DB	 179, 'Вариант 17					 ', +
     41	      F2 20 31 37 20 20	20+  179
     42	      20 20 20 20 20 20	20+
     43	      20 20 20 20 20 20	20+
     44	      20 20 20 20 20 20	20+
     45	      20 20 20 20 20 20	20+
     46	      20 20 20 20 20 20	20+
     47	      20 20 B3
     48	01CC  2D 32*(2D) AC		 tableTop		     DB	 '-', 50 dup ('-'), '¬'
     49	0200  4C 32*(2D) 2D		 tableBottom		     DB	 'L', 50 dup ('-'), '-'
     50
     51	0234  3E 20 6B 72 2E 63	6F+	 helpMsg     DB	'> kr.com [/?] [/u]', 10, 13
     52	      6D 20 5B 2F 3F 5D	20+
     53	      5B 2F 75 5D 0A 0D
     54	0248  20 5B 2F 3F 5D 20	2D+		     DB	' [/?] - вывод данной справки',	10, 13
     55	      20 E2 FB E2 EE E4	20+
     56	      E4 E0 ED ED EE E9	20+
     57	      F1 EF F0 E0 E2 EA	E8+
Turbo Assembler	 Version 3.1	    05/22/18 24:10:23	    Page 2
17.asm



     58	      0A 0D
     59	0266  20 5B 2F 75 5D 20	2D+		     DB	' [/u] - выгрузка резидента из памяти',	10, 13
     60	      20 E2 FB E3 F0 F3	E7+
     61	      EA E0 20 F0 E5 E7	E8+
     62	      E4 E5 ED F2 E0 20	E8+
     63	      E7 20 EF E0 EC FF	F2+
     64	      E8 0A 0D
     65	028C  20 20 46 35 20 20	2D+		     DB	'  F5  - вывод ФИО и группы по таймеру в центре	экрана', 10, 13
     66	      20 E2 FB E2 EE E4	20+
     67	      D4 C8 CE 20 E8 20	E3+
     68	      F0 F3 EF EF FB 20	EF+
     69	      EE 20 F2 E0 E9 EC	E5+
     70	      F0 F3 20 E2 20 F6	E5+
     71	      ED F2 F0 E5 20 FD	EA+
     72	      F0 E0 ED E0 0A 0D
     73	02C3  20 20 46 36 20 20	2D+		     DB	'  F6  - включение/отключения курсивного вывода	русского символа В', 10, 13
     74	      20 E2 EA EB FE F7	E5+
     75	      ED E8 E5 2F EE F2	EA+
     76	      EB FE F7 E5 ED E8	FF+
     77	      20 EA F3 F0 F1 E8	E2+
     78	      ED EE E3 EE 20 E2	FB+
     79	      E2 EE E4 E0 20 F0	F3+
     80	      F1 F1 EA EE E3 EE	20+
     81	      F1 E8 EC E2 EE EB	E0+
     82	      20 C2 0A 0D
     83	0306  20 20 46 37 20 20	2D+		     DB	'  F7  - включение/отключение частичной	русификации клавиатуры:	TP:BR ->    +
     84	      20 E2 EA EB FE F7	E5+  ЕЗЖИК', 10, 13
     85	      ED E8 E5 2F EE F2	EA+
     86	      EB FE F7 E5 ED E8	E5+
     87	      20 F7 E0 F1 F2 E8	F7+
     88	      ED EE E9 20 F0 F3	F1+
     89	      E8 F4 E8 EA E0 F6	E8+
     90	      E8 20 EA EB E0 E2	E8+
     91	      E0 F2 F3 F0 FB 3A	20+
     92	      54 50 3A 42 52 20	2D+
     93	      3E 20 C5 C7 C6 C8	CA+
     94	      0A 0D
     95	0355  20 20 46 38 20 20	2D+		     DB	'  F8  - включение/отключение режима блокировки	ввода букв abcde', 10, 13, 0
     96	      20 E2 EA EB FE F7	E5+
     97	      ED E8 E5 2F EE F2	EA+
     98	      EB FE F7 E5 ED E8	E5+
     99	      20 F0 E5 E6 E8 EC	E0+
    100	      20 E1 EB EE EA E8	F0+
    101	      EE E2 EA E8 20 E2	E2+
    102	      EE E4 E0 20 E1 F3	EA+
    103	      E2 20 61 62 63 64	65+
    104	      0A 0D 00
    105
    106	      =0163			 helpMsgLength		     EQU $-helpMsg
    107	0397  00			 commandLineResult	     DB	0
    108
    109	0398  00			 cursiveEnabled		     DB	0	     ; флаг перевода символа в курсив
    110	0399  00			 cursiveSymbol		     DB	00000000b    ; символ, составленный из единиц (его курсивный+
    111				     вариант)
    112	039A  00						     DB	00000000b
    113	039B  00						     DB	00000000b
    114	039C  3C						     DB	00111100b
Turbo Assembler	 Version 3.1	    05/22/18 24:10:23	    Page 3
17.asm



    115	039D  42						     DB	01000010b
    116	039E  82						     DB	10000010b
    117	039F  82						     DB	10000010b
    118	03A0  82						     DB	10000010b
    119	03A1  82						     DB	10000010b
    120	03A2  82						     DB	10000010b
    121	03A3  82						     DB	10000010b
    122	03A4  82						     DB	10000010b
    123	03A5  78						     DB	01111000b
    124	03A6  00						     DB	00000000b
    125	03A7  00						     DB	00000000b
    126	03A8  00						     DB	00000000b
    127
    128	03A9  4F			 charToCursiveIndex	     DB	'O'	     ; символ для замены
    129	03AA  10*(FF)			 savedSymbol		     DB	16 dup(0FFh) ; переменная для хранения старого символа
    130
    131	03BA  ????			 old_int9hOffset	     DW	 ?	     ; адрес старого обработчика int 9h
    132	03BC  ????			 old_int9hSegment	     DW	 ?	     ; сегмент старого обработчика int 9h
    133	03BE  ????			 old_int1ChOffset	     DW	 ?	     ; адрес старого обработчика int 1Ch
    134	03C0  ????			 old_int1ChSegment	     DW	 ?	     ; сегмент старого обработчика int 1Ch
    135	03C2  ????			 old_int2FhOffset	     DW	 ?	     ; адрес старого обработчика int 2Fh
    136	03C4  ????			 old_int2FhSegment	     DW	 ?	     ; сегмент старого обработчика int 2Fh
    137
    138	03C6  D0 E5 E7 E8 E4 E5	ED+	 installedMsg		     DB	 'Резидент загружен.', 0
    139	      F2 20 E7 E0 E3 F0	F3+
    140	      E6 E5 ED 2E 00
    141	03D9  D0 E5 E7 E8 E4 E5	ED+	 alreadyInstalledMsg	     DB	 'Резидент уже был загружен.', 0
    142	      F2 20 F3 E6 E5 20	E1+
    143	      FB EB 20 E7 E0 E3	F0+
    144	      F3 E6 E5 ED 2E 00
    145	03F4  D0 E5 E7 E8 E4 E5	ED+	 notInstalledMsg	     DB	 'Резидент не был загружен.$'
    146	      F2 20 ED E5 20 E1	FB+
    147	      EB 20 E7 E0 E3 F0	F3+
    148	      E6 E5 ED 2E 24
    149
    150	040E  D0 E5 E7 E8 E4 E5	ED+	 removedMsg		     DB	 'Резидент выгружен из памяти.'
    151	      F2 20 E2 FB E3 F0	F3+
    152	      E6 E5 ED 20 E8 E7	20+
    153	      EF E0 EC FF F2 E8	2E
    154	      =001C			 removedMsg_length	     EQU $-removedMsg
    155
    156	042A  CD E5 20 F3 E4 E0	EB+	 noRemoveMsg		     DB	 'Не удалось выгрузить резидент'
    157	      EE F1 FC 20 E2 FB	E3+
    158	      F0 F3 E7 E8 F2 FC	20+
    159	      F0 E5 E7 E8 E4 E5	ED+
    160	      F2
    161	      =001D			 noRemoveMsg_length	     EQU $-noRemoveMsg
    162
    163	      =00FF			 true			     EQU 0FFh	     ; нужно для удобства использования	not с флагами
    164										     ; 0FFh = 11111111b	= инверсия 00000000b
    165
    166					 ; новый обработчик прерывания int 9h
    167					 ; (работа с клавиатурой)
    168	0447				 new_int9h proc	far
    169	0447  56 50 53 51 52 06	1E	     push SI AX	BX CX DX ES DS		     ; сохраняем значения всех,	изменяемых регистров+
    170				     в стеке
    171	044E  0E			     push CS				     ; синхронизируем CS и DS
Turbo Assembler	 Version 3.1	    05/22/18 24:10:23	    Page 4
17.asm



    172	044F  1F			     pop DS
    173
    174	0450  9C			     pushf
    175	0451  2E: FF 1E	03BAr		     call dword	ptr CS:[old_int9hOffset]     ; вызываем	стандартный обработчик прерывания
    176	0456  B8 0040			     mov AX, 40h			     ; 40h - сегмент, где хранятся флаги состояния  +
    177				     клавиатуры
    178	0459  8E C0			     mov ES, AX
    179	045B  26: 8B 1E	001C		     mov BX, ES:[1Ch]			     ; адрес хвоста
    180	0460  83 EB 02			     sub BX, 2h				     ; сместимся назад к последнему введённому	    +
    181				     символу
    182	0463  83 FB 1E			     cmp BX, 1Eh			     ; не вышли	ли мы за пределы буфера?
    183	0466  73 03			     jae _go
    184	0468  BB 003C			     mov BX, 3Ch			     ; хвост вышел за пределы буфера: значит,	    +
    185				     последний
    186										     ; введённый символ	находится в конце буфера
    187	046B				 _go:
    188	046B  26: 8B 17			     mov DX, ES:[BX]			     ; в DX 0 введённый	символ
    189
    190	046E				 _test_Fx:				     ; проверка	F5-F8
    191	046E				 _F5:
    192	046E  80 FE 3B			     cmp DH, 3Bh			     ; F5
    193	0471  75 0C			     jne _F6
    194	0473  F6 16 012Br		     not signaturePrintingEnabled
    195	0477  26: 89 1E	001C		     mov ES:[1Ch], BX			     ; блокировка ввода	символа
    196	047C  EB 7C 90			     jmp _quit
    197	047F				 _F6:
    198	047F  80 FE 3C			     cmp DH, 3Ch			     ; F6
    199	0482  75 0F			     jne _F7
    200	0484  26: 89 1E	001C		     mov ES:[1Ch], BX			     ; блокировка ввода	символа
    201	0489  F6 16 0398r		     not cursiveEnabled
    202	048D  E8 0072			     call toggleCursive			     ; перевод символа в курсив	и обратно
    203										     ; в зависимости от	флага cursiveEnabled
    204	0490  EB 68 90			     jmp _quit
    205	0493				 _F7:
    206	0493  80 FE 3D			     cmp DH, 3Dh			     ; F7
    207	0496  75 0C			     jne _F8
    208	0498  F6 16 012Ar		     not translateEnabled
    209	049C  26: 89 1E	001C		     mov ES:[1Ch], BX			     ; блокировка ввода	символа
    210	04A1  EB 57 90			     jmp _quit
    211	04A4				 _F8:
    212	04A4  80 FE 3E			     cmp DH, 3Eh			     ; F8
    213	04A7  75 0C			     jne _translateOrIgnore
    214	04A9  F6 16 011Er		     not ignoreEnabled
    215	04AD  26: 89 1E	001C		     mov ES:[1Ch], BX			     ; блокировка ввода	символа
    216	04B2  EB 46 90			     jmp _quit
    217
    218	04B5				 _translateOrIgnore:			     ; просто выводим набранный	символ на экран
    219	04B5  80 3E 011Er FF		     cmp ignoreEnabled,	true		     ; включен ли режим	блокировки ввода?
    220	04BA  75 1B			     jne _checkTranslate
    221
    222	04BC  BE 0000			     mov SI, 0				     ; да, включен
    223	04BF  8A 0E 011Dr		     mov CL, ignoredLength		     ; количество игнорируемых символов
    224
    225	04C3				 _checkIgnored:
    226	04C3  3A 94 0103r		     cmp DL, ignoredChars[SI]		     ; проверяем, присутствует ли текущий символ в  +
    227				     списке игнорируемых
    228	04C7  74 06			     je	_block
Turbo Assembler	 Version 3.1	    05/22/18 24:10:23	    Page 5
17.asm



    229	04C9  46			     inc SI
    230	04CA  E2 F7			     loop _checkIgnored			     ; зацикливаем ignoredLength раз
    231	04CC  EB 09 90			     jmp _checkTranslate
    232
    233					 ; блокируем
    234	04CF				 _block:
    235	04CF  26: 89 1E	001C		     mov ES:[1Ch], BX			     ; блокировка ввода	символа
    236	04D4  EB 24 90			     jmp _quit
    237
    238	04D7				 _checkTranslate:
    239	04D7  80 3E 012Ar FF		     cmp translateEnabled, true		     ; включен ли режим	перевода?
    240	04DC  75 1C			     jne _quit
    241
    242	04DE  BE 0000			     mov SI, 0				     ; да, включен
    243	04E1  8A 0E 0129r		     mov CL, translateLength		     ; кол-во символов для перевода
    244
    245	04E5				 _checkTranslateLoop:
    246	04E5  3A 94 011Fr		     cmp DL, translateFrom[SI]		     ; присутствует ли текущий символ в	списке для  +
    247				     перевода?
    248	04E9  74 06			     je	_translate
    249	04EB  46			     inc SI
    250	04EC  E2 F7			     loop _checkTranslateLoop		     ; продолжаем, пока	не закончим проверять каждый+
    251				     символ
    252	04EE  EB 0A 90			     jmp _quit
    253
    254	04F1				 _translate:
    255	04F1  33 C0			     xor AX, AX				     ; переводим
    256	04F3  8A 84 0124r		     mov AL, translateTo[SI]
    257	04F7  26: 89 07			     mov ES:[BX], AX			     ; замена символа
    258
    259	04FA				 _quit:
    260	04FA  1F 07 5A 59 5B 58	5E	     pop DS ES DX CX BX	AX SI		     ; восстанавливаем все регистры
    261	0501  CF			     iret
    262	0502				 new_int9h endp
    263
    264					 ; в зависимости от флага cursiveEnabled меняет	начертание символа на курсив и обратно
    265					 ; сама	смена происходит в процедуре changeFont	- здесь	же подготавливаются данные
    266	0502				 toggleCursive proc
    267	0502  06 50			     push ES AX				     ; сохраняем регистры
    268	0504  0E			     push CS
    269	0505  07			     pop ES
    270
    271	0506  80 3E 0398r FF		     cmp cursiveEnabled, true		     ; если флаг равен true,
    272	050B  75 30			     jne _restoreSymbol			     ; выполняем замену	символа	на курсивный вариант,
    273										     ; предварительно сохраняя старый символ в	    +
    274				     savedSymbol
    275
    276	050D  E8 004E			     call saveFont
    277	0510  8A 0E 03A9r		     mov CL, charToCursiveIndex
    278	0514				 _shiftTable:
    279	0514  83 C5 10			     add BP, 16				     ; получаем	в BP таблицу всех символов. адрес   +
    280				     указывает на символ 0
    281										     ; поэтому нужно совершить сдвиг 16*X - где	X - +
    282				     код символа
    283	0517  E2 FB			     loop _shiftTable
    284
    285	0519  1E			     push DS				     ; пpи savefont смещается pегистp ES
Turbo Assembler	 Version 3.1	    05/22/18 24:10:23	    Page 6
17.asm



    286	051A  58			     pop AX				     ; поэтомy пpиходится делать такие махинации,   +
    287				     чтобы
    288	051B  06			     push ES				     ; записать	полyченный элемент в savedSymbol
    289	051C  1F			     pop DS
    290	051D  50			     push AX				     ; DS -> AX, ES -> DS, AX -> ES => ES и DS	    +
    291				     поменялись	местами
    292	051E  07			     pop ES				     ; + сохранение старого значения DS	в AX
    293	051F  50			     push AX
    294
    295	0520  8B F5			     mov SI, BP
    296	0522  BF 03AAr			     lea DI, savedSymbol		     ; сохpаняем в пеpеменнyю savedSymbol таблицу   +
    297				     нужного символа
    298
    299	0525  B9 0010			     mov CX, 16				     ; movsb из	DS:SI в	ES:DI
    300
    301	0528  F3> A4			     rep movsb				     ; исходные	позиции	сегментов возвpащены
    302	052A  1F			     pop DS				     ; восстановление DS
    303
    304	052B  B9 0001			     mov CX, 1				     ; заменим написание символа на кypсив
    305	052E  B6 00			     mov DH, 0
    306	0530  8A 16 03A9r		     mov DL, charToCursiveIndex
    307	0534  BD 0399r			     lea BP, cursiveSymbol
    308	0537  E8 0015			     call changeFont
    309	053A  EB 10 90			     jmp _exitToggleCursive
    310
    311	053D				 _restoreSymbol:
    312	053D  B9 0001			     mov CX, 1				     ; если флаг равен 0, заменяем курсивный символ +
    313				     на	старый вариант
    314	0540  B6 00			     mov DH, 0
    315	0542  8A 16 03A9r		     mov DL, charToCursiveIndex
    316	0546  BD 03AAr			     lea BP, savedSymbol
    317	0549  E8 0003			     call changeFont
    318
    319	054C				 _exitToggleCursive:
    320	054C  58			     pop AX
    321	054D  07			     pop ES
    322	054E  C3			     ret
    323	054F				 toggleCursive endp
    324
    325					 ; функция смены начертания символа (курсив/нормальное)
    326					 ;
    327					 ; входные данные:
    328					 ; 1) DL = номер символа для замены
    329					 ; 2) CX = количество символов заменяемых изображений символов
    330					 ;    (начиная с символа указанного в DX)
    331					 ; 3) ES:BP = адрес таблицы
    332					 ;
    333					 ; описание работы процедуры:
    334					 ; 1) происходит вызов int 10h (видеосервис)
    335					 ;    с	функцией AH = 11h (функции знакогенератора)
    336					 ;    параметр AL = 0 сообщает,	что будет заменено изображение
    337					 ;    символа для текущего шрифта.
    338					 ;    в	случаях, когда AL = 1 или 2, будет заменено изображение
    339					 ;    только для определенного шрифта (8x14 и 8x8 соответственно)
    340					 ; 2) параметр BH = 0Eh	сообщает, что на определение каждого изображения символа
    341					 ;    расходуется по 14	байт (режим 8x14 бит как раз 14	байт)
    342					 ; 3) параметр BL = 0 -	блок шрифта для	загрузки (от 0 до 4)
Turbo Assembler	 Version 3.1	    05/22/18 24:10:23	    Page 7
17.asm



    343					 ;
    344					 ; результат:
    345					 ; изображение указанного(ых) символа(ов) будет	заменено
    346					 ; на предложенное пользователем.
    347					 ; изменению подвергнутся все символы, находящиеся на экране:
    348					 ; таким образом, если изображение заменено, старый вариант нигде уже не проявится
    349	054F				 changeFont proc
    350	054F  50 53 52			     push AX BX	DX
    351	0552  B8 1100			     mov AX, 1100h
    352	0555  BB 1000			     mov BX, 1000h
    353	0558  CD 10			     int 10h
    354	055A  5A 5B 58			     pop DX BX AX
    355	055D  C3			     ret
    356	055E				 changeFont endp
    357
    358					 ; функция сохранения нормального начертания символа
    359					 ;
    360					 ; входные данные:
    361					 ; BH -	тип возвращаемой символьной таблицы
    362					 ;   = 0     - таблица из int 1fh
    363					 ;   = 1     - таблица из int 44h
    364					 ;   = 2..5  - таблица из 8x14,	8x8, 8x8 (top),	9x14
    365					 ;   = 6     - 8x16
    366					 ;
    367					 ; описание работы процедуры:
    368					 ;   происходит	вызов int 10h (видеосервис)
    369					 ;   с функцией	AH = 11h (функции знакогенератора)
    370					 ;   параметр AL = 30 -	подфункция получения информации	о EGA
    371					 ;
    372					 ; результат:
    373					 ;   1)	в ES:BP	находится таблица символов (полная)
    374					 ;   2)	в CX находится байт на символ
    375					 ;   3)	в DL количество	экранных строк
    376					 ; важно! происходит сдвиг регистра ES (ES = C000h)
    377	055E				 saveFont proc
    378	055E  50 53 52			     push AX BX	DX
    379	0561  B8 1130			     mov AX, 1130h
    380	0564  BB 0600			     mov BX, 0600h
    381	0567  CD 10			     int 10h
    382	0569  5B 58 5A			     pop BX AX DX
    383	056C  C3			     ret
    384	056D				 saveFont endp
    385
    386					 ; обработчик прерывания int 2Fh
    387					 ; служит для:
    388					 ;  1) проверки	факта присутствия TSR в	памяти (при AH=0FFh, AL=0)
    389					 ;     будет возвращён AH='i' в	случае,	если TSR уже загружен
    390					 ;  2) выгрузки	TSR из памяти (при AH=0FFh, AL=1)
    391	056D				 new_int2Fh proc
    392	056D  80 FC FF			     cmp AH, 0FFh			     ; наша процедура?
    393	0570  75 0B			     jne _2Fh_default			     ; нет - на	стандартный обработчик
    394	0572  3C 00			     cmp AL, 0				     ; подпроцедура проверки, загружен ли резидент в+
    395				     память?
    396	0574  74 0C			     je	 _alreadyInstalled2Fh
    397	0576  3C 01			     cmp AL, 1				     ; подпроцедура выгрузки из	памяти?
    398	0578  74 0B			     je	 _uninstall
    399	057A  EB 01 90			     jmp _2Fh_default
Turbo Assembler	 Version 3.1	    05/22/18 24:10:23	    Page 8
17.asm



    400
    401	057D				 _2Fh_default:
    402	057D  2E: FF 2E	03C2r		     jmp dword ptr CS:[old_int2FhOffset]     ; вызов стандартного обработчика
    403
    404	0582				 _alreadyInstalled2Fh:
    405	0582  B4 69			     mov AH, 'i'			     ; пусть AH	= 'i', если резидент уже загружен в +
    406				     память
    407	0584  CF			     iret				     ; конечно,	вместо 'i' может быть любое значение
    408
    409	0585				 _uninstall:				     ; подпроцедура выгрузки из	памяти
    410	0585  1E 06 52 53		     push DS ES	DX BX
    411	0589  33 DB			     xor BX, BX
    412
    413	058B  0E			     push CS				     ; CS = ES,	для доступа к переменным
    414	058C  07			     pop ES
    415
    416	058D  B8 2509			     mov AX, 2509h
    417	0590  26: 8B 16	03BAr		     mov DX, ES:old_int9hOffset		     ; возвращаем вектор прерывания 09h	на место
    418	0595  26: 8E 1E	03BCr		     mov DS, ES:old_int9hSegment
    419	059A  CD 21			     int 21h
    420
    421	059C  B8 251C			     mov AX, 251Ch
    422	059F  26: 8B 16	03BEr		     mov DX, ES:old_int1ChOffset	     ; возвращаем вектор прерывания 1Ch	на место
    423	05A4  26: 8E 1E	03C0r		     mov DS, ES:old_int1ChSegment
    424	05A9  CD 21			     int 21h
    425
    426	05AB  B8 252F			     mov AX, 252Fh
    427	05AE  26: 8B 16	03C2r		     mov DX, ES:old_int2FhOffset	     ; возвращаем вектор прерывания 2Fh	на место
    428	05B3  26: 8E 1E	03C4r		     mov DS, ES:old_int2FhSegment
    429	05B8  CD 21			     int 21h
    430
    431	05BA  2E: 8E 06	002C		     mov ES, CS:2Ch			     ; загрузим	в ES адрес окружения
    432	05BF  B4 49			     mov AH, 49h			     ; выгрузим	из памяти окружение
    433	05C1  CD 21			     int 21h
    434	05C3  72 0B			     jc	_notRemove
    435
    436	05C5  0E			     push CS
    437	05C6  07			     pop ES				     ; в ES - адрес резидентной	программы
    438	05C7  B4 49			     mov AH, 49h			     ; выгрузим	из памяти резидент
    439	05C9  CD 21			     int 21h
    440
    441	05CB  72 03			     jc	_notRemove
    442	05CD  EB 15 90			     jmp _unloaded
    443
    444	05D0				 _notRemove:				     ; не удалось выполнить выгрузку =>	вывод ошибки
    445	05D0  B4 03			     mov AH, 03h			     ; получаем	позицию	курсора
    446	05D2  CD 10			     int 10h
    447	05D4  BD 042Ar			     lea BP, noRemoveMsg
    448	05D7  B9 001D			     mov CX, noRemoveMsg_length
    449	05DA  B3 07			     mov BL, 0111b
    450	05DC  B8 1301			     mov AX, 1301h
    451	05DF  CD 10			     int 10h
    452	05E1  EB 12 90			     jmp _2Fh_exit
    453
    454	05E4				 _unloaded:				     ; выгрузка	прошла успешно => вывод	сообщения
    455	05E4  B4 03			     mov AH, 03h			     ; получаем	позицию	курсора
    456	05E6  CD 10			     int 10h
Turbo Assembler	 Version 3.1	    05/22/18 24:10:23	    Page 9
17.asm



    457	05E8  BD 040Er			     lea BP, removedMsg
    458	05EB  B9 001C			     mov CX, removedMsg_length
    459	05EE  B3 07			     mov BL, 0111b
    460	05F0  B8 1301			     mov AX, 1301h
    461	05F3  CD 10			     int 10h
    462
    463	05F5				 _2Fh_exit:
    464	05F5  5B 5A 07 1F		     pop BX DX ES DS
    465	05F9  CF			     iret
    466	05FA				 new_int2Fh endp
    467
    468					 ; обработчик прерывания int 1Ch
    469					 ; вызывается каждые 55	мс
    470	05FA				 new_int1Ch proc far
    471	05FA  50			     push AX
    472	05FB  0E			     push CS
    473	05FC  1F			     pop DS
    474
    475	05FD  9C			     pushf
    476	05FE  2E: FF 1E	03BEr		     call dword	ptr CS:[old_int1ChOffset]    ; вызываем	стандартный обработчик прерывания
    477
    478	0603  80 3E 012Br FF		     cmp signaturePrintingEnabled, true	     ; если нажата управляющая клавиша (в данном    +
    479				     случае F5)
    480	0608  75 1B			     jne _notToPrint
    481
    482	060A  83 3E 012Cr 5B		     cmp counter, printDelay*1000/55 + 1     ; если кол-во "тактов" равно printDelay секундам
    483	060F  74 03			     je	_letsPrint
    484
    485	0611  EB 0E 90			     jmp _dontPrint
    486
    487	0614				 _letsPrint:
    488	0614  F6 16 012Br		     not signaturePrintingEnabled
    489	0618  C7 06 012Cr 0000		     mov counter, 0
    490	061E  E8 0016			     call printSignature		     ; выводим подпись на экран
    491
    492	0621				 _dontPrint:
    493	0621  FF 06 012Cr			 inc counter			     ; увеличим	значение счетчика на 1
    494
    495	0625				 _notToPrint:
    496	0625  58			     pop AX
    497	0626  CF			     iret
    498	0627				 new_int1Ch endp
    499
    500					 ; выводит одну	строку подписи
    501	0627				 printSignatureLine proc
    502	0627  52			     push DX
    503	0628  8B 0E 012Er		     mov CX, signatureLineLength
    504	062C  B3 07			     mov BL, 0111b			     ; цвет выводимого текста
    505	062E  B8 1301			     mov AX, 1301h			     ; AH = 13h	- номер	ф-ии, AL = 01h - перемещение+
    506				     курсора
    507	0631  CD 10			     int 10h
    508	0633  5A			     pop DX
    509	0634  FE C6			     inc DH
    510	0636  C3			     ret
    511	0637				 printSignatureLine endp
    512
    513					 ; процедура вывода подписи
Turbo Assembler	 Version 3.1	    05/22/18 24:10:23	    Page 10
17.asm



    514	0637				 printSignature	proc
    515	0637  50 52 51 53 06 54	55+	     push AX DX	CX BX ES SP BP SI DI
    516	      56 57
    517
    518	0640  33 C0			     xor AX, AX				     ; обнуляем	значения регистров
    519	0642  33 DB			     xor BX, BX
    520	0644  33 D2			     xor DX, DX
    521
    522	0646  B4 03			     mov AH, 03h			     ; чтение текущей позиции курсора
    523	0648  CD 10			     int 10h
    524	064A  52			     push DX				     ; помещаем	информацию о положении курсора в стек
    525
    526	064B  BA 130F			     mov DX, 130Fh			     ; NB! вверху: 000Fh, посередине: 090Fh, внизу: +
    527				     130Fh
    528
    529	064E				 _actualPrint:
    530	064E  B4 0F			     mov AH, 0Fh			     ; чтение текущего видеорежима. в BH - текущая  +
    531				     страница
    532	0650  CD 10			     int 10h
    533
    534	0652  0E			     push CS
    535	0653  07			     pop ES				     ; указываем ES на CS
    536
    537	0654  BD 01CCr			     lea BP, tableTop
    538	0657  E8 FFCD			     call printSignatureLine		     ; выводим верх таблицы
    539	065A  BD 0130r			     lea BP, signatureLine1
    540	065D  E8 FFC7			     call printSignatureLine		     ; выводим первую строку
    541	0660  BD 0164r			     lea BP, signatureLine2
    542	0663  E8 FFC1			     call printSignatureLine		     ; выводим вторую строку
    543	0666  BD 0198r			     lea BP, signatureLine3
    544	0669  E8 FFBB			     call printSignatureLine		     ; выводим третью строку
    545	066C  BD 0200r			     lea BP, tableBottom
    546	066F  E8 FFB5			     call printSignatureLine		     ; выводим низ таблицы
    547
    548	0672  33 DB			     xor BX, BX
    549	0674  5A			     pop DX				     ; восстанавливаем из стека	прежнее	положение   +
    550				     курсора
    551	0675  B4 02			     mov AH, 02h			     ; меняем положение	курсора	на первоначальное
    552	0677  CD 10			     int 10h
    553
    554	0679  5F 5E 5D 5C 07 5B	59+	     pop DI SI BP SP ES	BX CX DX AX
    555	      5A 58
    556	0682  C3			     ret
    557	0683				 printSignature	endp
    558
    559					 ; Основная часть программы
    560					 ; 1) установка	видеорежима
    561					 ; 2) проверка,	запущен	ли резидент
    562					 ; 3) установка	вектора	прерываний
    563	0683				 _initTSR:
    564	0683  B4 03			     mov AH, 03h
    565	0685  CD 10			     int 10h
    566	0687  52			     push DX
    567	0688  B4 00			     mov AH, 00h			     ; установка видеорежима
    568	068A  B0 83			     mov AL, 83h
    569	068C  CD 10			     int 10h
    570	068E  5A			     pop DX
Turbo Assembler	 Version 3.1	    05/22/18 24:10:23	    Page 11
17.asm



    571	068F  B4 02			     mov AH, 02h
    572	0691  CD 10			     int 10h
    573
    574	0693  E8 009F			     call commandParamsParser		     ; читаем аргументы	командной строки
    575	0696  80 3E 0397r 02		     cmp commandLineResult, 2		     ; если результат =	2, значит была выведена	    +
    576				     справка
    577	069B  75 03			     jne _shouldContinue		     ; соответственно, никаких других действий	    +
    578				     делать не нужно
    579	069D  E9 0093			     jmp _exit
    580	06A0				 _shouldContinue:
    581	06A0  80 3E 0397r 01		     cmp commandLineResult, 1		     ; проверяем результат работы процедуры
    582	06A5  75 14			     jne _go_on
    583	06A7  B4 FF			     mov AH, 0FFh
    584	06A9  B0 00			     mov AL, 0
    585	06AB  CD 2F			     int 2Fh
    586	06AD  80 FC 69			     cmp AH, 'i'			     ; проверка	того, загружена	ли уже программа
    587	06B0  74 64			     je	_remove
    588
    589	06B2  B4 09			     mov AH, 09h
    590	06B4  BA 03F4r			     lea DX, notInstalledMsg		     ; не была загружена
    591	06B7  CD 21			     int 21h
    592	06B9  CD 20			     int 20h
    593	06BB				 _go_on:
    594	06BB  B4 FF			     mov AH, 0FFh			     ; проверка	того, что резидент уже запущен
    595	06BD  B0 00			     mov AL, 0
    596	06BF  CD 2F			     int 2Fh
    597	06C1  80 FC 69			     cmp AH, 'i'			     ; если запущена, то AH = 'i' (см. процедуру    +
    598				     new_int2Fh)
    599	06C4  74 64			     je	_alreadyInstalled
    600
    601	06C6  B8 3509			     mov AX, 3509h			     ; получить	в ES:BX	прерывания 09h
    602	06C9  CD 21			     int 21h
    603	06CB  2E: 89 1E	03BAr		     mov word ptr CS:old_int9hOffset, BX     ; обработчик прерывания 09h
    604	06D0  2E: 8C 06	03BCr		     mov word ptr CS:old_int9hSegment, ES
    605	06D5  B8 2509			     mov AX, 2509h			     ; установим вектор	на прерывание 09h
    606	06D8  BA 0447r			     mov DX, offset new_int9h
    607	06DB  CD 21			     int 21h
    608
    609	06DD  B8 351C			     mov AX, 351Ch			     ; получить	в ES:BX	прерывания 1Ch
    610	06E0  CD 21			     int 21h
    611	06E2  2E: 89 1E	03BEr		     mov word ptr CS:old_int1ChOffset, BX    ; обработчик прерывания 1Ch
    612	06E7  2E: 8C 06	03C0r		     mov word ptr CS:old_int1ChSegment,	ES
    613	06EC  B8 251C			     mov AX, 251Ch			     ; установим вектор	на прерывание 1Ch
    614	06EF  BA 05FAr			     mov DX, offset new_int1Ch
    615	06F2  CD 21			     int 21h
    616
    617	06F4  B8 352F			     mov AX, 352Fh			     ; получить	в ES:BX	прерывания 2Fh
    618	06F7  CD 21			     int 21h
    619	06F9  2E: 89 1E	03C2r		     mov word ptr CS:old_int2FhOffset, BX    ; обработчик прерывания 2Fh
    620	06FE  2E: 8C 06	03C4r		     mov word ptr CS:old_int2FhSegment,	ES
    621	0703  B8 252F			     mov AX, 252Fh			     ; установим вектор	на прерывание 2Fh
    622	0706  BA 056Dr			     mov DX, offset new_int2Fh
    623	0709  CD 21			     int 21h
    624
    625	070B  BB 03C6r			     lea BX, installedMsg		     ; выводим сообщение, что всё ОК
    626	070E  E8 0061			     call printStr
    627
Turbo Assembler	 Version 3.1	    05/22/18 24:10:23	    Page 12
17.asm



    628	0711  BA 0683r			     mov DX, offset _initTSR		     ; остаемся	в памяти и выходим из основной части
    629	0714  CD 27			     int 27h
    630
    631	0716				 _remove:				     ; выгрузка	из памяти
    632	0716  06			     push ES
    633	0717  A1 002C			     mov AX, DS:[2Ch]			     ; PSP
    634	071A  8E C0			     mov ES, AX
    635	071C  B4 49			     mov AH, 49h			     ; хватит памяти чтоб остаться резидентом?
    636	071E  CD 21			     int 21h
    637	0720  07			     pop ES
    638
    639	0721  B4 FF			     mov AH, 0FFh
    640	0723  B0 01			     mov AL, 1
    641	0725  CD 2F			     int 2Fh
    642	0727  EB 0A 90			     jmp _exit
    643	072A				 _alreadyInstalled:			     ; резидент	уже запущен
    644	072A  BB 03D9r			     lea BX, alreadyInstalledMsg
    645	072D  E8 0042			     call printStr
    646	0730  EB 01 90			     jmp _exit
    647	0733				 _exit:					     ; выход
    648	0733  CD 20			     int 20h
    649
    650					 ; парсер аргментов командной строки. выводит справку.
    651					 ; устанавливает флаг commandLineResult:
    652					 ; 0 = всё ОК; 1 = нужна выгрузка; 2 = была выведена справка, не нужно загружать резидент
    653	0735				 commandParamsParser proc
    654	0735  0E			     push CS
    655	0736  07			     pop ES
    656
    657	0737  BE 0080			     mov SI, 80h			     ; SI = смещение командной строки
    658	073A  AC			     lodsb				     ; получим кол-во символов
    659	073B  0A C0			     or	AL, AL				     ; если 0 символов введено,
    660	073D  74 2D			     jz	_paramParsingEnd		     ; то все в	порядке
    661
    662	073F				 _nextChar:
    663	073F  46			     inc SI				     ; теперь SI указывает на первый символ строки
    664
    665	0740  80 3C 00			     cmp [SI], BYTE ptr	0
    666	0743  74 27			     je	_paramParsingEnd
    667
    668	0745  AD			     lodsw				     ; получаем	два символа
    669	0746  3D 3F2F			     cmp AX, '?/'
    670	0749  74 16			     je	_displayHelp
    671	074B  3D 752F			     cmp AX, 'u/'
    672	074E  74 07			     je	_finishTSR
    673	0750  3D 552F			     cmp AX, 'U/'
    674	0753  74 02			     je	_finishTSR
    675	0755  EB E8			     jmp _nextChar
    676
    677	0757				 _finishTSR:
    678	0757  C6 06 0397r 01		     mov commandLineResult, 1		     ; флаг того, что необходимо выгрузить резидент
    679	075C  EB E1			     jmp _nextChar
    680
    681	075E  EB 0C 90			     jmp _paramParsingEnd
    682	0761				 _displayHelp:
    683	0761  BB 0234r			     lea BX, helpMsg			     ; выводим справку
    684	0764  E8 000B			     call printStr
Turbo Assembler	 Version 3.1	    05/22/18 24:10:23	    Page 13
17.asm



    685	0767  C6 06 0397r 02		     mov commandLineResult, 2		     ; флаг того, что резидент загружать не надо
    686
    687	076C				 _paramParsingEnd:
    688	076C  C3			     ret
    689	076D				commandParamsParser endp
    690
    691					 ; отображает символ из	AL
    692	076D				 printChar proc
    693	076D  B4 0E			     mov AH, 0EH
    694	076F  CD 10			     int 010H
    695	0771  C3			     ret
    696	0772				 printChar endp
    697
    698					 ; отображает нуль-терминированную строку из [BX]
    699	0772				 printStr proc
    700	0772  52 50			     push DX AX
    701	0774  8B 07			     mov AX, [BX]
    702	0776				 _printStrLoop:
    703	0776  3C 00			     cmp AL, 0
    704	0778  74 08			     je	_printStrEnd
    705	077A  E8 FFF0			     call printChar
    706	077D  43			     inc BX
    707	077E  8B 07			     mov AX, [BX]
    708	0780  EB F4			     jmp _printStrLoop
    709	0782				 _printStrEnd:
    710	0782  58 5A			     pop AX DX
    711	0784  C3			     ret
    712	0785				 printStr endp
    713
    714	0785			     code ends
    715				     end _start
Turbo Assembler	 Version 3.1	    05/22/18 24:10:23	    Page 14
Symbol Table




Symbol Name			  Type	 Value

??DATE				  Text	 "05/22/18"
??FILENAME			  Text	 "17	  "
??TIME				  Text	 "24:10:23"
??VERSION			  Number 030A
@CPU				  Text	 0101H
@CURSEG				  Text	 CODE
@FILENAME			  Text	 17
@WORDSIZE			  Text	 2
ALREADYINSTALLEDMSG		  Byte	 CODE:03D9
CHANGEFONT			  Near	 CODE:054F
CHARTOCURSIVEINDEX		  Byte	 CODE:03A9
COMMANDLINERESULT		  Byte	 CODE:0397
COMMANDPARAMSPARSER		  Near	 CODE:0735
COUNTER				  Word	 CODE:012C
CURSIVEENABLED			  Byte	 CODE:0398
CURSIVESYMBOL			  Byte	 CODE:0399
HELPMSG				  Byte	 CODE:0234
HELPMSGLENGTH			  Number 0163
IGNOREDCHARS			  Byte	 CODE:0103
IGNOREDLENGTH			  Byte	 CODE:011D
IGNOREENABLED			  Byte	 CODE:011E
INSTALLEDMSG			  Byte	 CODE:03C6
NEW_INT1CH			  Far	 CODE:05FA
NEW_INT2FH			  Near	 CODE:056D
NEW_INT9H			  Far	 CODE:0447
NOREMOVEMSG			  Byte	 CODE:042A
NOREMOVEMSG_LENGTH		  Number 001D
NOTINSTALLEDMSG			  Byte	 CODE:03F4
OLD_INT1CHOFFSET		  Word	 CODE:03BE
OLD_INT1CHSEGMENT		  Word	 CODE:03C0
OLD_INT2FHOFFSET		  Word	 CODE:03C2
OLD_INT2FHSEGMENT		  Word	 CODE:03C4
OLD_INT9HOFFSET			  Word	 CODE:03BA
OLD_INT9HSEGMENT		  Word	 CODE:03BC
PRINTCHAR			  Near	 CODE:076D
PRINTDELAY			  Number 0005
PRINTSIGNATURE			  Near	 CODE:0637
PRINTSIGNATURELINE		  Near	 CODE:0627
PRINTSTR			  Near	 CODE:0772
REMOVEDMSG			  Byte	 CODE:040E
REMOVEDMSG_LENGTH		  Number 001C
SAVEDSYMBOL			  Byte	 CODE:03AA
SAVEFONT			  Near	 CODE:055E
SIGNATURELINE1			  Byte	 CODE:0130
SIGNATURELINE2			  Byte	 CODE:0164
SIGNATURELINE3			  Byte	 CODE:0198
SIGNATURELINELENGTH		  Word	 CODE:012E
SIGNATUREPRINTINGENABLED	  Byte	 CODE:012B
TABLEBOTTOM			  Byte	 CODE:0200
TABLETOP			  Byte	 CODE:01CC
TOGGLECURSIVE			  Near	 CODE:0502
TRANSLATEENABLED		  Byte	 CODE:012A
TRANSLATEFROM			  Byte	 CODE:011F
TRANSLATELENGTH			  Byte	 CODE:0129
Turbo Assembler	 Version 3.1	    05/22/18 24:10:23	    Page 15
Symbol Table



TRANSLATETO			  Byte	 CODE:0124
TRUE				  Number 00FF
_2FH_DEFAULT			  Near	 CODE:057D
_2FH_EXIT			  Near	 CODE:05F5
_ACTUALPRINT			  Near	 CODE:064E
_ALREADYINSTALLED		  Near	 CODE:072A
_ALREADYINSTALLED2FH		  Near	 CODE:0582
_BLOCK				  Near	 CODE:04CF
_CHECKIGNORED			  Near	 CODE:04C3
_CHECKTRANSLATE			  Near	 CODE:04D7
_CHECKTRANSLATELOOP		  Near	 CODE:04E5
_DISPLAYHELP			  Near	 CODE:0761
_DONTPRINT			  Near	 CODE:0621
_EXIT				  Near	 CODE:0733
_EXITTOGGLECURSIVE		  Near	 CODE:054C
_F5				  Near	 CODE:046E
_F6				  Near	 CODE:047F
_F7				  Near	 CODE:0493
_F8				  Near	 CODE:04A4
_FINISHTSR			  Near	 CODE:0757
_GO				  Near	 CODE:046B
_GO_ON				  Near	 CODE:06BB
_INITTSR			  Near	 CODE:0683
_LETSPRINT			  Near	 CODE:0614
_NEXTCHAR			  Near	 CODE:073F
_NOTREMOVE			  Near	 CODE:05D0
_NOTTOPRINT			  Near	 CODE:0625
_PARAMPARSINGEND		  Near	 CODE:076C
_PRINTSTREND			  Near	 CODE:0782
_PRINTSTRLOOP			  Near	 CODE:0776
_QUIT				  Near	 CODE:04FA
_REMOVE				  Near	 CODE:0716
_RESTORESYMBOL			  Near	 CODE:053D
_SHIFTTABLE			  Near	 CODE:0514
_SHOULDCONTINUE			  Near	 CODE:06A0
_START				  Near	 CODE:0100
_TEST_FX			  Near	 CODE:046E
_TRANSLATE			  Near	 CODE:04F1
_TRANSLATEORIGNORE		  Near	 CODE:04B5
_UNINSTALL			  Near	 CODE:0585
_UNLOADED			  Near	 CODE:05E4

Groups & Segments		  Bit Size Align  Combine Class

CODE				  16  0785 Para	  none	  CODE
