Програма Txtprint.com - резидентна програма для швидкого і зручного друкування виборчого тексту з екрану
Програма Txtprint.com - резидентна програма для швидкого і зручного друкування виборчого тексту з екрану
Міністерство
освіти та науки України
Кіровоградський Державний Технічний університет
Кафедра
програмного забезпечення
Курсова
робота
з
дисципліни “Програмування на мові 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стi
DOS 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
cmp
ah,0Ah ;
якщо номер функції не рівний 0ah,
jnz Exec ; то приступити к
виконанню.
Fn0Ah:
push ax ; якщо функція 0ah, то затримати
mov ah,0bh ; її
виповнення до тіх пір, поки у
int 21h ; буфері клавіатури
не з`явиться
cmp al,0 ; хочаб один символ.
pop ax
jnz
Exec
push
cx
mov
cx,4000h
Delay: loop
Delay ; зробити
паузу
pop
cx
jmp
short Fn0Ah ; і
повторити перевірка буфера.
Exec:
or
byte ptr cs:DOS_busy,01h ; встановити признак
; зайнятості
DOS.
Popf ; визвати початковий
обробник.
pushf
call
dword ptr cs:[Int_21h_vect]
pushf
and
byte ptr cs:DOS_busy,0feh ; скинути признак
;
зайнятості.
popf
ret
2
Int_21h_vect
dd ?
Dos_busy
db 0
Int_21h
ENDP
Запит на
виконання функції 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 /t
TXTPRINT.OBJ
;**************************************************
cr equ 13 ;
символ "Возврат каретки".
lf equ 10 ;
символ "Перевод строки".
start_offset equ
0b8h ; сміщення початку резидентної
; порції
у сегменті команд
; і вершина
внутрішнього стеку.
internal_flags
record 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 = offset
callvideo - 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
sethandler
proc
; Встановити
обробник преривання.
push ax
mov ah,35h
int 21h
mov word
ptr [di],bx
mov word
ptr [di+2],es
pop ax
mov ah,25h
int 21h
ret
sethandler
endp
resethandler
proc
; Восстановити минулий обробник преривань.
push ds
mov
dx,word ptr [di]
mov
ds,word ptr [di+2]
mov ah,25h
int 21h
pop ds
ret
resethandler
endp
include
beep.asm
include
typestr.asm
include
message.asm
include
remove.asm
include
main.asm
include
prepare.asm
include
take&prn.asm
int_28h proc
far
test byte
ptr cs:[flags_offset],mask Sf or mask Rf
jz pass_28h ; Якщо небуло
команди, то вихід.
test byte ptr
cs:[flags_offset],mask Af or mask Tf
jnz pass_28h ; Якщо
активна, то вихід.
or byte ptr
cs:[flags_offset],mask Af
call
prepare ; Запуск.
and byte
ptr cs:[flags_offset],not(mask Sf or mask Rf or mask Af)
pass_28h: ;
Передати управління ісходному обробнику.
jmp dword ptr
cs:[int_28h_vect-shift]
int_28h_vect
dd ?
int_28h endp
int_08h proc
far
test byte
ptr cs:[flags_offset],mask Tf or mask Af; or mask Df
jnz pass_08h ; Якщо
активна, то вихід.
or byte ptr
cs:[flags_offset],mask Tf ; Встановити
;
признак активнисті Int_08h.
pushf
; Викликати ісходний
call dword ptr
cs:[int_08h_vect-shift] ; обробник.
test byte
ptr cs:[flags_offset],mask Sf or mask Rf
jz end_08h ; Якщо не
було команды, то вихід.
push di
; Перевірити признак активности DOS.
push es
mov
es,word ptr cs:[dos_flag_seg-shift]
mov
di,word ptr cs:[dos_flag_off-shift]
test byte
ptr es:[di],0ffh
pop es
pop di
jnz
end_08h ; Якщо DOS активна, то вихід.
or byte
ptr cs:[flags_offset],mask Af ; Встановити признак
;
активности START.
call
prepare ; Запуск.
and byte
ptr cs:[flags_offset],not(mask Sf or mask Rf or mask Af)
end_08h:
and byte
ptr cs:[flags_offset],not mask Tf ; Сбросити
iret ; признак
активністи Int_08h.
pass_08h:
; Передати управління ісходному
jmp dword ptr
cs:[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.
jne
remove_test
mov ah,2
; Перевірити Shift state.
int 16h
and al,0h
cmp al,0h
jne pass_09h
or byte ptr
cs:[flags_offset],mask Sf
jmp short
end_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 ptr
cs:[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 ptr
cs:[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 ptr
cs:[int_2fh_vect-shift]
int_2fh_vect dd ?
int_2fh endp
exeptions proc
far
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_sign
internal_flags <>
;----- Ця частина
програми використовується для загрузки резидента
boot: ; ( сама
не є резидентною ).
mov si,offset
start_string
call teletype
multiplex_test:
mov ax,8900h
; Тест на подвійну
int 2fh
; установку.
cmp al,0
je install
; Якщо не встановлен, то встановить.
mov si,offset
reboot_message ; Інакше
call teletype
; видати повідомлення про подвійну
call
teletype_keys ; загрузку, "гарячих" клавишах
int 20h
; і завершитись.
install:
call
teletype_keys ; Видати повідомлення про "гарячі" клавиши
cld
; Сдвинути резидентну
mov
di,start_offset ; порцію в PSP.
mov si,offset
callvideo
mov
cx,boot-callvideo
rep movsb
mov
cx,sethandler-shift
mov al,09h
; Встановити новий обробник
mov
dx,int_09h-shift ; преривання Int09h.
mov di,int_09h_vect-shift
call cx
mov al,2fh
; Встановити новий обробник
mov
dx,int_2fh-shift ; преривання Int2fh.
mov
di,int_2fh_vect-shift
call cx
mov al,28h
; Встановити новий обробник
mov
dx,int_28h-shift ; преривання Int28h.
mov
di,int_28h_vect-shift
call cx
mov al,08h
; Встановити новий обробник
mov
dx,int_08h-shift ; преривання Int08h.
mov
di,int_08h_vect-shift
call cx
mov ah,34h
; Прочитати і сохранити адресу
int 21h
; прапорця активністи DOS.
mov word ptr
ds:[dos_flag_off-shift],bx
mov word ptr
ds:[dos_flag_seg-shift],es
mov es,word
ptr ds:[002ch] ; Освободити
mov ah,49h
; окруженіе DOS.
int 21h
mov
dx,boot-shift ; Завершитись, оставив
int 27h
; резидента.
include
teletype.asm
teletype_keys
proc near
; Виводить
повідомлення про гарячі клавиши.
mov si,offset
hot_keys_mess1
call teletype
mov si,offset
hot_keys_mess2
call teletype
mov si,offset
hot_keys_mess3
call teletype
mov si,offset
hot_keys_mess4
call teletype
mov si,offset
hot_keys_mess5
call teletype
mov si,offset
hot_keys_mess6
call teletype
mov si,offset
hot_keys_mess7
call teletype
ret
teletype_keys
endp
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 db
cr,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 ptr
cs:[stack_offset-shift],sp
mov word ptr
cs:[stack_seg-shift],ss
push cs
pop ss
mov
sp,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.
mov
dx,int_23h-shift
mov
di,int_23h_vect-shift
call
sethandler
mov al,24h ;
Встановити новий обробник прерывання Int24h.
mov
dx,int_24h-shift
mov
di,int_24h_vect-shift
call
sethandler
mov ah,15 ;
Визначити поточний відеорежим і
call
callvideo ; номер відеосторінки.
cmp al,2
je set_param
cmp al,3
je set_param
cmp al,7
jne
end_prepare ; Якщо графічний режим, то вихід.
set_param:
; Сохранити номер відеосторінки.
mov byte ptr
ds:[current_video_page-shift],bh
mov ah,03h
; Сохранити позицію курсору.
call
callvideo
mov word ptr
ds:[cursor_loc-shift],dx
test byte ptr
ds:[flags_offset],mask Sf
jz
begin_remove
call start
jmp short
restore_cursor
begin_remove:
call remove
restore_cursor:
mov bh,byte
ptr ds:[current_video_page-shift]
mov dx,word
ptr ds:[cursor_loc-shift] ; Восстановити
mov ah,2
; положення курсору.
call
callvideo
end_prepare:
mov al,23h
; Восстановити вектор преривання Int 23h.
mov
di,int_23h_vect-shift
call
resethandler
mov al,24h
; Восстановити вектор преривання Int 24h.
mov
di,int_24h_vect-shift
call
resethandler
pop es ;
Восстановити регістри.
pop ds
pop bp
pop si
pop di
pop dx
pop cx
pop bx
pop ax
cli ;
Переключитись на стек прерваної програми.
mov ss,word
ptr cs:[stack_seg-shift]
mov sp,word
ptr cs:[stack_offset-shift]
ret
prepare endp
stack_offset dw ?
stack_seg dw ?
cursor_loc dw ?
current_video_page
db ?
;*******************
Кінець файлу PREPARE.ASM *************************
; Файл MAIN.ASM
; Модуль основної
програми
;*************************************************************
start proc
mov bp,sp
; Зарезервирувати місто
sub sp,13
; в пам`яти для змінних.
mov byte ptr
ds:[flag-shift],0 ; Обнулить всі прапорці.
mov byte ptr
ds:[fl2-shift],0
mov byte ptr
ds:[xx-shift],dl
mov byte ptr
ds:[yy-shift],dh
rd:
call kurpos
; Встановити курсор.
call delay
; Визвать затримку.
in al,60h
; Взяти символ.
cmp al,14
; BackSpace ?
jne nn
; Якщо ні - далі.
or byte ptr
ds:[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 ptr
ds:[yy-shift],0 ; Перевірити позицію курсора.
jne n00
mov byte ptr
ds:[yy-shift],25
jmp n00
rd1:
call keybuf
jmp rd
n00:
dec byte ptr
ds:[yy-shift] ; Уменьшить Y на 1.
call kurpos
; Встановити курсор.
n1:
cmp al,80
; DOWN ?
jne n2
; Якщо ні - далі.
cmp byte ptr
ds:[yy-shift],25 ; Перевірити позицію курсору.
jne n11
mov byte ptr
ds:[yy-shift],0
n11:
inc byte ptr
ds:[yy-shift] ; Увеличити Y на 1.
call kurpos
; Встановити курсор.
n2:
cmp al,75
; LEFT ?
jne n3
; Якщо ні - далі.
cmp byte ptr
ds:[xx-shift],0 ; Преревірити позицію курсору.
jne n22
mov byte ptr
ds:[xx-shift],80
dec byte ptr
ds:[yy-shift]
n22:
dec byte ptr
ds:[xx-shift] ; Уменьшить X на 1.
call kurpos
; Встановити курсор.
n3:
cmp al,77
; RIGHT ?
jne n4
; Якщо ні - далі.
cmp byte ptr
ds:[xx-shift],80 ; Перевірити позицію курсору.
jne n33
mov byte ptr
ds:[xx-shift],0
inc byte ptr
ds:[yy-shift]
n33:
inc byte ptr
ds:[xx-shift] ; Увеличить X на 1.
call kurpos
; Встановити курсор.
n4:
cmp al,1
; ESC ?
jne rd1
; Якщо ні - далі.
cmp byte ptr
ds:[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
mov
al,es:[41ah] ; Взяти кінець буферу
mov
es:[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 ptr
ds:[flag-shift],0
je nh
mov al,byte
ptr ds:[wx-shift]
cmp byte ptr
ds:[xx-shift],al
jne lab
mov al,byte
ptr ds:[wy-shift]
cmp byte ptr
ds:[yy-shift],al
je rr
lab:
call labela
; Виділити.
jmp rr
nh:
mov al,byte
ptr ds:[xx-shift]
mov byte ptr
ds:[x1-shift],al
mov al,byte
ptr ds:[yy-shift]
mov byte ptr
ds:[y1-shift],al
rr:
pop ax
mov byte ptr
ds:[flag-shift],1
ret
here endp
kurpos proc
; Встановлює
курсор.
push ax
mov ah,02h
mov dh,byte
ptr ds:[yy-shift]
mov dl,byte
ptr ds:[xx-shift]
mov bh,0
call
callvideo
pop ax
ret
kurpos endp
labela proc
; Змінює колір
поміченого тексту.
cmp byte ptr
ds:[fl2-shift],0
je f0
call unlabel
call ifswap
jmp f1
f0:
mov al,byte
ptr ds:[x1-shift]
mov byte ptr
ds:[wx-shift],al
mov al,byte
ptr ds:[y1-shift]
mov byte ptr
ds:[wy-shift],al
call ifswap
f1:
mov byte ptr
ds:[fl2-shift],1
mov al,byte
ptr ds:[x1-shift]
mov byte ptr
ds:[tx-shift],al
mov al,byte
ptr ds:[y1-shift]
mov byte ptr
ds:[ty-shift],al
hh:
push cx
push dx
mov ah,02h ;
Змінити позицію курсору.
mov dh,byte
ptr ds:[ty-shift]
mov dl,byte
ptr ds:[tx-shift]
mov bh,0
call
callvideo
mov ah,08h ;
Считати символ/атрибут.
mov bh,0
call
callvideo
mov byte ptr
ds:[scrr-shift],ah
mov ah,09h ;
Записати символ з ізмененим атрибутом.
mov bl,byte
ptr ds:[scrr-shift]
add bl,15
mov cx,1
mov bh,0
call
callvideo
pop dx
pop cx
mov dl,byte
ptr ds:[tx-shift]
cmp dl,byte
ptr ds:[xx-shift]
je ok
as:
inc byte ptr
ds:[tx-shift]
cmp byte ptr
ds:[tx-shift],80
jne hh
mov byte ptr
ds:[tx-shift],0
inc byte ptr
ds:[ty-shift]
jmp hh
ok:
mov al,byte
ptr ds:[yy-shift]
cmp byte ptr
ds:[ty-shift],al
je rro ;
Якщо кінець, то вийти,
jmp as ;
інакше оброблювати наступний символ.
rro:
mov al,byte
ptr ds:[xx-shift]
mov byte ptr
ds:[wx-shift],al
mov al,byte
ptr ds:[yy-shift]
mov byte ptr
ds:[wy-shift],al
ret
labela endp
unlabel proc
; Встановлює
колір поміченого тексту.
push ax
push dx
push cx
mov al,byte
ptr ds:[x1-shift]
mov byte ptr
ds:[tx-shift],al
mov al,byte
ptr ds:[y1-shift]
mov byte ptr
ds:[ty-shift],al
tl:
mov ah,02h
; Змінити позицію курсору.
mov dh,byte
ptr ds:[ty-shift]
mov dl,byte
ptr ds:[tx-shift]
mov bh,0
call
callvideo
mov ah,08h
; Считати символ/атрибут.
mov bh,0
call
callvideo
mov byte ptr
ds:[scrr-shift],ah
call ToPrn
mov ah,09h
; Записати символ з востановленим атрибутом.
mov bl,byte
ptr ds:[scrr-shift]
sub bl,15
mov cx,1
mov bh,0
call
callvideo
mov al,byte
ptr ds:[wx-shift]
cmp byte ptr
ds:[tx-shift],al
je don
nt:
inc byte ptr
ds:[tx-shift]
cmp byte ptr
ds:[tx-shift],80
jne tl
call PrnEnt
mov byte ptr
ds:[tx-shift],0
inc byte ptr
ds:[ty-shift]
jmp tl
don:
mov al,byte
ptr ds:[wy-shift]
cmp byte ptr
ds:[ty-shift],al
je ex ;
Якщо кінець, то вийти,
jmp nt ;
інакше оброблювати наступний символ.
ex:
pop ax
pop cx
pop dx
ret
unlabel endp
ToPrn proc
; Печатает
символ.
test byte ptr
ds:[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 ptr
ds:[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,byte
ptr ds:[y1-shift] ; Порівняти координати Y1 и YY
cmp al,byte
ptr ds:[yy-shift]
jg zq
jl qw
mov al,byte
ptr ds:[x1-shift] ; Порівняти координати X1 и XX
cmp al,byte
ptr ds:[xx-shift]
jng qw
zq:
; Якщо треба змінити,
mov al,byte
ptr ds:[yy-shift] ; змінюєм.
mov byte ptr
ds:[y1-shift],al
mov al,byte
ptr ds:[xx-shift]
mov byte ptr
ds:[x1-shift],al
mov al,byte
ptr ds:[wx-shift]
mov byte ptr
ds:[xx-shift],al
mov al,byte
ptr ds:[wy-shift]
mov byte ptr
ds:[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
mov
di,test_vector-shift
mov al,09h
; Перевірити вектор преривання Int09h.
mov
dx,int_09h-shift
call di
jne
not_remove
mov al,2fh
; Перевірити вектор преривання Int2fh.
mov
dx,int_2fh-shift
call di
jne
not_remove
mov al,28h
; Перевірити вектор преривання Int28h.
mov
dx,int_28h-shift
call di
jne
not_remove
mov al,08h
; Перевірити вектор преривання Int08h.
mov
dx,int_08h-shift
call di
je uninstall
not_remove:
mov
ax,notremove_mess-shift
push ax
push ax
call mess
ret
uninstall:
mov
ax,remove_mess-shift
push ax
xor ax,ax
push ax
call mess
mov
cx,resethandler-shift
mov al,09h
; Восстановити вектор преривання Int09h.
mov
di,int_09h_vect-shift
call cx
mov al,2fh
; Восстановити вектор преривання Int2fh.
mov
di,int_2fh_vect-shift
call cx
mov al,28h
; Восстановити вектор преривання Int28h.
mov
di,int_28h_vect-shift
call cx
mov al,08h
; Восстановити вектор преривання Int08h.
mov
di,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
mov
di,code_table-shift ; Загрузити сміщення
mov
si,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
call
callvideo
mov ah,8
call
callvideo
cmp dh,15
jb lab_1
cmp dl,27
jb exch_noth
jmp short
exch_attr
lab_1:
cmp dh,11
jb lab_2
cmp dl,52
ja exch_attr
jmp short
exch_code
lab_2:
cmp dl,52
ja exch_noth
exch_code:
xchg al,byte
ptr [di] ; Заменити код символа.
inc di
exch_attr:
xchg ah,byte
ptr [si] ; Заменити атрибут.
inc si
exch_noth:
mov bl,ah
; Вивести символ.
mov cx,1
mov ah,9
call
callvideo
inc dx
pop cx
loop loop_2
inc dh
pop cx
loop loop_1
mov dx,1900h
; Убрати курсор.
mov ah,02h
call
callvideo
ret
; Вийти з процедури.
xchgmess endp
mess proc
push bp
mov bp,sp
push bx
mov bh,byte
ptr ds:[current_video_page-shift]
mov bl,byte
ptr ds:[attribute_table-shift]
push bx
; Вивести вікно повідомлення.
call xchgmess
pop bx
mov dx,0b29h
; Вивести текст повідомлення.
mov si,word
ptr [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
loop
mess_loop
pop bx
wait_mess:
mov ah,0
; Ждати натиснення клавиши.
int 16h
call xchgmess
; Восстановити екран.
pop bx
pop bp
ret 4
; Вийти з процедури.
mess endp
; Таблиця
атрибутів вікна повідомлення.
attribute_table
db 29 dup(4eh),14 dup (206),13 dup (4eh)
db
07h,07h
db 28 dup
(4eh)
db
07h,07h
db 4eh,26
dup (206),4eh
db
07h,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
; Встановити курсор в нужну позицию.
call
callvideo
lodsb
or al,al
; Якщо зустрився кінець строки,
jz
end_typestr ; то вихід.
mov cx,1
mov ah,9
call
callvideo
inc dx
; Определити позицію для вивода
jmp short
typestr_loop ; следуючого символу.
end_typestr:
push dx
; Убрати курсор.
mov dx,1900h
mov ah,2
call
callvideo
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:
loop
speaker_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 ;
Якщо кінець строки, то вихід.
je
end_teletype
call
callvideo ; Вивести символ.
jmp short
type_next_char
end_teletype:
ret
teletype endp
;********************
Кінець файлу TELETYPE.ASM **********************
|