globus_ussr
Member | Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору Работой клавиатуры управляет электронная схема, называемая контроллером клавиатуры. В его функции входит распознавание нажатой клавиши и помещение закреплённого за ней кода в выходной регистр (порт) с номером $60. Поступающий в порт код клавиши называется скан-кодом и является в некотором роде её порядковым номером. При этом каждой клавише соответствуют два скан-кода, отличающиеся на 128. Меньший код (код нажатия) засылается в порт $60 при нажатии клавиши, больший код (код отпускания) – при отпускании клавиши. Такая система позволяет, например, в случае, когда буквенная клавиша удерживается в нажатом состоянии (т.е. поступил код нажатия, но в течение некоторого интервала времени не поступило кода отпускания) перейти в режим генерации многократного кода нажатия. Каждое нажатие и каждое отпускание клавиши вызывает сигнал аппаратного прерывания, заставляющий процессор прервать выполняемую программу и перейти на программу обработки прерывания (ПОП) от клавиатуры, которая вызывается через вектор $09 (её часто называют программой INT $09). Программа INT $09 работает, кроме порта $60, ещё с двумя областями оперативной памяти: с кольцевым буфером ввода (адреса от $40:$1E до $40:$3D), куда в конце концов помещаются коды ASCII нажатых клавиш, и словом состояния (или словом флагов) клавиатуры (адрес $40:$17), где фиксируется состояние управляющих клавиш (<Shift>, <Ctrl>, <Caps Lock> и др. – см. рисунок). Программа INT $09, получив управление в результате прерывания от клавиатуры, считывает из порта $60 скан-код и анализирует его значение. Если он принадлежит управляющей клавише и представляет собой код нажатия, то в слове флагов клавиатуры устанавливается флаг, соответствующий нажатой клавише (например, при нажатии <Right Shift> устанавливается бит 0, при нажатии <Left Shift> – бит 1, <Ctrl> – бит 2, <Alt> – бит 3). Если управляющая клавиша отпускается, соответствующий ей бит сбрасывается в 0. При нажатии любой другой клавиши программа INT $09 считывает из порта $60 её скан-код нажатия и по таблице трансляции скан-кодов в коды ASCII формирует двухбайтовый код, старший байт которого содержит скан-код, а младший – код ASCII. При этом скан-код характеризует клавишу, а ASCII-код определяет закреплённый за ней символ. Поскольку за каждой клавишей закреплено по нескольку символов (не менее двух), то каждому скан-коду соответствует несколько ASCII-кодов. При формировании двухбайтового кода программа INT $09 анализирует состояние флагов. Например, клавише <Q> соответствует скан-код $10 (десятичное 16), ASCII-код буквы Q – $51 (81), буквы q – $71 (113). Если <Q> нажата при нажатой клавише <Shift>, то будет сформирован двухбайтовый код $1051, иначе – код $1071. Если предварительно была нажата клавиша <Caps Lock>, то результат будет обратным (включенный режим <Caps Lock> аннулирует последующее нажатие <Shift>). При формировании двухбайтовых кодов некоторым специальным клавишам (например, F1 – F10, <Home>, <End>, <>, <> и т.п.) в таблице трансляции, с которой работает программа INT $09, соответствует нулевой код ASCII. Двухбайтовые коды, имеющие нулевой младший байт, называются расширенными кодами ASCII и используются для управления программами. Полученный в результате трансляции двухбайтовый код засылается программой INT $09 в кольцевой буфер клавиатуры, объем которого составляет 15 машинных слов. Коды символов извлекаются из буфера по принципу FIFO. За состоянием буфера следят два указателя: в хвостовом указателе (слово по адресу $40:$1C) хранится адрес первой свободной ячейки, в головном указателе ($40:$1A) – адрес самого старого кода, принятого с клавиатуры и ещё не востребованного программой. Когда буфер пуст, оба указателя указывают на его первую ячейку. В ходе заполнения буфера хвостовой указатель смещается (по 2 байта) до последнего адреса и вновь возвращается на начало – и так далее по кольцу. Аналогично перемещается головной указатель при считывании кодов. Если при заполнении буфера не происходит считывания поступивших в него кодов (readkey), то при вводе более 16 символов приём новых кодов блокируется, и последующие нажатия на клавиши сопровождаются предупреждающими звуковыми сигналами (переполнение буфера). Для считывания кода нажатой клавиши выполняемая программа вызывает прерывание INT $16, которое активизирует драйвер клавиатуры BIOS. Драйвер считывает из буфера коды, смещая при этом головной указатель; таким образом, программный запрос на ввод с клавиатуры выполняет приём кода не прямо с клавиатуры, а из кольцевого буфера. |