Лабораторна робота №1 - Ввід інформації з клавіатури. Обмін інформації з файлами засобами мови Turbo C

Назва роботи: Ввід інформації з клавіатури

Мета роботи: Ознайомитись з можливостями організації вводу з клавіатури в комп'ютерах сімейства ІВМ РС.

Загльні положення

Ввід інформації в комп'ютер може бути виконаний на трьох рівнях:

Зверненням до функцій операційної системи (МS DOS);

Зверненням до функцій BIOS;

Фізичним безпосереднім доступом до апаратних засобів.

Перший рівень дозволяє пропускати клавіатурний ввід через через інста - льованні драйвери, забезпечує контроль за клавішами Crtl-C ( Crtl-Break) та стандартну для операційної системи обробку помилок.

Другий рівень дозволяє програмі слідкувати за натиском усіх, а не тільки символьних клавіш, виконувати керування апаратурою клавіатури і інш. Третій рівень - ( безпосередній доступ до буферу клавіатури )значно підвищує продуктивність програми. В деяких випадках необхідна імітація натиску клавіш клавіатури з записом кодів безпосередньо у буфер. При цьому фізично натиск клавіш не відбивається. Так будуються, наприклад, демонстрційні програми.

Коротко зупинимось на апаратних засобах персонального комп'ютера для вводу з клавіатури. Клавіатура вміщує вбудований мікропроцесор. Він при кожному натисканні клавіші визначає її порядковий номер ( скенд-код ) і розміщує його в порт спеціальної електронної схеми - програмованого переферійного інтерфейсу (ППІ). Скенд-код у перших 7 бітах вміщує порядковий номер натиснутої клавіши, а восьмий біт дорівнє "о", якщо клавіша була натиснута (прямий скенд-код), та дорівнює "1",якщо клавіша

Була відпущена (зворотній скенд-код). Коли скенд-код записаний у порт 60h, схема ППІ видає сигнал "підтвердження" повідомляючи мікропроце - сор клавіатури про те, що код прийнято.

Якщо клавіша натиснута довше деякого часу затримки ( delay value ), мікропроцесор клавіатури починає генерувати з заданою частотою (typenic) прямий скенд-код натиснутої клавіші. Коли скенд-код прийнятий схемою ППІ, аппаратура комп'ютера генерує переривання 9.Стандартний обробник переривання 9 - це програма, що входить до BIOS ISR аналізує скенд-код, та по спеціальним правилам перетворює його ( ISR - Interrupt Servise Routine - програма обслуговування переривання ).

Буфер BIOS для запису кодів клавіш займає 32 байта пам'яті з адреси 40:1ЕН (1086 в 10 с/г). Запис йнформації до буферу виконує ISR BIOS переривання 9, читаня - функції ISR BIOS переривання 16Н. Буфер клавіатури розрахований на 15 натискань клавш, що генерують двохбайтні коди, і тому має 30 байт для кодів клавіш та два додаткових байта, які резервуються під двохбайтовий код для клавіші ENTER.

Буфер організовується як кільцева черга, доступ до якої виконується за допомогою покажчика "голови" (head-pointer),адреса якого 40:1АН ( 1050 в с/г), та покажчика "хвоста" (tail pointer) адреса якого 40:1СН(1052 в с/г). Значення, що записані у покажчиках дорівнюють зміщення до слова, де буде записаний обробником переривання 9 код клавіші, що буферизується, т. т. перше вільне слово буфера.

Покажчик "годови" задає зміщення слова, яке буде повернуте запиту буферизованого вводу з клавіатури, зробленого операційного системою або BIOS.

Буфер для клавіатури - це класичний приклад використання кільцевого кільцевого буферу для органіції асихронної взаємодії програм за схемою "виробник-споживач". Одна з програм (ISR BIOS переривання 9)"виробляє" інформацію, тобто, вона є процесом-виробником. Програма, що виконується, через функцію АН=00Н переривання 16Н BIOS "споживає" інформацію, тобто є процесом-споживачем. Асинхронність взаємодії означає що запис до буферу нової їнформації та читання з нього відбувається у випадкові, не зв'язані моменти часу. Тому що "виробник" постійно аналізує наявність переповнення буферу, не відбувється перевизначення не прочитаних ще "споживачем" кодів клавіатури. Тобто при переповненні буферу "виробник" блокується до того часу, доки "споживач" не прочитає одне або декілька слів з буферу. Якщо ж буфер пустий і виконується спроба читання інформації, функція АН=00Н переривання 16Н BIOS переходить до безконечного циклу, умовою якого є нерівність між собою покажчиків "голови" і "хвоста". Фактично, біжуча програма, що виконує ввід з клавіатури, блокується, не даючи "споживати" неіснуючу ще інформацію.

Перший рівень вводу з клавіатури

Послідовність дій системи при вводі з клавіатури така:

Функція MS-DOS викликає драйвер клавіатури, передаючи йому запит

На ввід одного символу з буферу клавіатури;

Драйвер, виконуючи запит, звертається до потрібної функції перерива-

Ння 16Н BIOS;

ISR BIOS переривання 16Н читає з буферу клавіатури потрібне слово

Та передає його в драйвер;

Драйвер повертає байт (звичайно молодший) в MS-DOS.

Таким чином, функції MS-DOS та функції бібліотеки Turbo C, що спираються на них, слабо залежать від особливостей апаратури, оскільки система ізольована від неї двома шарами програмного забезпечення -

Драйверами та BIOS.

Для вводу з клавіатури використовується такі функції MS-DOS:

АН = 01Н - ввід з очікуванням з стандартного пристрою вводу (клавіатури);

АН = 06Н - ввід-вивід з консолі;

АН = 07Н - ввід з консолі з очікуванням без "відлуння" на екран;

АН = 08Н - подібна до попередньої, крім реакції на натискання Crtl-Break (викликається переривання 23Н);

АН = ОАН - буферизований ввід рядка з консолі;

АН = ОВН - перевірка стану стандартного вводу;

АН = ОСН - ввід з клавіатури з чисткою буфера;

АН = 3FH - функція префіксного читання з файлу або пристрою.

Бібліотечні функції Turbo C для роботи з файлами можна поділити на дві

Групи: потокові та префіксні. Потокові функції виконують додаткову буферизацію інформації, що приводить до подвійної буферизації інфор-

Мації: на рівні бібліотечної функції та на рівні MS-DOS. Префіксні

Функції не виконують додаткову буферизацію, а одразу звертаються до

Префіксних функцій MS-DOS. Початкові функції більш ефективні при

Перенесенні інформації між файлом та Сі-програмою по символам та рядкам. Префіксні функції - блок-орієнтовані функції і їх використа ння дає виграш в продуктивності при перенесені одразу цілої групи байтів за одне звертання до функції. Розглянуті функції MS-DOS для вводу з клавіатури можна викликати одразу з Сі-програми через такі функції Тurbo C, як geninterrupt(), int86(), intr(), та інші, або нявно функціями вводу Turbo C. Bелика група функцій Turbo C для вводу з клавіатури - це функції потокового та префіксного вводу. Використовуючи функції вводу, прототипи яких розміщені у файлі stdio. h, неможливо виконати, наприклад, не відображення символів і т. ін. Для виконання таких дій використовуються функції Turbo C, прототипи яких розміщені у файлі conio. h. Вони, як правило розраховані на побудову найпростішого віконного інтерфейсу.

Приклад використання функцій cgets()*L7-1.C*,функцій gets() та getsh() *L7-2.C*, getpass() - *L7-3.C*, ungetch() - *L7-4.C*

Другий рівень вводу з клавіатури

Інтерфейсом програм у персональному комп'ютері з клавіатурою є переривання 16Н BIOS.

Його функції такі:

АН=00Н - читання з очікуванням двохбайтового коду з буферу клавіатури

АН=01Н - читання без очікування двох байтового коду з буферу клавіа...;

АН=02Н - визначення стану шифра тригерних клавіш;

АН=03Н - установка затримки та частоти повторення ;

АН=04Н - запис до буферу клавіатури двохбайтового коду клавіші ( ця

Функція не має аналогів у бібліотеці Turbo C ).

Функції Аh=00-02H є аналогами функції 00-02Н, але для клавіатур з 102/102 клавішами. Приклади використання функції enter-kb-BIOS ( ) - *L7-5.C*,

*L7-6.C*.

Функція АН=00-02Н переривання 16Н BIOS покладенні в основу функції bioskey( ) бібліотеки Turbo C. Приклади її використання - *L7-7.C*

Третій рівень вводу з клавіатури.

Для багатьох професійних програм необхідним є безпосереднім доступ до буферу клавіатури. Для функції цього типу існує власний заголовочний

Файл kb. р. Це такі функції:

Clear-kb ( ) - очищення буферу клавіатури;

Gets-kb ( ) - очищення буферу клавіатури та ввід з очікуванням двохбайтового коду натискання клавіші;

Key-kb ( ) - читання двохбайтового коду натискання клавіші;

Gets-kb ( ) - розширене визначення стану шифт - та тригерних клавіш

На момент виклику функції;

Sets-kb ( ) - розширена установка стану шифт - та тригерних клавіш;

Enter-kb ( )- запис безпосередньо до буферу клавіатури коду натискання клавіш.

Приклади використання функцій - *L7-8.C*, *L7-9.C*, *L7-10C*, *L7-11.C*,

*L7-12.C*,*L7-13.C*

Порядок виконання роботи

    1. В середовищі MS-DOS ініціалізувати одну з систем програмування Turbo C, Turbo C++, Boorland C++. 2. Відкомпілювати та виконати один або декілька вказаних вказаних викладачем прикладів (Всі приклади з ВООК/2). 3. Модифікувати вказаний приклад (або приклад ) певний чином. Виконати модифікований приклад. 4. Зробити висновки з особливостей функціонування тих або інших програмних засобів вводу інформації з клавіатури.

Результат виконання роботи:

#include <stdio. h>

#include <conio. h>

#include <ctype. h>

Void main(){

Char string[80];

Char * str, ch, * password;

Int c, i, extended;

//cgets()

String[0] = 81;

Printf(" 1. Function cgets() ");

Printf("Input some chars:");

Str = cgets(string);

Printf(" cgets read %d characters: "%s" ", string[1], str);

Printf("The returned pointer is %p, string[0] is at %p ", str, &;string);

//gets()

Printf(" 2. Function gets() ");

Printf("Input a string:");

Gets(string);

Printf("The string input was: %s ", string);

//getch()

Extended = 0;

Printf(" 3. Function getch() ");

Printf("Enter any character: ");

C = getch();

If (!c){

Extended = getch();

Printf(" Special key. Extended scan-cod %#u ", ch);

}

Else {

Printf(" Symbol key %c (ASCII-cod %#u) ", ch, ch);

}

//getpass()

Printf(" 4. Function getpass() ");

Password = "x04x0Ex1Cx0Ex1Bx04x06";

Str = getpass("Enter password (8 symbols):");

While(*password)

If(*str++ != (*password++ ^ 0x4f)){

Puts("aWrong password. ");

Cprintf("The password is: %s ", password);

}

Puts("Correct password. ");

//ungetch()

I = 0;

Printf(" 5. Function ungetch() ");

Puts("Input an integer followed by a char:");

While((ch = getche()) != EOF &;&; isdigit(ch))

I = 10 * i + ch - 48;

If (ch!= EOF) ungetch(ch);

Printf(" i = %d, next char in buffer = %c ", i, getch());

}

#include <dos. h>

#include <bios. h>

#include <stdio. h>

#include <conio. h>

Int enter_kb_BIOS(unsigned key_code){

Struct REGPACK r;

R. r_cx = key_code;

R. r_ax = 0x0500;

Intr (0x16, &;r);

Return r. r_ax &; 0x00ff;

}

Void main(){

Char BIOS_key_cur, BIOS_key_old, BIOS_key;

Char * icons[] =

{

"Right Shift:", "Left Shift :", "Ctrl :",

"Alt :", "ScrollLock :", "NumLock :",

"CapsLock :", "Ins :", 0,

};

Int index = 0, x, y;

//enter_kb_BIOS()

If (!enter_kb_BIOS('a')) printf("Successfuly loaded into keyboard buffer ");

Else printf("Keyboard buffer is full ");

Printf(" Read from buffer: %c ",getche());

Printf("Press any key to continue... ");getche();

//bioskey()

Clrscr();

While(icons[index]) puts(icons[index++]);

BIOS_key_old = bioskey(2);

BIOS_key_old = ~BIOS_key_old;

While(!((bioskey(1) &; 0xff00) == 0x1000)){

Y = 1;

BIOS_key_cur = BIOS_key = bioskey(2);

For(index = 0; index < 8; index++){

X = 14;

Gotoxy(x, y);

If((BIOS_key &; 0x01) != (BIOS_key_old &; 0x01))

If(BIOS_key &; 0x01){

Textattr(BLACK | (LIGHTGRAY << 4));

Cputs("on ");

}

Else{

Textattr(LIGHTGRAY | (BLACK << 4));

Cputs("off");

}

BIOS_key >>= 1;

BIOS_key_old >>= 1;

Y++;

}

BIOS_key_old = BIOS_key_cur;

}

Bioskey(0);

}

#include <stdio. h>

#include <dos. h>

#include "kb. h"

Int enter_kb_BIOS(unsigned key_code){

Struct REGPACK r;

R. r_cx = key_code;

R. r_ax = 0x0500;

Intr (0x16, &;r);

Return r. r_ax &; 0x00ff;

}

Void clear_kb(void){

Char register _es * tail = (char _es *) TAIL_PTR, _es * head = (char _es *) HEAD_PTR;

Disable();

_ES = 0x40;

* tail = * head;

Enable();

}

Unsigned int getc_kb(void){

Register ret_ax = 0;

_AX = 0x0C01;

Geninterrupt(0x21);

Ret_ax = _AL;

If(!ret_ax){

_AH = 0x01;

Geninterrupt(0x21);

Ret_ax = _AL;

Return ret_ax << 8;

}

Return ret_ax;

}

Unsigned key_kb(void){

Register char _es * tail = (char _es *) TAIL_PTR;

Register char _es * head = (char _es *) HEAD_PTR;

_ES = 0x40;

If(* head == * tail) return 0;

Disable();

Tail = (char _es *) (* head);

Enable();

Return * (unsigned _es *) tail;

}

Void getsh_kb(unsigned * old_status){

Unsigned _es * shift_address = (unsigned _es *) 0x17;

Disable();

_ES = 0x40;

* old_status = * shift_address;

Enable();

}

Void setsh_kb(unsigned * new_status){

Unsigned _es * shift_address = (unsigned _es *) 0x17;

Disable();

_ES = 0x40;

* shift_address =* new_status;

Enable();

}

Enter_kb(int where, unsigned key_code){

Unsigned register _es * tail = (unsigned _es *) TAIL_PTR, _es * head = (unsigned _es *) HEAD_PTR, _es * tmp, ret;

_ES = 0x40;

Disable();

Switch(where){

Case KB_HEAD:

Tmp = (unsigned _es *) * head;

Tmp--;

If(tmp < (unsigned _es *) KB_BUFFER_START)

Tmp = (unsigned _es *) (KB_BUFFER_END - 2);

If(tmp == (unsigned _es *) * tail){

Ret = FULL;

Break;

}

Else{

    * (unsigned _es *) tmp = key_code; * head = (unsigned) tmp;

Ret = OK;

Break;

}

Case KB_TAIL:

Tmp = (unsigned _es *) * tail;

If(tmp == (unsigned _es *) KB_BUFFER_END)

Tmp = (unsigned _es *) KB_BUFFER_START;

If(tmp + 1 == (unsigned _es *) * head){

Ret = FULL;

Break;

}

Else{

* (unsigned _es *) tmp = key_code;

Tmp ++;

* tail = (unsigned) tmp;

Ret = OK;

Break;

}

Default:

Ret = ERROR;

}

Enable();

Return ret;

}

Void main(){

Unsigned stat, errorlevel;

//clear_kb()

Printf(" Function clear_kb() ");

Printf("Clearing keyboard buffer...");

Clear_kb();

Printf("done ");

//getc_kb()

Printf(" Function getc_kb() ");

Printf("Enter any key: ");

Printf(" Scan code: %X ",getc_kb());

//key_kb()

Printf(" Function key_kb() ");

Printf("Writing in key buffer char 'Z'..."); enter_kb_BIOS('Z');printf("done ");

Printf("Reading: %c ",key_kb());

Printf("Reading again: %c ",key_kb());

//getsh_kb

Printf(" Function getsh_kb(old_status)");

Getsh_kb(&;stat);

Printf(" Shift-Trigger Byte: %X ",stat);

//setsh_kb

Printf(" Function setsh_kb(new_status)");

Printf(" Setting new Shift-Trigger Byte ");

Setsh_kb(&;stat);

//enter_kb

Printf(" Function enter_kb(where, key_code);");

Errorlevel=enter_kb(KB_HEAD, 'A');

Printf(" Writing to key buffer char 'A' with left shifting of key head Errorlevel=%x - ",errorlevel);

If (errorlevel==0) {printf("( OK )"); }

If (errorlevel==1) {printf("( FULL )"); }

If (errorlevel==2) {printf("( ERROR )");}

}

Похожие статьи




Лабораторна робота №1 - Ввід інформації з клавіатури. Обмін інформації з файлами засобами мови Turbo C

Предыдущая | Следующая