НОУ ІНТУІТ, Лекція, Введення з клавіатури
Пряме введення-виведення "на середньому рівні" дозволяє вводити і виводити текстові символи у файл, на консоль, модем, віддалений термінал. При цьому в MS-DOS він організований за допомогою механізму переривань. Для ілюстрації "Прямого введення" будуть наведені функції прямого введення з консолі мовами Асемблер і Сі.
5.1. Вступ. Загальні відомості про клавіатуру
Клавіатура - це не просто "дошка з клавішами" (дослівний переклад англійської назви "keyboard"). Крім механічної частини (власне клавіш і контактів) вона включає складну топологію провідників, і навіть власний мікропроцесор - контролер .
Завдання, які вирішується цим мікропроцесором, такі:
- реагувати на натискання клавіш або комбінації клавіш;
- Реагувати на "тривале" натискання на клавішу та здійснювати відповідні дії;
- За положенням клавіш генерувати спеціальний скен-код клавіші (див. розділ 5.1.1);
- Відповідно до "таблиці символів" (codepage) перетворювати скен-код клавіші в ASCII символ, їй відповідної;
Примітка: деякі "сірі" (керуючі) клавіші не генерують символи, а використовуються лише для керування комп'ютером. У цьому випадку для них символ ASCII не генерується (записується в 0).
Бачите, як все складно. Тепер розберемося з рештою.
5.1.1. Поняття про скен-код клавіш
При натисканні кнопки на клавіатурі генерується її скен-код. Скен-код можна вважати "номером кнопки" на клавіатурі. Однак, це не зовсім так. Наприклад, якщо скен код клавіші"F10"дорівнює "68", то той же код клавіші з натиснутою клавішою"Shift"дорівнюватиме "93", з клавішею"Ctrl "- "103", а з клавішею"Alt"- "113".
Існують так звані"алфавітно-цифрові" ("білі") та "керуючі" ("сірі") клавіші. Перші генерують скен-код та ASCII символи. Другі генерують лише розширений скен-код, а в полі "ASCII символу" стоїть нуль. Завдяки цьому програміст легко може зрозуміти, як обробляти код клавіші: чи виводити символ на екран або запускати послідовність дій, що управляє.
Докладніше про скен-код клавіш дивися [1, 8, 33].
5.1.2. "Ехоппечатати" символів
При введенні з клавіатури пари значень "Скен-код" - "ASCII символ" заноситься до клавіатури для її обробки на комп'ютері. При цьому на старих терміналах усі введені символи відображалися на екрані дисплея. Але, з появою персональних ЕОМ, з'ясувалося, що такий висновок ("Ехопічат") не завжди зручний. Що робити, якщо Ви вводите пароль, і Ви не хочете, щоб його прочитав з екрана? А що робити, якщо Ви використовуєте алфавітно-цифрову клавішу як керуючу (наприклад, при обробці меню)? У цьому випадку Вам допоможуть функції введення клавіатури без еходруку.
5.1.3. Клавіатурний буфер
Отриманий в результаті перетворень у контролері двобайтовий код надсилається в кільцевий буфер введення, який служить для синхронізації введення даних з клавіатури та прийому виконуваної програмою. Об'єм кільцевого буфера становить 15 слів (30 байт). При цьому буфер організований за принципом: "першим записаний - першим ліченим" (англійська абревіатура "FIFO"). При переповненні буфера нові коди до нього не надходять, а натискання клавіші викликає попереджувальні сигнали.
5.2. Основні функції для введення символів із клавіатури
5.2.1. Консольне введення в Асемблері
5.2.1.1. Очікування введення символу без еходруку
Функції 7 і 8 переривання 21H очікують на введення символу, якщо буферклавіатури порожній; Поява символу на екрані не відображається.
Різниця між цими функціями полягає в тому, що функція 8 розпізнає спеціальне поєднання клавіш"Ctrl+Break", а функція 7 ігнорує це поєднання клавіш.
В обох випадках функція повертає символ у регістрAL. ЯкщоALмістить ASCII 0, отримано розширений код. Повторіть виклик переривання з тими ж параметрами, іALз'явиться другий байт розширеного коду.
5.2.1.2. Очікування введення символу з еходруком
При введенні символів з еходруком відлуння символів видається на екран. При цьому символи "повернення каретки" та "забій" переводяться у відповідні переміщення курсору, а не відображаються як символи ASCII. Виведення луни здійснюється з поточної позиції на екрані. При цьому курсор після виведення зміщується на позицію праворуч, а після досягнення правої межі екрана - переносить висновок на новий рядок.
Функція 1 переривання 21H очікує введення символу з клавіатури, якщо буфер порожній, а потім виводить його на екран у поточну позицію курсора. Функція обробляє натисканняCtrl+Break. Введений символ зберігається в регістріAL. Якщо вмістALдорівнює ASCII 0, то для отримання розширеного коду повторіть переривання.
Приклад використання цієї функції аналогічний прикладу 5.1.
Функція 1 переривання 21H повністю ігнорує клавішуEsc. Клавіші табуляції інтерпретуються нормально. Клавіша"Backspace"зсуває курсор на одну позицію вліво, але не стирає символ у цій позиції. Клавіша"Enter"викликає переміщення курсору на першу позицію рядка (немає автоматичного перенесення на новий рядок).
5.2.1.3. Отримання рядка символів
Більшість мов програмування надаютьможливості для введення рядка символів. Вони використовують можливості введення символів з еходруком, поміщаючи автоматично введені символи буфер оперативної пам'яті. Звичайно ж, повинна бути виділена пам'ять, достатня для прийому символів рядка, і повинна записуватись довжина рядка під час введення. Якщо цього не зробити, то буде відмова системи типу "переповнення буфера", якою може скористатися зловмисник.
Функція 0AH переривання 21H дозволяє вводити рядок довжиною до 254 символів, видаючи відлуння термінал. Ця функція продовжує вводити символи доти, доки не натиснуто клавішу "повернення каретки" ("Enter").DS:DXвказує на рядок, куди поміщаються символи, що вводяться. При введенні першого байта цієї позиції повинен містити число байтів, що відводиться для цього рядка. Після того, як рядок введений, другий байт дає число реально введених символів. Сам рядок починається з третього байта.
Треба відвести достатньо пам'яті для рядка потрібної довжини плюс 2 байти для дескриптора рядка плюс 1 додатковий байт для символу "Повернення каретки". Код повернення каретки: ASCII 13 - вводиться як останній символ рядка, але не враховується в результаті, який функція поміщає в другий байт дескриптора.
Таким чином, для отримання 50 - символьного рядка треба відвести мінімум 53 байти пам'яті, і помістити в перший байт пам'яті рядки число ASCII 51. Після введення 50 символів другий байт дескриптора міститиме ASCII 50, а 53 байт відведеної пам'яті буде містити ASCII 13 .
У цій процедурі можна використати можливості редагування рядка MS-DOS. Натискання"Backspace"або"стрілка вліво"видаляє символ з екрана, не розміщуючи його в пам'яті. Працює кнопка табуляції, а розширені коди ігноруються. Допускаються порожні рядки(що містять лише символ ASCII 13). На дисплеї при досягненні правого краю екрана рядок, що вводиться, переноситься на наступний рядок дисплея, а при досягненні правого нижнього кута екран зсувається на рядок вгору. Якщо вводиться більше символів, ніж відведено для рядка, зайві символи ігноруються і вмикається звук динаміка.