Міністерствоосвіти та науки УкраїниКіровоградський Державний Технічний університет
Кафедрапрограмного забезпечення
Курсоваробота
здисципліни “Програмування на мові ASM-86” на тему:
ПрограмаTXTPRINT.COM — резидентна програма для швидкого і зручного друкування виборчоготексту з екрану
Зміст
Вступ.
1. Призначення та областьвикористання системи.
2. Огляд iснуючих систем. Обґрунтування вибору принципу розробки та методики побудови системи. Постановка задачіпо реалізації технічногозавдання
3. Опис та обґрунтування проектних рішень по проектуванню системи.
4. Разрахунки та експерементальніматеріали які підтверджують вірністьпрограмних рішень
5. Основнi висновки
Перелiк скорочень, символiв таспецiальних термiнiв.
Список лiтератури.
Анотацiя.
Додатки.
Текст програми.
Вступ
Програма txtprint.com — резидентна програма, яка предназначена для того, щоб швидко ізручно надрукувати виборчий текст з екрану. Це може бути корисним, колидоводиться аналізувати в водночас багато текстової інформаціі, наприклад різніфайли-помічники, текст іншої програми, та багато ін. Також ця програма можестати у пригоді тоді, коли треба надрукувати текстовий файл, але не повністю,окремими епізодами. Програма дуже зручна для її використання, займає усього 2килобайти DOS — пам`яті, також її можна вилучити з пам`яті в будь-який час. Просто ізрозуміло оформлен інтерфейс з користувачем, отже навчитись роботі з програмою TXTPRINT.COM можна за хвилину.
Також в програмівстановлено тест на подвійну загрузку, отже при спробі завантажити її вдругекористувач отримає повідомлення про це, а також програма нагадае про «гарячі» клавіші, таким чином запобігаючи подвійного завантаження.Програма не конфліктує з іншими резидентними програмами (якщо, звісно, вонипрацюють коректно), але в разі змінення ними хочаб одного з векторів преривань INT 08H, INT 09H, INT 28H, INT 2FH програма TXTPRINT.COM не в змозі буде вилучитись з пам`ятіпо вимозі користувача. Про це програма видасть повідомлення, і нагадає пропричину цього (не на вершині). Але після вилучення з пам`яті тієї програми, щозмінила вище перечислених векторів преривань, при подальшої вимоги користувачапрограму TXTPRINT.COM теж буде вилучено з пам`яті.
1.Призначення та область використання системи
Програма TXTPRINT.COM призначена для друку на принтерівибіркового тексту з екрану. Також її можна використовувати в учбових закладахдля полегчення і прискорення засвоєння потрібної документації з комп`ютера (різні HELP-програми, завдання задач та ін.).Для цього користувачу потрібно перед переглядом документації на комп`ютері завантажити програму TXTPRINT.COM і в потрібний час викликати її задопомогою «гарячих» клавиш. Потім помітити потрібну частину тексту і датикоманду «печатати». Після чого цей текст розпечатається на принтері, і будебільш зручнішим для прочитання та багаторазового перегляду під час виконанняроботи (лабораторної тощо). Програма має дуже простий і зручний інтерфейс, щодуже полегшує роботу з нею, займає усього 2 кілобайти DOS-пам`яті.
Також ця програмадуже цікава з точки зору вивчення резидентних програм. На її прикладі можнаобучати студентів по роботі з функціями DOS в резидентних програмах.
2. Огляд існуючих систем, обґрунтування виборупринципу розробки та методики побудовисистеми. Постановка задачі пореалізації технічного завдання
Існує багатосистем, у яких можна зробити вибіркову розпечатку тексту (усіпрограми-редактори, та багато ін.), але їх недолік у тому, що вони нерезидентні, і можуть розпечатувати тільки текст, редагуванням якого вонизаймаються.
Програма TXTPRINT.COM повинна бути резидентною, працюватишвидко та надійно при різних процесорах, а також займати якомога менше пам`яті. Тому задача розроблялась на мовіасемблера (ASM-86) для TASM версії не нижче 2.0.
Програма повинна:
n бути резидентною і не конфліктувати зопераційною системою та іншими програмами;
n викликатись по натисненню «гарячих»клавиш; мати дружній інтерфейс з користувачем;
n розпечатувати помічений текст зекрану;
n не завантажуватись в друге;
n займати якомога менше пам`яті;
n по вимозі користувача вилучатись зпам`яті.
По обґрунтуваннюта реалізації цього завдання см. розділ 3.
3. Опис та обґрунтуванняпроектних рішень по проектуванню системи
Усе, щоприводиться у цьому параграфi вiдноситься тiльки до «випригуючих»(popup) резидентних програм.
Реентабельною(повторно входимою) програмою називаеться програма чи процедура, одна копiяякої в пам`ятi може бути одночасно викликатись кiлькома процесами, при чьомурiзноманiтнi виповнювання цiєї процедури не впливають одна на одну.
НереентабильністьMS-DOS проявляеться в неможливiстi звертання к функцiям DOS, якщо вжевиповнюеться яка-небудь iнша функцiя DOS. Порушення цiєї вимоги призведе дозруйнування системного стеку i краху операцiйної системи. Саме знереентабильнiстю DOS пов`язанi основнi труднощi розработки popup — програм.Справа в тому, що цi резидентнi програми використовують для свого запускуаппаратнi преривания, якi можуть статися в будь-який час, у тому числi й тодi,коли виповнюється функцiя DOS.
Найпростiшерiшення цiєї проблеми складається у повнiй вiдмовi вiд використання системногосервiсу DOS в резидентних програмах. Iнколи це не дуже складно. Так, для виводуна дiсплей можна користуватись прериванням BIOS 10H чи прямим записом увiдеобуфер, для вводу символiв з клавiатури приємлимо користуватись прериванням16H, при роботi з принтером i послiдовними портами також неважко працювати нарiвнi BIOS. Але у разi, коли потрiбен дисковий ввод — вивод, це вже стає дужепроблематичним.
Працювати здисками средствами BIOS — дiйсно дуже хлопотна справа.
Iснують i iншiситуацiї, коли зручнiше було б використовувати функцiї DOS. Отже, требанавчитися перемагати нереентабiльнiсть DOS. Для цього iснує багато можливостей.
Почнем з того, щоіснує простий (хоча й недокументований) спосiб запобiгнути конфлiктiв з операційноюсистемою. При активiзацiї програма може перевiрити байтовий прапорець активнiстiDOS i, якщо вiн вiдмiнний вiд нуля (сервiс DOS недоступний), повернутись допасивного стану. Адресу цього прапорця повiдомляє функцiя DOS 34H.
/>
Функція 34H. Дає адресу прапорця активністі DOS
/>Виклик: AH = 34H
/>Повертає: ES:BX — адреса прапорця
Нажаль, якщовибрати цей путь, така резидентна программа, скоріше за все, взагалі буде невзмозі стартувати. Це пов`язано з тим, що COMMAND.COM та багато інших програм проводятьбагато часу в очикуванні ввода строки з клавіатури посредством функції DOS 0AH, і, отже, прапорець активністі DOS майже завжди взведений. Ця обставинавикористовується у диспетчері функцій DOS, який може мати вигляд на зразок цього:
Int_21h PROC far
sti
pushf
cmpah,0Ah ;якщо номер функції не рівний 0ah,
jnz Exec ; то приступити квиконанню.
Fn0Ah:
push ax ; якщо функція 0ah, то затримати
mov ah,0bh; їївиповнення до тіх пір, поки у
int 21h ; буфері клавіатурине з`явиться
cmp al,0 ; хочаб один символ.
pop ax
jnzExec
pushcx
movcx,4000h
Delay: loopDelay ; зробитипаузу
popcx
jmpshort Fn0Ah; іповторити перевірка буфера.
Exec:
orbyte ptr cs:DOS_busy,01h; встановити признак
; зайнятостіDOS.
Popf ; визвати початковийобробник.
pushf
calldword ptr cs:[Int_21h_vect]
pushf
andbyte ptr cs:DOS_busy,0feh ; скинути признак
; зайнятості.
popf
ret2
Int_21h_vectdd ?
Dos_busy db 0
Int_21hENDP
Запит навиконання функції 0AH не передається одразу до операційноїсистеми. Замість цього периодично перевіряється стан буфера вводу (функція DOS 0BH або функція 01H преривання 16H). І вже тільки після того як буферпочав заповниватися, визивається функція 0AH.Оберніть увагу на те, як оформлен возврат у програму — це викликано тим, що DOS використовує прапорець CF в якості признаку помилки.
Важливо те, що вописаному прикладі можна відмовитись від перевірки недокументованого прапорцяактивністі DOS. Замість того диспетчервстановлює свій власний прапорець, який дотого ж бітовий, отже він може бути об`єднан з іншими прапорцями резидентноїпрограми.
Диспетчер функційDOS — приємлимий, але ненайбільш вдалий спосіб перевагання нереєнтабільності DOS. Програмам, використовуючим його,далеко не завжди вдається стартувати. Крім того, їм приходиться аналогічнимчином відслежувати ще й преривання 25H (читати сектор), 26H (писатисектор) DOS, а також преривання 13H BIOS.
Обробникипреривань 25H і 26H виявляються звичайними функціями — під час повернення управління вони залишають в стеці регистр прапорців. А цекласичний приклад помилки, якій в наслідок увішов у документацію.
Найбільш цікавимиможливостями преодоління нереєнтабільністі DOS пов`язані з використовуванням недокументованого преривання 28H. Це преривання використовуєтьсярезидентними процесами самої операційної системи, наприклад, PRINT, та генерується як раз під часвиконання функцій DOS, колипрапорець активністі DOS взведений, але система знаходиться у безпечному стані.
За допомогоюпреривання 28H можна досягнути потрясаючихрезультатів. Отже, така програма може стартувати, наприклад, під час копіюванняфайлів, а іноді при форматуванні диску.
При натисканні на«гарячу» клавишу не відбувається негайна активізація програми, а лишевстановлюється битовий прапорець, повідомляючий, що поступила командастартувати. Обробник преривання 28H перевіряє стан прапорця, і, якщо прапорець встановлен, апрограма ще не активна, активізує її. На прикінці роботи управління завждипередається завжди повинне передаватись початковому обробнику. Програми, яківиконуються усередині преривання 28H, неповинні користуватись функціями DOS з номерами 00H — 0CH.
А як буть, колидовгий час не відбувається звертання до функцій DOS і, отже, не вироблялось преривання28H? ПроРграмазнов не в змозі стартувать. Щоб запобігнути цього, буде потрібна ще одна точкавходу, в якісті якої зручно буде обрати обробник якогось часто возникаючогопреривання, наприклад, від таймеру. Тоді перед активізацією програми требаперевіряти прапорець активністі DOS, чи свій власний прапорець.
Реакція навиключні випадки.
Іноді врезультаті збоїв апаратної частини або неправильних дій користувача можескластися ситуація, коли подальша робота програми виявляється неможливою. Вцьому випадку управління дістає спеціальна процедура обробки критичної помилки,адреса якої знаходиться у векторі преривання 24H. Користувач може також сам прерватипрограму, натиснувши комбинацію клавиш Ctrl+Break. При цьому MS-DOS передає управління до процедуризавершення, яка починається по адресі обробника преривання 23H.
Цей сервіс DOS, неодмінно, дуже корисний, алеорієнтован на звичайні програми і не може правильно працювати в резидентнихпрограмах. Тому вам слід передбачити власну оброботку виключних випадків абовідключити існуючу.
Почнемо зпреривання Ctrl+Break. Реакція системи на це прериваннязалежить від стану прапорця перевірки по Ctrl+Break. Якщо прапорець скинутий, то перевірка натиснення Ctrl+Break і завершення програми відбуваєтьсятільки при виконанні функції DOS з номерами 00H — 0CH, а якщо прапорець встановлен, привиконанні будь-яких функцій. Тому, якщо в програмі не використовуються функції DOS 00H-0CH, тодідостатньо скинути прапорець перевірки по Ctrl+Break при активізації резидентної програми і встановити його початковезначення перед поверненням у пасивний стан.
/>
Функція 33H. Прапорець перевірки по Ctrl+Break
/>Виклик: AH = 33H
AL = 0 — отримати стан прапорця
1 — змінити станпрапорця.
DL (якщо AL=1) = 0 — скинути прапорець
1 — встановитипрапорець
/>Повертає: DL ( якщо AL дорівнював 0) -
стан прапорця:
0 — скинут
1 — встановлен
Для перевірки абозміни стану прапорця зручно застосовувати функцію DOS 33H.
Другий можливийпуть — просто відмінити оброботку преривання 23H, тобто змінити його вектор так, щоб він вказував на інструкцію IRET.
При виникниннікритичної помилки (звично це помилка диску) MS-DOS завантажує у регістри AX, DI, SI, BP інформацію про помилку ініцируєпреривання 24H. Стандартний системнийобробоник преривання веде себе слідуючим чином: видає на дісплей повідомленняпро помилку і запит користувача — «Abort, Retry, File or Ignore?» («Прервати, Повторити, Зняти або Ігнорувати»), чекаєвідповіді і повертає управління функції DOS, при виконанні якої виникла помилка.Подальші дії операційної системи визначається змістом регістру AL(відповідь користувача).
4. Розрахунки та експеріментальні матеріали, що підтверджуютьвірність програмних рішень
Насправді,програма не має в собі ніяких математичних розрахунків, тільки простіші.Складність написання програми полягала у технічній реалізації поставленоїзадачі. Тому підтвердити вірність програмних рішень можливо було тількиексперіментально. Були проведені тести на можливу недостачу пам`яті, роботу у версіях DOS 3.2 й вище, також під емуляцією DOS у системі WINDOWS`95. Також програма пройшла тести на правильність друку,загальну роботу з принтером. Результати тестів підтверджують правильністьроботи програми. Тести проводилися з EPSON-суміснимипринтерами.
5.Основні висновки
Програма TXTPRINT.COM — програма для вибіркового друкутексту з екрану. Для того, щоб получити готовий COM — файл з тексту програми, требавиконати: TASM TXTPRINT.ASM, потім TLINK TXTPRINT.OBJ /T. Після цього запустити програму TXTPRINT.COM. Під час просмотру інформації наекрані, яку треба розпечатати треба натиснути ScrollLock. Після цього, користуючись клавишамикурсору і ENTER помітити необхідний фрагмент тексту.Потім для розпечатки натиснути клавишу BackSpace, щоб почати розпечатувати, або ESC в разі, якщо текст був поміченийнеправильно. Після цього програма завершує своє роботу до наступного виклику поScrollLock. Коли роботу з розпечаткоюзакінчено взагалі, можна вилучити програму TXTPRINT.COM з пам`яті за допомогою комбинаціїклавиш Ctrl+Alt+Esc. Програма повідомить про закінченнясвоєї роботи, і для того, щоб розпочати роботу програми знов, треба зановозавантажувати TXTPRINT.COM.
Програма впроцесі роботи змінює вектори преривань 08H, 09H, 28H, 2FH, 23H і 24H. Томуякщо після завантаження TXTPRINT.COM булитакож завантажені інші програми, використовуючи хоча б одне з цих преривань, тоцю програму неможна буде вилучити з пам`яті доти, доки не будуть вилучені тіпрограми, а отже востановлені вектори цих преривань.
Перелiкскороченнь, символiв та спецiальних термiнiв
i т.д. — i такдалi
i т.i. — i такеiнше
та iн. — та iншi
т.я. — так як
п. — пункт
ОС — операцiйна система
popup — резидентні програми, які викликаютьсякористувачем
DOS — дискова операцiйнасистема
BIOS — базовасистема вводу/виводу
INT — переривання
PC — персональний комп'ютер
WINDOWS — операцiйна система
Списоклітератури
1. Р. Джордейн «Справочник программиста персональныхкомпьютеров типа IBM PC» М: Мир, 1991р.
2. П. Абель «Мова асемблера для IBM PC тапрограмування.» М.: Вища школа,1992.
3. Р. Лей та «Уейт-Груп» «Написання драйверів для MS-DOS.» М.: Мир, 1995р.
4. Електронний спавочник «TeachHelp»
5. Конспект лекцій по системномупрограмуванню
Анотація
Програма TXTPRINT.COM — програма для вибіркового друкутексту з екрану. Для того, щоб получити готовий COM — файл з тексту програми, требавиконати: TASM TXTPRINT.ASM, потім TLINK TXTPRINT.OBJ /T. Після цього запустити програму TXTPRINT.COM. Під час просмотру інформації на екрані,яку треба розпечатати треба натиснути ScrollLock. Після цього, користуючись клавишами курсору і ENTER помітити необхідний фрагмент тексту.Потім для розпечатки натиснути клавишу BackSpace, щоб почати розпечатувати, або ESC в разі, якщо текст був поміченийнеправильно. Після цього програма завершує своє роботу до наступного виклику поScrollLock. Коли роботу з розпечаткоюзакінчено взагалі, можна вилучити програму TXTPRINT.COM з пам`яті за допомогою комбинаціїклавиш Ctrl+Alt+Esc. Програма повідомить про закінченнясвоєї роботи, і для того, щоб розпочати роботу програми знов, треба зановозавантажувати TXTPRINT.COM.
Програма впроцесі роботи змінює вектори преривань 08H, 09H, 28H, 2FH, 23H і 24H. Томуякщо після завантаження TXTPRINT.COM булитакож завантажені інші програми, використовуючи хоча б одне з цих преривань, тоцю програму неможна буде вилучити з пам`яті доти, доки не будуть вилучені тіпрограми, а отже востановлені вектори цих преривань.
Текст програмимає дев`ять модулів. Їх текст,краткий опис та пояснення приводяться у додатках.
Додатки
Текстпрограми
; ФайлTXTPRINT.ASM — основна програма
; Для створенняготового продукту необхідно
; виповнитислідуючі команди:
; TASM TXTPRINT.ASM
; TLINK /tTXTPRINT.OBJ
;**************************************************
cr equ 13 ;символ «Возврат каретки».
lf equ 10 ;символ «Перевод строки».
start_offset equ0b8h ; сміщення початку резидентної
; порціїу сегменті команд
; і вершинавнутрішнього стеку.
internal_flagsrecord Sf:1,Rf:1,Af:1,Tf:1,Pf:1 ; набор прапорців
; 1=печать дозволена
; 1=Int_08hактивна
; 1=программа активна
; 1=команда«удалити»
; 1=команда«стартувати»
.model tiny
.code
org 100h
entry:
jmp boot ;перейти на процедуру загрузки резиденту.
shift = offsetcallvideo — start_offset ; Величина
; сдвигу резидентної порції.
flags_offset =offset resident_sign — shift ; Сміщення прапорців
callvideo proc
; Обернутися до відео-BIOS.
push di
push si
push bp
int 10h
pop bp
pop si
pop di
ret
callvideo endp
sethandlerproc
; Встановитиобробник преривання.
push ax
mov ah,35h
int 21h
mov wordptr [di],bx
mov wordptr [di+2],es
pop ax
mov ah,25h
int 21h
ret
sethandlerendp
resethandlerproc
; Восстановити минулий обробник преривань.
push ds
movdx,word ptr [di]
movds,word ptr [di+2]
mov ah,25h
int 21h
pop ds
ret
resethandlerendp
includebeep.asm
includetypestr.asm
includemessage.asm
includeremove.asm
includemain.asm
includeprepare.asm
includetake&prn.asm
int_28h procfar
test byteptr cs:[flags_offset],mask Sf or mask Rf
jz pass_28h ; Якщо небулокоманди, то вихід.
test byte ptrcs:[flags_offset],mask Af or mask Tf
jnz pass_28h ; Якщоактивна, то вихід.
or byte ptrcs:[flags_offset],mask Af
callprepare ; Запуск.
and byteptr cs:[flags_offset],not(mask Sf or mask Rf or mask Af)
pass_28h: ;Передати управління ісходному обробнику.
jmp dword ptrcs:[int_28h_vect-shift]
int_28h_vectdd ?
int_28h endp
int_08h procfar
test byteptr cs:[flags_offset],mask Tf or mask Af; or mask Df
jnz pass_08h ; Якщоактивна, то вихід.
or byte ptrcs:[flags_offset],mask Tf ; Встановити
; признак активнисті Int_08h.
pushf ; Викликати ісходний
call dword ptrcs:[int_08h_vect-shift] ; обробник.
test byteptr cs:[flags_offset],mask Sf or mask Rf
jz end_08h ; Якщо небуло команды, то вихід.
push di ; Перевірити признак активности DOS.
push es
moves,word ptr cs:[dos_flag_seg-shift]
movdi,word ptr cs:[dos_flag_off-shift]
test byteptr es:[di],0ffh
pop es
pop di
jnzend_08h ; Якщо DOS активна, то вихід.
or byteptr cs:[flags_offset],mask Af ; Встановити признак
; активности START.
callprepare ; Запуск.
and byteptr cs:[flags_offset],not(mask Sf or mask Rf or mask Af)
end_08h:
and byteptr cs:[flags_offset],not mask Tf; Сбросити
iret ; признакактивністи Int_08h.
pass_08h: ; Передати управління ісходному
jmp dword ptrcs:[int_08h_vect-shift]; обробнику.
int_08h_vect dd ?
int_08h endp
int_09h proc far
push ax ; Сохранити регістр AX.
in al,60h ; Ввести код натиснутоїклавиши.
cmp al,70 ; клавиша ScrollLock.
jneremove_test
mov ah,2 ; Перевірити Shift state.
int 16h
and al,0h
cmp al,0h
jne pass_09h
or byte ptrcs:[flags_offset],mask Sf
jmp shortend_09h
remove_test:
cmp al,1 ; Клавиша Esc ?
jne pass_09h
mov ah,2 ; Перевірити Shift state.
int 16h
and al,0ch
cmp al,0ch
jne pass_09h
or byte ptrcs:[flags_offset],mask Rf
end_09h:
in al,61h ; Обробити апаратнепреривання.
push ax
or al,80h
out 61h,al
pop ax
out 61h,al
mov al,20h
out 20h,al
pop ax
iret
pass_09h:
pop ax ;Восстановити регістри і передати управління по старому
jmp dword ptrcs:[int_09h_vect-shift]; вектору преривання Int_09h.
int_09h_vect dd ?
int_09h endp
int_2fh proc far
cmp ax,8900h ; Якщо запитуєтся установка процесу
jne pass_2fh ; з номером 89Н, то запретити установку.
mov al,0ffh ; Інакше передати управління
iret ; ісходному обробнику.
pass_2fh:
jmp dword ptrcs:[int_2fh_vect-shift]
int_2fh_vect dd ?
int_2fh endp
exeptions procfar
int_24h: mov al,3 ; Команда «Зняти системний визов».
int_23h: iret ; Вийти з преривання.
int_24h_vect dd ?
int_23h_vect dd ?
exeptions endp
dos_flag_off dw ?
dos_flag_seg dw ?
resident_signinternal_flags
;----- Ця частинапрограми використовується для загрузки резидента
boot: ; ( самане є резидентною ).
mov si,offsetstart_string
call teletype
multiplex_test:
mov ax,8900h ; Тест на подвійну
int 2fh ; установку.
cmp al,0
je install ; Якщо не встановлен, то встановить.
mov si,offsetreboot_message ; Інакше
call teletype ; видати повідомлення про подвійну
callteletype_keys; загрузку, «гарячих» клавишах
int 20h ; і завершитись.
install:
callteletype_keys; Видати повідомлення про «гарячі» клавиши
cld ; Сдвинути резидентну
movdi,start_offset; порцію в PSP.
mov si,offsetcallvideo
movcx,boot-callvideo
rep movsb
movcx,sethandler-shift
mov al,09h ; Встановити новий обробник
movdx,int_09h-shift ; преривання Int09h.
mov di,int_09h_vect-shift
call cx
mov al,2fh ; Встановити новий обробник
movdx,int_2fh-shift ; преривання Int2fh.
movdi,int_2fh_vect-shift
call cx
mov al,28h ; Встановити новий обробник
movdx,int_28h-shift ; преривання Int28h.
movdi,int_28h_vect-shift
call cx
mov al,08h ; Встановити новий обробник
movdx,int_08h-shift ; преривання Int08h.
movdi,int_08h_vect-shift
call cx
mov ah,34h ; Прочитати і сохранити адресу
int 21h ; прапорця активністи DOS.
mov word ptrds:[dos_flag_off-shift],bx
mov word ptrds:[dos_flag_seg-shift],es
mov es,wordptr ds:[002ch] ; Освободити
mov ah,49h ; окруженіе DOS.
int 21h
movdx,boot-shift ; Завершитись, оставив
int 27h ; резидента.
includeteletype.asm
teletype_keysproc near
; Виводитьповідомлення про гарячі клавиши.
mov si,offsethot_keys_mess1
call teletype
mov si,offsethot_keys_mess2
call teletype
mov si,offsethot_keys_mess3
call teletype
mov si,offsethot_keys_mess4
call teletype
mov si,offsethot_keys_mess5
call teletype
mov si,offsethot_keys_mess6
call teletype
mov si,offsethot_keys_mess7
call teletype
ret
teletype_keysendp
start_string db«Screen text printer. Version 1.0.»,cr,lf,0
hot_keys_mess1 db«Use »,0
hot_keys_mess2 db«ScrollLock»,40 dup (0)
hot_keys_mess3 db" to activate text printer and",cr,lf,0
hot_keys_mess4 db«Ctrl + Alt + Esc »,34 dup(0)
hot_keys_mess5 db" to remove it from memory.",cr,lf,lf,0
hot_keys_mess6 db«Use Enter to label text and»,cr,lf,0
hot_keys_mess7 db«BackSpace to print it. Use Esc to cancel.»,cr,lf,0
reboot_message dbcr,lf,«Text Taker has already»
db "been installed !",7,cr,lf,lf,0
io_error_mess db«I/O failure.»,cr,lf,lf,lf,0
end_entry:
END entry
;******************Кінець файлу TXTPRINT.ASM ************************
; ФайлPREPARE.ASM
; Модуль основноїпрограми.
;*************************************************************
prepare proc
cli ;Ініціализувати стек.
mov word ptrcs:[stack_offset-shift],sp
mov word ptrcs:[stack_seg-shift],ss
push cs
pop ss
movsp,start_offset
sti
push ax ;Сохранити регістри.
push bx
push cx
push dx
push di
push si
push bp
push ds
push es
push cs
pop ds
mov al,23h ;Встановити новий обробник преривання Int23h.
movdx,int_23h-shift
movdi,int_23h_vect-shift
callsethandler
mov al,24h ;Встановити новий обробник прерывання Int24h.
movdx,int_24h-shift
movdi,int_24h_vect-shift
callsethandler
mov ah,15 ;Визначити поточний відеорежим і
callcallvideo; номер відеосторінки.
cmp al,2
je set_param
cmp al,3
je set_param
cmp al,7
jneend_prepare ; Якщо графічний режим, то вихід.
set_param: ; Сохранити номер відеосторінки.
mov byte ptrds:[current_video_page-shift],bh
mov ah,03h ; Сохранити позицію курсору.
callcallvideo
mov word ptrds:[cursor_loc-shift],dx
test byte ptrds:[flags_offset],mask Sf
jzbegin_remove
call start
jmp shortrestore_cursor
begin_remove:
call remove
restore_cursor:
mov bh,byteptr ds:[current_video_page-shift]
mov dx,wordptr ds:[cursor_loc-shift] ; Восстановити
mov ah,2 ; положення курсору.
callcallvideo
end_prepare:
mov al,23h ; Восстановити вектор преривання Int 23h.
movdi,int_23h_vect-shift
callresethandler
mov al,24h ; Восстановити вектор преривання Int 24h.
movdi,int_24h_vect-shift
callresethandler
pop es ;Восстановити регістри.
pop ds
pop bp
pop si
pop di
pop dx
pop cx
pop bx
pop ax
cli ;Переключитись на стек прерваної програми.
mov ss,wordptr cs:[stack_seg-shift]
mov sp,wordptr cs:[stack_offset-shift]
ret
prepare endp
stack_offset dw ?
stack_seg dw ?
cursor_loc dw ?
current_video_pagedb ?
;*******************Кінець файлу PREPARE.ASM *************************
; Файл MAIN.ASM
; Модуль основноїпрограми
;*************************************************************
start proc
mov bp,sp ; Зарезервирувати місто
sub sp,13 ; в пам`яти для змінних.
mov byte ptrds:[flag-shift],0 ; Обнулить всі прапорці.
mov byte ptrds:[fl2-shift],0
mov byte ptrds:[xx-shift],dl
mov byte ptrds:[yy-shift],dh
rd:
call kurpos ; Встановити курсор.
call delay ; Визвать затримку.
in al,60h ; Взяти символ.
cmp al,14 ; BackSpace ?
jne nn ; Якщо ні — далі.
or byte ptrds:[flags_offset],mask Pf ; Іначе дозволити печать,
mov ah,01h ; ініціализувати 0 порт,
mov dx,0
int 17h
call unlabel ; розпечатать
jmp hi ; й вийти.
nn:
cmp al,28 ; ENTER ?
jne n0 ; Якщо ні — далі.
call here
n0:
cmp al,72 ; UP ?
jne n1 ; Якщо ні — далі.
cmp byte ptrds:[yy-shift],0 ; Перевірити позицію курсора.
jne n00
mov byte ptrds:[yy-shift],25
jmp n00
rd1:
call keybuf
jmp rd
n00:
dec byte ptrds:[yy-shift] ; Уменьшить Y на 1.
call kurpos ; Встановити курсор.
n1:
cmp al,80 ; DOWN ?
jne n2 ; Якщо ні — далі.
cmp byte ptrds:[yy-shift],25 ; Перевірити позицію курсору.
jne n11
mov byte ptrds:[yy-shift],0
n11:
inc byte ptrds:[yy-shift] ; Увеличити Y на 1.
call kurpos ; Встановити курсор.
n2:
cmp al,75 ; LEFT ?
jne n3 ; Якщо ні — далі.
cmp byte ptrds:[xx-shift],0 ; Преревірити позицію курсору.
jne n22
mov byte ptrds:[xx-shift],80
dec byte ptrds:[yy-shift]
n22:
dec byte ptrds:[xx-shift] ; Уменьшить X на 1.
call kurpos ; Встановити курсор.
n3:
cmp al,77 ; RIGHT ?
jne n4 ; Якщо ні — далі.
cmp byte ptrds:[xx-shift],80 ; Перевірити позицію курсору.
jne n33
mov byte ptrds:[xx-shift],0
inc byte ptrds:[yy-shift]
n33:
inc byte ptrds:[xx-shift] ; Увеличить X на 1.
call kurpos ; Встановити курсор.
n4:
cmp al,1 ; ESC ?
jne rd1 ; Якщо ні — далі.
cmp byte ptrds:[fl2-shift],0 ; Інакше восстановити колір
je hi ; й вийти.
call unlabel
; Вихід.
hi:
call keybuf ; Очистити буфер клавіатури.
mov sp,bp
ret ;Завершитись.
start endp
; Опис змінних:
scrr db ?
xx db ?
yy db ?
x1 db ?
y1 db ?
tx db ?
ty db ?
wx db 2
wy db 2
fl2 db 0
flag db 0
;********************Кінець файлу MAIN.ASM **************************
; Файл TAKE&PRN.ASM
; Модуль основноїпрограми.
;*************************************************************
keybuf proc
; Очищає буферклавіатури.
push es
push ax
sub ax,ax
mov es,ax
moval,es:[41ah] ; Взяти кінець буферу
moves:[41ch],al ; і записати в початок.
pop ax
pop es
ret
keybuf endp
delay proc
; Ініцііруєзатримку.
push cx
mov cx,60
l1:
push cx
mov cx,20000
l2:
loop l2
pop cx
loop l1
pop cx
ret
delay endp
del2 proc
; Ініцііруєзатримку.
push cx
mov cx,6000
a2:
loop a2
pop cx
ret
del2 endp
here proc
; Обробкавиділення тексту.
push ax
cmp byte ptrds:[flag-shift],0
je nh
mov al,byteptr ds:[wx-shift]
cmp byte ptrds:[xx-shift],al
jne lab
mov al,byteptr ds:[wy-shift]
cmp byte ptrds:[yy-shift],al
je rr
lab:
call labela ; Виділити.
jmp rr
nh:
mov al,byteptr ds:[xx-shift]
mov byte ptrds:[x1-shift],al
mov al,byteptr ds:[yy-shift]
mov byte ptrds:[y1-shift],al
rr:
pop ax
mov byte ptrds:[flag-shift],1
ret
here endp
kurpos proc
; Встановлюєкурсор.
push ax
mov ah,02h
mov dh,byteptr ds:[yy-shift]
mov dl,byteptr ds:[xx-shift]
mov bh,0
callcallvideo
pop ax
ret
kurpos endp
labela proc
; Змінює колірпоміченого тексту.
cmp byte ptrds:[fl2-shift],0
je f0
call unlabel
call ifswap
jmp f1
f0:
mov al,byteptr ds:[x1-shift]
mov byte ptrds:[wx-shift],al
mov al,byteptr ds:[y1-shift]
mov byte ptrds:[wy-shift],al
call ifswap
f1:
mov byte ptrds:[fl2-shift],1
mov al,byteptr ds:[x1-shift]
mov byte ptrds:[tx-shift],al
mov al,byteptr ds:[y1-shift]
mov byte ptrds:[ty-shift],al
hh:
push cx
push dx
mov ah,02h ;Змінити позицію курсору.
mov dh,byteptr ds:[ty-shift]
mov dl,byteptr ds:[tx-shift]
mov bh,0
callcallvideo
mov ah,08h ;Считати символ/атрибут.
mov bh,0
callcallvideo
mov byte ptrds:[scrr-shift],ah
mov ah,09h ;Записати символ з ізмененим атрибутом.
mov bl,byteptr ds:[scrr-shift]
add bl,15
mov cx,1
mov bh,0
callcallvideo
pop dx
pop cx
mov dl,byteptr ds:[tx-shift]
cmp dl,byteptr ds:[xx-shift]
je ok
as:
inc byte ptrds:[tx-shift]
cmp byte ptrds:[tx-shift],80
jne hh
mov byte ptrds:[tx-shift],0
inc byte ptrds:[ty-shift]
jmp hh
ok:
mov al,byteptr ds:[yy-shift]
cmp byte ptrds:[ty-shift],al
je rro ;Якщо кінець, то вийти,
jmp as ;інакше оброблювати наступний символ.
rro:
mov al,byteptr ds:[xx-shift]
mov byte ptrds:[wx-shift],al
mov al,byteptr ds:[yy-shift]
mov byte ptrds:[wy-shift],al
ret
labela endp
unlabel proc
; Встановлюєколір поміченого тексту.
push ax
push dx
push cx
mov al,byteptr ds:[x1-shift]
mov byte ptrds:[tx-shift],al
mov al,byteptr ds:[y1-shift]
mov byte ptrds:[ty-shift],al
tl:
mov ah,02h ; Змінити позицію курсору.
mov dh,byteptr ds:[ty-shift]
mov dl,byteptr ds:[tx-shift]
mov bh,0
callcallvideo
mov ah,08h ; Считати символ/атрибут.
mov bh,0
callcallvideo
mov byte ptrds:[scrr-shift],ah
call ToPrn
mov ah,09h ; Записати символ з востановленим атрибутом.
mov bl,byteptr ds:[scrr-shift]
sub bl,15
mov cx,1
mov bh,0
callcallvideo
mov al,byteptr ds:[wx-shift]
cmp byte ptrds:[tx-shift],al
je don
nt:
inc byte ptrds:[tx-shift]
cmp byte ptrds:[tx-shift],80
jne tl
call PrnEnt
mov byte ptrds:[tx-shift],0
inc byte ptrds:[ty-shift]
jmp tl
don:
mov al,byteptr ds:[wy-shift]
cmp byte ptrds:[ty-shift],al
je ex ;Якщо кінець, то вийти,
jmp nt ;інакше оброблювати наступний символ.
ex:
pop ax
pop cx
pop dx
ret
unlabel endp
ToPrn proc
; Печатаетсимвол.
test byte ptrds:[flags_offset],mask Pf ; Перевірити прапорець печаті.
jz outp ; Якщо не дозволено — вийти.
mov ah,00h
mov dx,0
int 17h ; Печатать.
call del2
outp:
ret
ToPrn endp
PrnEnt proc
; Печатает ENTER
test byte ptrds:[flags_offset],mask Pf ; Перевірити прапорець печаті.
jz notp ; Якщо не дозволено — вийти.
mov ah,0
mov dx,0
mov al,0ah ; Печатати CR.
int 17h
mov ah,0
mov dx,0
mov al,0dh ; Печатать LF.
int 17h
notp:
ret
PrnEnt endp
ifswap proc
push ax
mov al,byteptr ds:[y1-shift] ; Порівняти координати Y1 и YY
cmp al,byteptr ds:[yy-shift]
jg zq
jl qw
mov al,byteptr ds:[x1-shift] ; Порівняти координати X1 и XX
cmp al,byteptr ds:[xx-shift]
jng qw
zq: ; Якщо треба змінити,
mov al,byteptr ds:[yy-shift] ; змінюєм.
mov byte ptrds:[y1-shift],al
mov al,byteptr ds:[xx-shift]
mov byte ptrds:[x1-shift],al
mov al,byteptr ds:[wx-shift]
mov byte ptrds:[xx-shift],al
mov al,byteptr ds:[wy-shift]
mov byte ptrds:[yy-shift],al
qw:
pop ax
ret ;Выход
ifswap endp
;*******************Кінець файлу TAKE&PRN.ASM ***********************
; Файл REMOVE.ASM
; Модуль основноїпрограми
;*************************************************************
test_vector proc
; Перевіритивектор преривання.
mov ah,35h
int 21h
cmp bx,dx
jne exit
mov dx,es
cmp cx,dx
exit:
ret
test_vector endp
remove proc
mov cx,cs
movdi,test_vector-shift
mov al,09h ; Перевірити вектор преривання Int09h.
movdx,int_09h-shift
call di
jnenot_remove
mov al,2fh ; Перевірити вектор преривання Int2fh.
movdx,int_2fh-shift
call di
jnenot_remove
mov al,28h ; Перевірити вектор преривання Int28h.
movdx,int_28h-shift
call di
jnenot_remove
mov al,08h ; Перевірити вектор преривання Int08h.
movdx,int_08h-shift
call di
je uninstall
not_remove:
movax,notremove_mess-shift
push ax
push ax
call mess
ret
uninstall:
movax,remove_mess-shift
push ax
xor ax,ax
push ax
call mess
movcx,resethandler-shift
mov al,09h ; Восстановити вектор преривання Int09h.
movdi,int_09h_vect-shift
call cx
mov al,2fh ; Восстановити вектор преривання Int2fh.
movdi,int_2fh_vect-shift
call cx
mov al,28h ; Восстановити вектор преривання Int28h.
movdi,int_28h_vect-shift
call cx
mov al,08h ; Восстановити вектор преривання Int08h.
movdi,int_08h_vect-shift
call cx
cli
push cs
pop es
mov ah,49h ; Освободити займаєму пам`ять.
int 21h
ret
remove_mess db' has been',0,'REMOVED form memory. ',0
notremove_mess db' UNABLE to',0,'remove. Not on the top. ',0
remove endp
;*********************Кінець файлу REMOVE.ASM ***********************
; ФайлMESSAGE.ASM
; Модуль основноїпрограми.
;*************************************************************
xchgmess proc
movdi,code_table-shift ; Загрузити сміщення
movsi,attribute_table-shift ; таблиць кодів і
; атрибутів вікна повідомлення.
mov cx,6
mov dh,10
loop_1: ;Цикл по строках.
push cx
mov cx,30
mov dl,25
loop_2: ;Цикл по стовбцях.
push cx
mov ah,2
callcallvideo
mov ah,8
callcallvideo
cmp dh,15
jb lab_1
cmp dl,27
jb exch_noth
jmp shortexch_attr
lab_1:
cmp dh,11
jb lab_2
cmp dl,52
ja exch_attr
jmp shortexch_code
lab_2:
cmp dl,52
ja exch_noth
exch_code:
xchg al,byteptr [di] ; Заменити код символа.
inc di
exch_attr:
xchg ah,byteptr [si] ; Заменити атрибут.
inc si
exch_noth:
mov bl,ah ; Вивести символ.
mov cx,1
mov ah,9
callcallvideo
inc dx
pop cx
loop loop_2
inc dh
pop cx
loop loop_1
mov dx,1900h ; Убрати курсор.
mov ah,02h
callcallvideo
ret ; Вийти з процедури.
xchgmess endp
mess proc
push bp
mov bp,sp
push bx
mov bh,byteptr ds:[current_video_page-shift]
mov bl,byteptr ds:[attribute_table-shift]
push bx ; Вивести вікно повідомлення.
call xchgmess
pop bx
mov dx,0b29h ; Вивести текст повідомлення.
mov si,wordptr [bp+6]
call typestr
mov dx,0c1bh
call typestr
push bx ; Подати звуковий сигнал.
mov cx,2
mess_loop:
mov di,550
mov bx,30
call beep
mov di,1100
call beep
loopmess_loop
pop bx
wait_mess:
mov ah,0 ; Ждати натиснення клавиши.
int 16h
call xchgmess ; Восстановити екран.
pop bx
pop bp
ret 4 ; Вийти з процедури.
mess endp
; Таблицяатрибутів вікна повідомлення.
attribute_tabledb 29 dup(4eh),14 dup (206),13 dup (4eh)
db07h,07h
db 28 dup(4eh)
db07h,07h
db 4eh,26dup (206),4eh
db07h,07h
db 28 dup(4eh)
db 30 dup(07h)
; Образатрибутів вікна повідомлення.
code_table db'============================'
db'!Screen Printer: !'
db '! !'
db '! press any key… !'
db'============================'
;******************Кінець файлу MESSAGE.ASM *************************
; ФайлTYPESTR.ASM
; Модуль основноїпрограми.
;*************************************************************
typestr proc
typestr_loop:
mov ah,2 ; Встановити курсор в нужну позицию.
callcallvideo
lodsb
or al,al ; Якщо зустрився кінець строки,
jzend_typestr ; то вихід.
mov cx,1
mov ah,9
callcallvideo
inc dx ; Определити позицію для вивода
jmp shorttypestr_loop; следуючого символу.
end_typestr:
push dx ; Убрати курсор.
mov dx,1900h
mov ah,2
callcallvideo
pop dx
ret ;Вийти з процедури.
typestr endp
;********************Кінець файлу TYPESTR.ASM ************************
; Файл BEEP.ASM
; Модуль основноїпрограми.
;*************************************************************
beep proc
; Подає звуковойсигнал заданої частоти і тривання.
push bx ;Сохранити регістри.
push cx
push di
mov di,1000
mov al,0b6h ; Записати у регістр режим таймеру.
out 43h,al
mov dx,14h ; Делитель часу равен
mov ax,4f38h ; 1331000/частота.
div di
out 42h,al ; Записати молодший байт лічильника таймера 2.
mov al,ah
out 42h,al ; Записати молодший байт лічильника таймера 2.
in al,61h ; Считати поточну установку порта В
push ax ;й сохранити її.
or al,3
out 61h,al ; Включити динамик.
wait_beep:
mov cx,01fffh
speaker_on:
loopspeaker_on
dec bx ;Лічильник тривалісті ісчерпан ?
jnz wait_beep ; Ні. Продовжити звучання.
pop ax ;Да. Восстановити похідну установку
out 61h,al ; Порта В.
pop di ;Восстановити всі регистри.
pop cx
pop bx
ret ;Вийти з процедури.
beep endp
;*********************Кінець файлу BEEP.ASM *************************
; ФайлTELETYPE.ASM
; Модуль основноїпрограми.
;*************************************************************
teletype proc
mov bh,0 ;Обрати нулеву відеосторінку.
cld
type_next_char:
lodsb ;Загрузити наступний символ в AL.
mov ah,0eh
cmp al,0 ;Якщо кінець строки, то вихід.
jeend_teletype
callcallvideo; Вивести символ.
jmp shorttype_next_char
end_teletype:
ret
teletype endp
;********************Кінець файлу TELETYPE.ASM **********************