Прерывание 21h: функции DOS для работы с буфером клавиатуры

воскресенье, 25 апреля 2010 г. Автор: Vadim 0 коммент.

Различные служебные функции DOS для работы с буфером клавиатуры (функции 01h, 06h, 07h, 08h, 0Ah, 0Bh и 0Ch) классифицируются прежде всего по трем критериям: ожидают ли они ввода или же, когда символ не получен, сообщают, что ввода нет; выдают ли они на экран дисплея эхо (введенный символ); и реагирует ли функция на ввод стандартного символа прерывания во время ее исполнения. (Напомним, что нажатие комбинации клавиш Ctrl-Break или Ctrl-C рассматривается как прерывание ограниченным числом стандартных функций DOS. Однако, начиная с версии 2.00, в DOS введена команда BREAK ON, которая дает указание DOS реагировать на ввод символа прерывания при всех обстоятельствах.)

Все функции ввода с клавиатуры получают введенный символ из буфера клавиатуры, размещенного в памяти компьютера, а не непосредственно из порта 60h интерфейса клавиатуры (из порта 60h скан-коды считываются прерыванием 09h, переводятся в коды символов и помещаются в буфер клавиатуры).

Функция 1 прерывания 21h: ввод символа с эхопечатью

Функция 01h ждет появления символа в буфере клавиатуры со стандартного устройства ввода и после приема символа помещает его в регистр AL. Другие функции, относящиеся к вводу символов с клавиатуры: 06h, 07h и 08h.

Примечание. В первой версии DOS стандартным устройством ввода всегда является клавиатура, а стандартным устройством вывода - экран дисплея. В последующих версиях DOS имеется возможность переадресации стандартного ввода и вывода на другие устройства, а также в файлы. DOS обрабатывает символы, поступающие от стандартного устройства ввода, одинаковым образом независимо от того, является ли их источником реальное устройство (такое, как клавиатура) или поток символов, переадресованный из файла.

Работа функции 01h происходит следующим образом. Нажатие клавиши, соответствующей одному из символов кода ASCII, приводит к записи соответствующего байта в регистр AL и немедленной выдаче символа данной функцией на экран (в позицию курсора). Нажатие клавиши, формирующей сигнал, не относящийся к оду ASCII, приводит к формированию двух байтов, которые могут быть получены путем двух последовательных обращений к данной функции.

Обычно функция 01h применяется для проверки принадлежности символа, соответствующего нажатой клавише, коду ASCII. Для этого производится проверка регистра AL. Если AL не равно 00h, то это символ кода ASCII. Если же AL=00h, то вы имеете дело с символом, не относящимся к коду ASCII; в этом случае следует повторить обращение к данной функции для получения псевдокода, соответствующего специальному действию клавиши. Как и в случае применения других средств DOS, предназначенных для ввода символов с клавиатуры, при использовании данной функции развернутый код символов набора ASCII оказывается недоступным, даже если соответствующие средства обслуживания клавиатуры системы ROM BIOS позволяют осуществить доступ к нему.

Функция 6 прерывания 21h: непосредственный ввод

и вывод с консоли

Функция 06h - это универсальная функция, объединяющая операции ввода с клавиатуры и вывода на дисплей. В версиях DOS, начиная со второй и выше, эта функция, как и другие, действует по отношению уже не к клавиатуре и дисплею, а к стандартным устройствам ввода и вывода (в качестве которых по умолчанию принимаются клавиатура и дисплей).

При реализации данной функции регистр AL используется для ввода, а регистр DL - для вывода. Если при вызове функции 06h в регистре DL находится значение FFh (в десятичной нотации 255), то при нажатии какой-либо клавиши эта функция поместит соответствующий ASCII-код в регистр AL и сбросит нулевой флаг; при отсутствии нажатия клавиши она установит нулевой флаг.

Если же вызвать функцию 06h при любом другом значении регистра DL, то будет выполнен вывод символа, соответствующего данному значению, на стандартное устройство вывода.

Функция 06h не ожидает ввода символа с клавиатуры и не осуществляет его эхопечати на экране. Кроме того, функция 06h не воспринимает сочетание клавиш Ctrl-C как прерывание программы (при использовании данного сочетания она помещает в регистр AL значение 03h, т.е. соответствующий данному значению ASCII-код).

Функция 7 прерывания 21h: непосредственный ввод

с консоли без эхопечати

Функция 07h ожидает ввода символа со стандартного устройства ввода и после ввода символа помещает его в регистр AL. Она не осуществляет эхопечати символа на экране и не воспринимает сочетание клавиш Ctrl-C как прерывание программы.

Функция 07h действует точно так же, как функция 01h: нажатие клавиши, относящейся к коду ASCII, приводит к немедленному занесению в регистр AL соответствующего байта; нажатие клавиши, не относящейся к коду ASCII, приводит к формированию двух байтов, которые могут быть получены двумя последовательными обращениями к функции 07h.

Функция 8 прерывания 21h:

ввод с консоли без эхопечати

Функция 08h ожидает ввода символа, не осуществляя эхопечати и прерывает программу при нажатии Ctrl-C.

Эта функция идентична функции 01h, за исключением того, что она не выводит введенный символ на экран дисплея (или стандартное устройство вывода).

Для более полного понимания особенностей данной функции обратитесь к описанию функции 01h. Сравните данную функцию с функциями 01h, 06h и 07h. Если вы хотите использовать функцию 08h, но не желаете ждать ввода символа, изучите функцию 0Bh, которая сообщает о готовности ввода. Изучите также функцию 0Ch, которая является модификацией данной функции.

Ярлыки: , ,

Буфер клавиатуры

Автор: Vadim 0 коммент.

 

Буфер клавиатуры имеет объем 32 байта и располагается в памяти начиная с адреса 0040:001E. Он может накапливать до 15 нажатий на клавишу, независимо от того, являются ли они однобайтными кодами ASCII или двухбайтными расширенными кодами - буфер отводит по два байта для каждого нажатия клавиши (последнее нажатие, которое может быть максимально 16-м по счету, зарезервировано для клавиши <Enter>, которая разрешает исполнение введенной с клавиатуры команды для командного процессора COMMAND.COM). Для однобайтных кодов первый байт содержит код ASCII, а второй - скан-код клавиши. Для расширенных кодов первый байт содержит 0, а второй номер расширенного кода. Этот номер обычно совпадает со скан-кодом клавиши, но не всегда, поскольку некоторые клавиши могут комбинироваться с клавишами сдвига для генерации различных кодов.

Буфер устроен как циклическая очередь, которую называют также буфером FIFO (первый вошел - первым ушел). Однако не имеется определенной ячейки памяти, в которой находилось бы всегда начало строки в буфере. Вместо этого два указателя хранят позиции головы и хвоста строки символов, находящейся в буфере в текущий момент. Указатель головы указывает на позицию, занятую первым символом в буфере, а указатель хвоста - на позицию, следующую за последним символом (т.е. на первую свободную). Новые нажатия клавиш запасаются в позициях, на которые указывает указатель хвоста (в более старших адресах памяти), и соответственно обновляется указатель хвоста. После того, как израсходованы старшие адреса в буфере, новые символы начинают вставляться в самые младшие ячейки буфера; поэтому возможны ситуации, когда хвост буфера имеет меньший адрес, чем голова. После того как буфер заполнен, новые вводимые символы игнорируются, при этом обработчик прерываний клавиатуры выдает гудок через динамик. В этот момент указатель хвоста указывает на ячейку перед головой в циклической очереди буфера (куда можно занести нажатие <Enter>). Наконец, когда оба указателя равны, то буфер пуст. Поэтому чтобы очистить буфер клавиатуры, достаточно установить указатели но одно и тоже значение. На рис.2 показаны некоторые возможные конфигурации данных в буфере.

Указатели на голову и хвост расположены по адресам 0040:001A и 0040:001C, соответственно. Хотя под указатели отведено 2 байта, используется только младший байт. Значения указателей меняются от 1Eh до 3Ch, что соответствует позициям буфера в области данных BIOS.

Чтобы разрешить ввод 15 символов требуется, как уже было сказано, 16-я пустая позиция, 2 байта которой всегда содержат код возврата каретки (ASCII 13) и скан-код клавиши <Enter>, равный 28. Они поступают в буфер по нажатию клавиши <Enter>. Эта пустая позиция непосредственно предшествует голове строки символов.

Ввод данных с клавиатуры

Автор: Vadim 0 коммент.

 

Ввод данных с клавиатуры реализован с использованием промежуточного буфера ввода - "буфера клавиатуры" (специальной области памяти): все набираемые на клавиатуре символы сначала попадают в этот буфер, и уже отсюда они затем будут считываться программами DOS. Это означает, что можно досрочно ввести много данных и они не пропадут. Например, если в программе осуществляется ввод по одному символу, то все равно можно сразу набрать много символов - затем они будут считываться из буфера по одному. Кроме того, при вводе допускается редактирование вводимого текста: при нажатии клавиши "стрелка влево" или Backspase уничтожается последний набранный символ, а при нажатии Esc уничтожается весь набранный текст (при работе COMMAND.COM редактирование возможно пока не нажата клавиша Enter; при нажатии Enter командный процессор исполняет введенную команду). Рассмотрим путь символов от клавиатуры до буфера ввода подробнее.

Клавиатура содержит встроенный микропроцессор, который воспринимает каждое нажатие или отпускание клавиши и выдает скан-код в порт A (60h) микросхемы контроллера клавиатуры, расположенной на системной плате. Скан-код - это однобайтное число (в определенных случаях - последовательность однобайтных чисел), однозначно определяющее нажатую вами клавишу. Клавиатура вырабатывает различные сканируемые коды в зависимости от того, нажимается или отпускается клавиша. Младшие 7 битов скан-кода представляют идентификационный номер, присвоенный каждой клавише, а старший бит говорит о том, была ли клавиша нажата или отпущена: при нажатии старший бит (бит 7) содержит 1, при отпускании - 0. Например, 7-битный скан-код клавиши B - 48, или 0110000 в двоичной системе. Когда эта клавиша нажимается, то в порт A интерфейса посылается код 10110000, а когда ее освободили - код 00110000. AT работает немного по-другому, посылая в обоих случаях один и тот же скан-код, но предваряя его кодом F0h, когда клавиша отпускается. Отличие "кодов нажатия" и "кодов освобождения" позволяет компьютеру различать комбинации из нескольких клавиш, т.е. когда при удержании одной клавиши одновременно нажимается другая. В этом случае код освобождения от первой клавиши не поступает, и компьютер таким образом "знает", что она не освобождалась, т.е. что вводится комбинация, и правильно распознает ее. Комбинации используются при смене регистра клавиатуры (например, "a" и "Shift-a", т.е. "A"), реализации ввода "горячих клавиш" и т.д.

Дублируемые клавиши дифференцируются клавиатурой путем использования для них более длинных скан-кодов, состоящих из нескольких байтов. Например, две клавиши смены регистра Alt имеют различные сканируемые коды: левая клавиша Alt имеет сканируемый код, равный 38h, в то время как правая клавиша Alt имеет 2-байтовый сканируемый код E0h 38h.

Если какая-либо клавиша остается нажатой больше половины секунды, то контроллер посылает сигналы через заданные интервалы времени.

Микросхема контроллера клавиатуры управляет вводом информации с клавиатуры в процессор. Всякий раз, когда вы нажимаете или отпускаете ту или иную клавишу, контроллер клавиатуры формирует ее скан-код (очередной его байт) в порте A и генерирует прерывание 9 (запрос на процессор поступает по линии IRQ1). Процессор моментально прекращает свою работу и переключается на выполнение подпрограммы обработчика прерывания 9, содержащуюся в ROM BIOS. Обработчик считывает байт из порта A и осуществляет его обработку. Когда поступает код от клавиши сдвига или переключателя, то изменение статуса записывается в память (по адресам 0040:0011 и 0040:0012). Во всех остальных случаях скан-код трансформируется в код символа ASCII, при условии, что он подается при нажатии клавиши (в противном случае скан-код отбрасывается). Конечно, процедура сначала определяет установку клавиш сдвига и переключателей, чтобы правильно получить вводимый код (это "a" или "A" ?). После этого введенный код помещается в буфер клавиатуры. На рис.1 показан путь, который проходит нажатие на клавишу перед тем, как попасть в Вашу программу.

Имеется два типа кодов символов: коды ASCII и расширенные коды. Коды ASCII - это байтные числа, используемые для представления символов внешнего алфавита ЭВМ. Этот набор включает обычные символы пишущей машинки, а также ряд специальных букв и символов псевдографики. ASCII коды включают также 32 управляющих кода, которые обычно используются для передачи команд периферийным устройствам, а не выводятся как символы на экране; правда, каждый из них имеет соответствующее символьное представление, которое может быть выведено на дисплей с использованием прямой адресации дисплейной (видео) памяти.

Второй набор кодов, расширенные коды, присвоен клавишам или комбинациям клавиш, которые не имеют представляющего их символа ASCII, таким как функциональные клавиши или комбинации с клавишей Alt. Расширенные коды имеют длину 2 байта, причем первый байт всегда 0. Второй байт - определенный номер расширенного кода. Например, код 0:30 представляет Alt-A. Начальный номер позволяет программе определить, принадлежит ли данный код набору ASCII или расширенному набору.

Имеется несколько комбинаций клавиш, которые выполняют специальные функции и не генерируют скан-коды. Эти комбинации включают Ctrl-Break, Ctrl-Alt-Del и PrtSc, плюс SysReq для AT. Эти исключения приводят к заранее предопределенным результатам. Все остальные нажатия клавиш должны интерпретироваться Вашей программой, и если они имеют специальное назначение, скажем сдвинуть курсор влево, то Ваша программа должна содержать машинные команды, обеспечивающие достижение этого эффекта.

К счастью, операционная система предоставляет различные процедуры (служебные функции DOS 01h, 06h, 07h, 08h, 0Ah, 0Bh и 0Ch прерывания 21h ) для чтения кодов из буфера клавиатуры, включая средства для получения сразу целой строки. Поскольку эти процедуры позволяют делать практически все, что Вы можете пожелать, то практически бессмысленно писать свои процедуры обработки ввода с клавиатуры и можно пользоваться готовыми функциями DOS.

Перевод чисел в ASCII-коды

Автор: Vadim 0 коммент.

Для перевода чисел в их ASCII-коды даже не обязательно знать сами ASCII-коды, т.е. коды внешнего алфавита МЭВМ. Достаточно подготовить в памяти ЭВМ таблицу цифр, но не заполнять ее самому кодами цифр, а поручить эту работу ассемблеру. Этого можно добиться при помощи директивы

Table DB '0123456789ABCDEF'

По этой директиве ассемблер автоматически поместит, начиная с мнемоадреса Table правильные однобайтные ASCII-коды шестнадцатиричных цифр от 0 до F. Здесь '012..F' - это строковая константа, т.е. последовательность символов, заключенная в апострофы. Строковая константа всегда заменяется при ассемблировании на ее ASCII-код. Таким образом, в памяти ЭВМ по метке Table будет открыта таблица ASCII-кодов цифр. Теперь, чтобы перевести какую-то цифру, например 3, в ее ASCII-код, надо просто заменить эту цифру на соответствующий байт из таблицы (в нашем примере - на 3-й байт).

Для работы с таблицей, т.е. извлечения из нее нужных кодов, обычно используется команда XLAT. Она заменяет значение в регистре AL, рассматриваемое как номер элемента в таблице, на байт из таблицы с этим номером (исходное значение в AL служит индексом таблицы). Сама таблица адресуется регистром BX в сегменте данных DS. Таким образом, действие команды XLAT такое:

XLAT ; AL := m(DS:BX + AL)

Предположим, что необходимо преобразовать цифру 7 в ASCII-код. Получается следующий фрагмент:

MOV BX, OFFSET Table ; Поместить смещение таблицы в BX

MOV AL, 7 ; Загрузить 7 в AL

XLAT ; Считать 7-й элемент из таблицы в AL

Ярлыки:

Коды ASCII для чисел

Автор: Vadim 0 коммент.

Среди функций DOS нет такой, которая выводит числа. Такую операцию, если надо, приходится реализовывать на основе функций вывода текста на экран. Поэтому, чтобы вывести число, надо предварительно преобразовать его цифры в ASCII-коды этих цифр и выводить на экран эти коды, а не само число. Если же выводить число на экран непосредственно, то экран воспримет его не как число, а как последовательность ASCII-символов - каждый байт числа будет воспринят как один ASCII-символ - и выведет на экран эти символы, а не наше число. Например, если вывести на экран байт 61h, то на экране отобразится символ (буква) 'a', а не число (две цифры) 61, поскольку байт 61h (в двоичной нотации - 01100001) - это и есть ASCII-код буквы 'a'. Для того чтобы "высветить" на экране цифры '61', надо вывести на экран сначала ASCII-код цифры '6' - он равен 36h (00110110), а потом - ASCII-код цифры '1' - 11h (00010001). Тогда на экране отобразится нужная запись: 61. Кодирование цифр и букв-шестнадцатиричных цифр показано в таблице.

Таблица. Представление 16-ричных цифр в коде ASCII

-----------------------------------------------------------------

Цифра Код ASCII Цифра Код ASCII

двоичный 16-рич. двоичный 16-рич.

-----------------------------------------------------------------

0 0011 0000 30h 8 0011 1000 38h

1 0011 0001 31h 9 0011 1001 39h

2 0011 0010 32h A 0100 0001 41h

3 0011 0011 33h B 0100 0010 42h

4 0011 0100 34h C 0100 0011 43h

5 0011 0101 35h D 0100 0100 44h

6 0011 0110 36h E 0100 0101 45h

7 0011 0111 37h F 0100 0110 46h

-----------------------------------------------------------------

Ярлыки:

Прерывание 10h: службы ROM BIOS для видеодисплея

Автор: Vadim 0 коммент.

 

Все видеослужбы ROM BIOS запрашиваются с помощью прерывания 10h (в десятичной нотации 16). Имеется 25 основных служб, предоставляемых данным прерыванием. Подобно всем другим службам ROM BIOS видеослужбы нумеруются, начиная с 00h, и выбираются с помощью занесения номера службы в регистр AH. Обычно при работе с этими службами требуется задавать дополнительные параметры в регистрах AL, BX, CX или DX.

Служба 0: установить режим выдачи изображения

Служба 0 используется для выбора одного из четырнадцати режимов выдачи, показанных в таблице. Режимы с 0h по 6h применимы для стандартного цветного графического адаптера (CGA); режим 7h применяется для монохромного режима (MDA); режимы с 0Dh по 10h были добавлены для улучшенного графического адаптера (EGA); наконец, режимы 11h - 13h были внедрены на многоцветном графическом массиве (MCGA) (PS/2 моделей 25 и 30) и видеографическом массиве (VGA) (PS/2 моделей 50, 60 и 80).

Обычно при установке режима ROM BIOS чистит буфер памяти экрана, даже если снова и снова устанавливается один и тот же режим. Такая повторная установка того же самого режима может быть использована как простой и эффективный способ очистки экрана. В некоторых версиях DOS команда CLS фактически чистит экран с помощью данного способа. Установка видеорежима приводит также к установке принятых по умолчанию значений цветов цветовой палитры, поэтому при очистке экрана не используйте службу 0, если вы работаете с цветами, вместо этого применяйте видеослужбу 6.

При наличии адаптеров EGA,MCGA и VGA вы можете также дать указание ROM BIOS не очищать экран при установке видеорежима. Для этого к номеру режима, задаваемому вами в регистре AL, прибавьте число 80h (в десятичной нотации 128), что соответствует добавлению 1 в бит 7.

Значения регистров для службы установки видеорежима 0h

Номер службы Параметр

AH = 0 AL = номер режима

Таблица. Видеорежимы, устанавливаемые с помощью

видеослужбы ROM BIOS

--------------------------------------------------------------

Режим Тип Разрешающая Число Видеопод-

способность цветов системы

--------------------------------------------------------------

00h,01h Текстовый 40*25 16 CGA,EGA,

MCGA,VGA

02h,03h Текстовый 80*25 16 CGA,EGA,

MCGA,VGA

04h,05h Графический 320*200 4 CGA,EGA,

MCGA,VGA

06h Графический 640*200 2 CGA,EGA,

MCGA,VGA

07h Текстовый 80*25 Монохромный MDA,

EGA,VGA

08h,09h,0Ah Только для PCjr

0Bh,0Ch Внутренние режимы BIOS

0Dh Графический 320*200 16 EGA,VGA

0Eh Графический 640*200 16 EGA,VGA

0Fh Графический 640*350 Монохромный EGA,VGA

10h Графический 640*350 16 EGA,VGA

11h Графический 640*480 2 MCGA,VGA

12h Графический 640*480 16 VGA

13h Графический 320*200 256 MCGA,VGA

Например, следующий фрагмент очистит экран и установит видеорежим 3:

MOV AX, 0003h

INT 10h

Служба 6: прокрутить окно вверх

Служба 06h (в десятичной нотации 6) и ее напарник служба 07h (в десятичной нотации 7) используются для задания на экране прямоугольной области текстового окна и прокручивания его содержимого вверх или вниз на одну или более строк. Для достижения эффекта прокрутки в нижнюю часть окна службой 06h вставляются пустые строки (служба 07h вставляет пустые строки в верхнюю часть окна); при этом верхние строки окна (нижние - в случае службы 07h) смещаются и исчезают с экрана.

Число строк, подлежащих прокрутке, задается в регистре AL. При AL = 00h окно очищается полностью (то же самое произойдет, если мы прокрутим больше строк, чем позволяет размер окна). Положение и размер окна задается в регистрах CX и DX: CH содержит верхнюю строку, а DH - нижнюю строку; CL - левую колонку, а DL - правую колонку. Атрибуты для новых пустых строк в обеих службах, задаются в регистр BH. Ниже суммируется порядок задания значений регистров для обеих служб (06h и 07h).

Значения регистров для служб прокрутки окон 06h и 07h

Номер службы Параметры

AH = 06h AL = число строк, подлежащих прокрутке

(прокрутка CH = номер строки для верхнего лев. угла

вверх)

AH = 07h CL = номер колонки для верх. левого угла

(прокрутка DH = номер строки для нижнего прав. угла

вниз)

DL = номер колонки для ниж. правого угла

BH = атрибут для выдачи пустых строк

Служба 7: прокрутить окно вниз

Служба 07h (в десятичной нотации 7), как мы уже упоминали, является зеркальным отображением службы 06h. Различие между этими двумя службами состоит в том, как происходит прокрутка. При выполнении службы 07h новые пустые строки появляются в верхней части окна, а старые строки исчезают со стороны его нижней части. (При выполнении службы 06h имеют место противоположные изменения.)

Служба 02h: установить положение курсора

Служба 02h (в десятичной нотации 2) устанавливает позицию курсора, используя координаты строки и колонки экрана. В текстовых режимах, где может быть несколько страниц изображения, каждая из них имеет независимо записываемую позицию курсора. Хотя в графических режимах и нет видимого курсора, в них логическое положение курсора поддерживается тем же способом, что и в текстовых режимах. Эта логическая позиция курсора используется для управления вводом/выводом символов по аналогии с текстовым режимом.

Для задания позиции курсора номер строки помещается в регистр DH, номер колонки в DL, а номер страницы в BH. Нумерация строк и колонок начинается с координат 0,0 в левом верхнем углу экрана. В графических режимах для идентификации положения курсора используются координаты строки и колонки пикселов вместо координат для знака. Номер страницы - это обычный номер страницы изображения, используемый в Бэйсике: страницы от 0 до 7 в 40-колонных режимах и от 0 до 3 в 80-колонных режимах. В графических режимах номер страницы должен быть установлен в 0.

Сведения о задании регистров даны ниже.

Значения регистров при установке положения курсора

с помощью службы 02h

Номер службы Параметры

AH = 02h DH = номер строки

DL = номер колонки

BH = номер страницы

Прерывание 21h: общие функции DOS

Автор: Vadim 1 коммент.
 

Все функции DOS вызываются с помощью прерывания 21h (в десятичной нотации 33). Первая версия DOS содержала 42 функции. Во второй к ним добавлено еще 33 функции, которые сохраняются во всех последующих версиях. Выбор конкретной функции осуществляется путем записи соответствующего номера в регистр AH.

Функция 02: вывод одного символа на экран

Для вывода одного символа на экран ПК используется

функция 02 прерывания 21h:

mov DL, <код выводимого символа>

mov AH, 2

int 21h

Выводимый символ высвечивается в позиции курсора (что бы там ни было записано), после чего курсор сдвигается на одну позицию вправо. Если курсор находился в конце строки экрана, то он перемещается на начало следующей строки, а если курсор был в конце последней строки экрана, то содержимое экрана сдвигается на одну строку вверх, а внизу появляется пустая строка, в начало которой и устанавливается курсор.

Особым образом осуществляется вывод символов с кодами 7, 8, 9, 10 (0Ah) и 13 (0Dh). Символ с кодом 7 (bell, звонок) на экране не высвечивается (и курсор не сдвигается), а вызывает звуковой сигнал. Символ с кодом 8 (backspase, шаг назад) возвращает курсор на одну позицию влево, если только он не был в самой левой позиции строки. Символ с кодом 9 (tab, табуляция) смещает курсор вправо на ближайшую позицию, кратную 8. Символ с кодом 10 (line feed, перевод строки) перемещает курсор в следующую строку экрана, оставляя его в той же колонке. Символ с кодом 13 (carrige returne, возврат каретки) устанавливает курсор на начало текущей строки; вывод подряд символов с кодами 13 и 10 означает перевод курсора на начало следующей строки.

Функция 9: вывести строку на экран дисплея

Для вывода на экран строки (последовательности символов) можно, конечно, использовать функцию 02, однако сделать это можно и за один прием с помощью функции 09 прерывания 21h:

DS:DX := начальный адрес строки

mov AH, 9

int 21h.

Перед обращением к этой функции в регистр DS должен быть помещен номер того сегмента памяти, в котором находится выводимая строка, а в регистр DX - смещение строки внутри этого сегмента. При этом в конце строки должен находиться символ $ (код 24h), который служит признаком конца строки и сам не выводится.

Хотя эта функция может оказаться намного удобнее функций побайтового вывода на экран (функция 2 и 6), она имеет тот недостаток, что вполне обычный символ $ используется как ограничитель строки. Это еще один побочный продукт совместимости с CP/M.

Расширенные функции операционной системы DOS в качестве ограничителя строки используют CHR$(0). Это соответствует соглашениям, принятым в операционной системе UNIX и языке программирования Си.

Среди функций DOS нет такой, которая выводит числа. Такую операцию, если надо, приходится реализовывать на основе рассмотренных функций.

Функция 4Ch: завершение программы

Завершив все свои действия, программа обязана вернуть управление операционной системе, чтобы пользователь мог продолжить работу на ПК. Такой возврат реализуется функцией 4Ch прерывания 21h, которую помещают в конце программы:

mov AL, <код завершения>

mov AH, 4Ch

int 21h

Каждая программа, вообще говоря, обязана сообщить, успешно или нет она завершила свою работу. Дело в том, что любая программа вызывается из какой-то другой программы (например, из операционной системы), и иногда вызвавшей программе, чтобы правильно продолжить работу, надо знать, выполнила ли вызванная программа все, что надо, или она проработала с ошибкой. Такая информация передается в виде кода завершения программы (некоторого целого числа), который должен быть нулевым, если программа проработала правильно, и ненулевым (каким именно - оговаривается в каждом случае особо) в противном случае. (Узнать код завершения вызванной программы можно с помощью функции 4Dh прерывания 21h.) Потребуется этот код или нет, программа все равно должна выдать его.

МАНИПУЛЯТОР МЫШЬ

Автор: Vadim 0 коммент.

Манипулятор мышь (в дальнейшем, просто мышь) является средством, позволяющим пользователю достаточно удобно осуществлять управление прикладными программами. Как правило, мышь соединена с ПЭВМ через последовательный интерфейс. Прикладные программы, связывающиеся через интерфейс с мышью, делают это через обращение к драйверу Microsoft, например GMOUSE.COM. Все обращения к драйверу происходят через прерывание 33h.

Прерывание 33h имеет ряд функций, которые выбираются с помощью загрузки номера функции в регистр AX. Основные функции будут приведены ниже.

Функция 00h: инициализация мыши. Если мышь инициализирована, то в регистре AX возвращается значение FFFFh, а в регистре BX - число клавиш мыши. Если инициализации не происходит, то в регистре AX возвращается значение 0000h.

Функция 01h: показать указатель мыши.

Функция 02h: спрятать указатель мыши.

Функция 03h: получить текущие координаты указателя мыши и состояние кнопок. Координаты указателя соответствует виртуальному экрану. На практике, обычно, они содержат положение пикселя в графическом режиме или умноженные на 8 координаты в текстовом режиме. Отсчет графических координат начинается от 0. Текстовые координаты отсчитываются от 1. Эта функция возвращает в регистре CX координату x, а в регистре DX координату y, в регистре BX - состояние кнопки (бит 0 - левая кнопка нажата, если установлена; бит 1 - средняя кнопка нажата, если установлена; бит 2 - правая кнопка нажата, если установлена).

Функция 04h: установить позицию указателя. В регистр CX пересылается координата x, а в регистр DX координата y. Установленная позиция указателя будет игнорироваться, если она находится внутри области исключения (см. функцию 07h и 08h). Координаты задаются всегда в пикселях, где (0,0) - координата верхнего левого угла виртуального экрана.

Функция 05h: получить информацию о нажатии клавиши. В регистр BX пересылается номер кнопки (0 - левая кнопка, 1 - правая кнопка, 2 - средняя кнопка). В регистр AX возвращается состояние кнопки (бит 0 - левая кнопка нажата, если установлена; бит 1 - средняя кнопка нажата, если установлена; бит 2 - правая кнопка нажата, если установлена). В регистр BX возвращается счетчик нажатия клавиши, CX - координата x последнего нажатия, DX - координата y последнего нажатия. После обращения к этой функции счетчик нажатия клавиши сбрасывается.

Функция 06h: получить информацию об отжатии клавиши. В регистр BX пересылается номер кнопки (0 - левая кнопка, 1 - правая кнопка, 2 - средняя кнопка). В регистр AX возвращается состояние кнопки (бит 0 - левая кнопка отжата, если установлена; бит 1 - средняя кнопка отжата, если установлена; бит 2 - правая кнопка отжата, если установлена). В регистр BX возвращается счетчик отжатий клавиши, CX - координата x последнего отжатия клавиши мыши, а DX - координата y последнего отжатия клавиши мыши. После обращения к этой функции счетчик отжатия клавиши сбрасывается.

Функция 07h: установить горизонтальное ограничение для указателя мыши. В регистр CX пересылается минимальное значение координаты x, в регистр DX - максимальное значение координаты x.

Функция 08h: установить вертикальное ограничение для указателя мыши. В регистр CX пересылается минимальное значение координаты y, в регистр DX - максимальное значение координаты y.

Функция 09h: установить форму указателя мыши в графическом режиме. По умолчанию используется указатель типа стрелки. В ES:DX пересылают адрес буфера изображения. Длина буфера изображения 64 байта. Байты с 32 по 64 определяют вид курсора, а байты с 0 по 31 определяют прозрачность курсора. Они рассматриваются как битовая маска 16´16 каждый бит которой маскирует пиксели экрана. При создании изображения драйвер предварительно получает информацию о 16´16 пикселях соответствующего места экрана и к каждому пикселю применяется операция AND с маской экрана, а затем к полученному результату - операция XOR с маской изображения. Приведенный ниже пример показывает формирование курсора в графическом режиме в виде прямоугольника с тонкой прозрачной полоской в середине.

program testmouse;

uses dos,graph;

var

reg:registers;

res1,res2,i,res3,res4:byte;

buf : array [0..63] of byte;

gd,gm:integer;

begin

FOR i:=32 TO 64 DO

buf[i]:=255;

FOR i:=0 TO 31 DO

buf[i]:=1;

gd:=detect;

initgraph(gd,gm,'');

reg.AX:=1;

intr($33,reg);

reg.ax:=9;

reg.es:=seg(buf);

reg.dx:=ofs(buf);

intr($33,reg);

.

.

.

closegraph;

end.

В регистр BX заносится смещение вправо (в пикселях) из левого верхнего угла указателя, пикселя изображения рассматриваемого драйвером в качестве текущей позиции. В регистр CX заносится смещение вниз (в пикселях) из левого угла указателя, пикселя изображения рассматриваемого драйвером в качестве текущей позиции.

Функция 0Ah: установить вид указателя мыши в текстовом режиме. В регистр BX заносят 0, если выбирают курсор, используемый в программе, и 1, если выбирают стандартный курсор. Если указатель генерируется программой, то в регистр CX заносятся биты определяющие маску AND, а в регистр DX заносятся биты определяющие маску XOR по следующему принципу. Биты 0-7 - код символа; биты 8-10 цвет символа; бит 11 - бит интенсивности; биты 12-14 - цвет фона; бит 15 - бит мерцания.

Функция 10h: установить область исключения указателя. В регистр CX пересылают значение левой верхней координаты x, в DX - значение левой верхней координаты y, в SI - значение правой нижней координаты x, в DI - значение правой нижней координаты y. Эта функция определяет область исключения отображения указателя мыши. Область исключения отменяется обращением к функции 00h или 01h, или другим обращением к этой функции.

Перед выполнением любых внешних программ, прикладные программы должны сохранять состояние драйвера мыши, для того, чтобы при возврате в прикладную программу все настройки мыши в прикладной программе оставались неповрежденными.

Функция 15h: получить размер сохраненного буфера состояния мыши. В регистр BX возвращается размер буфера в байтах.

Функция 16h: сохранить состояние драйвера мыши. В ES:DX заносится адрес буфера. Под буфер выделяется 64 байта.

Функция 17h: восстановить состояние драйвера мыши. В ES:DX заносится адрес буфера.

Функция 1Dh: установить текущую видеостраницу для указателя мыши. В регистр BX заносится номер видеостраницы. Допустимые номера страницы зависят от активного режима визуального отображения.

Функция 1Eh: получить текущую видеостраницу для указателя мыши. В регистр BX возвращается номер текущей видеостраницы для указателя мыши.

Функция 1Fh: отключить драйвер мыши. Если отключение драйвера прошло успешно, то в регистр AX заносится значение 001Fh, а в ES:BX - адрес драйвера. Если драйвер не отключен, то в регистр AX возвращается значение FFFFh.

Функция 20h: повторное включение драйвера мыши.

Функция 24h: получить информацию о мыши. Возвращаются следующие значения:

BH - старший номер версии драйвера; BL - младший номер версии драйвера; CH - тип мыши (1 - bus mouse, 2 - serial mouse, 3 - InPort mouse, 4 - PS/2 mouse, 5 - HP mouse); CL - номер аппаратного прерывания.

При работе с мышью было бы неэффективно сводить команды мыши к эмуляции клавиатуры, но обрабатывать сигналы мыши и клавиатуры надо согласованно. Очень часто программа состоит из длительных операций, во время которых ее не интересует мышь и клавиатура, и операций обработки команд пользователя (перемещения курсора или выбор опций меню), выполнение которых должно успевать за частотой получения сигналов. Перемещения мыши при этом надо накапливать, а из буфера клавиатуры достаточно брать последнее слово (и очищать буфер). Все сказанное реализуется в приведенной ниже программе.

Procedure test;

{чтение мыши и клавиатуры}

type signal=record

case mouse:boolean of

true:(left,right:boolean;

{состояние клавиш мыши

dx,dy:word ;{ее перемещение });

false: (asc,ext:byte;

{ ASC- и расширенный коды }

status:word;

{флаги клавиатуры});

end;

{поле mouse показывает, сигнал от мыши или клавиатуры}

var ready:boolean;

begin

ready:=false; {ожидание команды}

with signal_t(signal) do

repeat

if mouse_sig then begin

mouse:=true;

r.ax:=11;intr($33,r);dx:=r.cx;dy:=r.dx;

r.ax:=3; intr($33,r);

left:=r.bx and 1 <>0;

right:=r.bx and 2 <>0;

mouse_sig:=false;

ready:=true; end

else {если мышь не трогали - опрос клавиатуры}

begin r.ah:=$11; intr($16,r);

{если не расширенная клавиатура, вызывайте функцию 1}

if r.flags and 64 = 0 then begin

{если буфер клавиатуры не пуст}

mouse:=false;

status:=memw[$40:$17]; {флаги клавиатуры}

repeat

r.ah:=$10;intr($16,r);

asc:=r.al; ext:=r.ah;

r.ah:=$11; intr($16,r);

ready:=r.flags and 64 <>0;

{очистка буфера и запоминание кода клавиши}

until ready; end;

end

until ready;

end;

ВНУТРЕННИЕ РЕГИСТРЫ

воскресенье, 31 января 2010 г. Автор: Vadim 0 коммент.

На рис. 1.2 пока­заны три группы регистров данных, и адресов, 16-битовый указатель команд IP (Instruction Pointer) и 16-битовый регистр флагов.

clip_image002[4]

РЕГИСТРЫ ДАННЫХ

В зависимости от того, чем Вы оперируете: 16-битовыми словами или 8-битовыми байтами, регистры данных можно рассматривать как четыре 16-бито­вых или восемь 8-битовых регистров. В первом случае регистры имеют имена АХ, ВХ, СХ, DX. Эти регистры образованы из 8-битовых регистров AL, АН, BL, ВН, CL, СН, DL и DH. Здесь L и Н означают младшие (low-order) и старшие (high-order) байты 16-битовых регистров. Например, регистры AL и АН образуют соответственно младший и старший байты регистра АХ.

Всеми этими регистрами можно пользоваться при программировании, но сле­дует учитывать, что ряд команд использует их неявным образом, в частности

регистр АХ, аккумулятор (accumulator), используется при умножении и делении слов, в операциях ввода-вывода и в некоторых операциях над строками; регистр AL используется при выполнении аналогичных операций над байтами, а также при преобразовании-десятичных чисел и выполнении над ними арифмети­ческих операций;

регистр АН используется при умножении и делении байтов;

регистр ВХ, Базовый регистр (base register), часто используется при адресации данных в памяти;

регистр СХ, счетчик (count register), используется как счетчик числа повторений цикла и в качестве номера позиции элемента данных при операциях над строка­ми. Регистр CL используется как счетчик при операциях сдвига и циклического сдвига на несколько битов;

регистр DX, регистр данных (data register), используется при умножении и деле­нии слов. Кроме того, в операциях ввода-вывода он используется как номер порта.

Программисты, имеющие опыт работы с микропроцессорами 8080 и 8085, должны заметить, что АН - единственный регистр микропроцессора 8088, не имеющий ана­лога в этих микропроцессорах. Остальные регистры использовались в них под другими именами; так, в микропроцессоре 8080 регистру AL соответствует регистр А, а регистрам ВХ, СХ и DX соответствуют регистры HL, ВС и DE.

Только регистры данных могут использоваться и как 16-битовые, и как 8-бито­вые. Все регистры остальных групп - 16-битовые.

РЕГИСТРЫ СЕГМЕНТОВ

Ранее уже говорилось, что в ЭВМ, сконструированных на базе мик­ропроцессоров 8086 и 8088, программы и данные хранятся в отдельных областях памяти. Эти области (или сегменты) могут иметь объем до 64 Кбайт. Микропроцес­сор 8088 может иметь дело одновременно с четырьмя сегментами. Начальные адре­са этих сегментов содержатся в его четырех регистрах сегментов. Эти регистры выполняют следующие функции:

регистр сегмента команд CS (code segment) указывает на сегмент, содержащий текущую исполняемую программу. Для вычисления адреса следующей исполня­емой команды микропроцессор 8088 добавляет к содержимому регистра CS (умноженному на 16) содержимое указателя команд IP;

регистр сегмента стека SS (stack segment) указывает на текущий сегмент стека. Стек представляет собой область памяти, используемую для временного хра­нения данных и адресов. Микропроцессор 8088 использует стек для хранения адреса возврата из текущей подпрограммы, но стек можно использовать также для восстановления содержимого регистров, изменяемых при работе програм­мы. Позже мы рассмотрим стеки более подробно;

регистр сегмента данных DS (data segment) указывает на текущий сегмент дан­ных, обычно содержащий используемые в программе переменные; регистр дополнительного сегмента ES (extra segment) указывает на текущий дополнительный сегмент, который используется при выполнении операций над строками.

РЕГИСТРЫ УКАЗАТЕЛЕЙ И ИНДЕКСОВ

Вспомните, что для вычисления адреса команды в сегменте команд микропроцессор 8088 извлекает номер блока памяти из регистра CS, а смеще­ние- из регистра IP. Подобным образом за счет выбора номера блока из соответ­ствующего регистра сегмента, а смещения - из другого регистра осуществляется доступ к данным других сегментов. Для доступа к сегменту данных микропроцес­сор 8088 извлекает номер блока из регистра DS, а смещение - из регистра ВХ или индексного регистра (SI или DI). Для доступа к сегменту стека микропроцессор 8088 извлекает номер блока из регистра SS, а смещение - из регистра указателя (SP или BP). Выбирая номер блока из регистра ES, микропроцессор может также полу­чить доступ к дополнительному сегменту (подробнее об этом см. в гл. 2).

УКАЗАТЕЛЬ КОМАНД

Большинство микропроцессоров выполняют программу следующим образом: извлекают из памяти очередную команду, исполняют ее, затем извлекают следующую команду и т. д. Этот подход (при котором цепочка действий выполня­ется последовательно), естественно, приводит к простоям, так как микропроцес­сор должен перед исполнением команды подождать ее извлечения из памяти. В микропроцессоре 8088 большая часть этих простоев исключается за счет того, что эти две задачи - извлечение команды и ее исполнение - выполняются отдельны­ми специализированными компонентами микросхемы.

Одна из них, интерфейс шины (Bus Interface Unit), извлекает команды из памяти и осуществляет передачу данных между исполнительными компонентами и "внеш­ним миром". Другая компонента, операционный блок (Execution Unit), только исполняет команды. Так как эти компоненты независимы, то интерфейс шины может извлекать новую команду из памяти в то самое время, когда операционный блок исполняет ранее извлеченную команду.

Как только интерфейс шины извлекает команду, он передает ее на конвейер микропроцессора (электронный эквивалент автомата для продажи сигарет). Таким образом, когда операционный блок заканчивает исполнение команды программы, то обычно может "взять" следующую команду прямо с конвейера.

clip_image002

Так как интерфейс шины не знает порядка исполнения команд программы, то он всегда извлекает команды с последовательно возрастающими адресами. Поэто­му операционному блоку приходится ждать извлечения команды из памяти толь­ко в тех случаях, когда в программе управление передается не следующей коман­де, а какой-то другой. Тогда операционный блок ожидает, пока интерфейс шины не освободит конвейер и не извлечет требуемую команду. Тогда и только тогда микропроцессор 8088 ждет подобно многим другим микропроцессорам извлечения каждой команды. На рис. 1.3 показано параллельное извлечение и исполнение команд в микропроцессоре 8088.

Так как микропроцессор 8088 работает столь необычным образом, то специалис­ты фирмы Intel подчеркнули отличие своего регистра "следующего исполняемого адреса" от регистров "следующего извлекаемого адреса" других производителей микропроцессоров, назвав его указателем команд (IP - instruction pointer) вместо обычного счетчика команд (PC - program counter). Так как регистр IP имеет столь специфическое назначение, то Вы не можете выполнять арифметические операции над его содержимым. Однако микропроцессор 8088 имеет команды, одни из кото­рых изменяют содержимое регистра IP, а другие помещают его в стек и извлекают обратно.

ФЛАГИ

В программе нередко требуется принять решение на основании резуль­тата только что исполненной микропроцессором 8088 команды. Например Вам может понадобиться выполнить одни действия, если результат сложения оказался нулем (например, напечатать. "Баланс равен нулю!" в программе для бухгалтер­ских расчетов), и совсем другие действия в противном случае.

В 16-битовом регистре флагов фиксируется информация о текущем состоянии дел, которая может помочь Вашей программе принять решение. Шесть битов регистра служат для хранения состояний, а три других могут быть использованы для программного управления режимом работы микропроцессора 8088.

На рис. 1.4 показано, как эти девять- флагов размещены в регистре флагов. Флаги имеют следующие значения:

[.Бит 0, флаг переноса CF(carry flag), равен 1, если произошел перенос единицы при сложении или заем единицы при вычитании. В противном случае он равен нулю. Кроме того, CF содержит значение бита, который при сдвиге или цикли­ческом сдвиге регистра или ячейки памяти вышел за их границы, и отражает результат операции сравнения. Наконец, CF служит индикатором результата умножения; детали см. в описании бита 11 (OF).

2.Бит 2,флаг четности PF(parity flag), равен 1, если в результате операции полу­чено число с четным числом единиц в его битах. В противном случае он равен нулю. ФлагРГ в основном используется в операциях обмена данными.

3. Бит 4, вспомогательный флаг переноса AF (auxiliary carry flag), аналогичен флагу CF, только контролирует перенос или заем для третьего бита данных. Полезен при выполнении операций над упакованными десятичными числами.

4. Бит 6, флаг нуля ZF(zero flag),равен 1, если в результате операции получен нудь; ненулевой результат c6pacbiBaerZF в нуль.

5. Бит 7, флаг знака SF (sign flag), имеет значение только при операциях над числами со знаком. Флаг SF равен 1, если в результате арифметической или логической операции, сдвига или циклического сдвига получено отрицательное число. В противном случае он равен нулю. Иными словами, SF дублирует стар­ший (знаковый) бит результата независимо от того, имеет результат длину 8 или 16 битов.

6. Бит 8, флаг трассировки TF (trap flag), разрешает микропроцессору 8088 испол­нять програму "по шагам" и используется при отладке программ.

7. Бит 9, флаг прерывания IF (interrupt enable flag), разрешает микропроцессору 8088 реагировать на прерывания от внешних устройств. Сбрасывание IF в нуль заставляет микропроцессор 8088 игнорировать прерывания до тех пор, пока F не станет равным 1.

8. Бит 10, флаг направления DF (direction flag), заставляет микропроцессор 8088 уменьшать на единицу (DF = 1) или увеличивать на'единицу(ВР = 0) регистр(ы) индекса после выполнения команды для работы со строками. Если DF = 0, то микропроцессор 8088 будет обрабатывать строку "слева направо" (от младших адресов к старшим). Если DF = 1, то обработка пойдет в обратном направлении (от старших адресов к младшим или справа налево).

9. Бит И, флаг переполнения OF (overflow flag), в первую очередь служит инди­катором ошибки при выполнении операций над числами со знаком. Флаг OF равен 1, если результат сложения двух чисел с одинаковым знаком или резуль­тат вычитания двух чисел с противоположными знаками выйдет за пределы допустимого диапазона значений операндов. В противном случае он равен 0. Кроме того, OF = 1, если старший, (знаковый) бит операнда изменился в резуль­тате операции арифметического сдвига. В противном случае он равен 0.

В сочетании с флагом CF флаг OF указывает длину результата умножения. Если старшая половина произведения отлична от нуля, то OF hCF равны 1; в противном случае оба эти флага равны 0.

Наконец,OF = 0, если частное от деления двух чисел переполняет результирую­щий регистр.

clip_image004

На рис. 1.4 заштрихованы позиции неиспользуемых битов (1, .3, 5 и 12 - 15). Когда бы Вы ни прочитали значение регистра флагов, эти биты будут нулевыми.

Не делайте ошибок, рассчитывая, что в кождый момент времени флаги должны быть в определенном состоянии. У микропроцессора 8088 имеются команды для установки или сброса флагов. Если состояние флагов может быть неоднозначным, используйте эти команды.

У микропроцессора 8088 есть команды условной передачи управления, которые проверяют состояния флагов переноса CF, четности PF, нуля ZF, знака SF и переполнения OF. В зависимости от результата проверки выполнение программы продолжается либо со следующей команды, либо с некоторой другой ячейки памяти.

ОБЩИЕ СВЕДЕНИЯ О МИКРОПРОЦЕССОРЕ 8088

Автор: Vadim 0 коммент.

Внутри микропроцессора 8088 информация содержится в группе 16-битовых элементов, называемых регистрами. Всего он имеет 14 регистров: 12 регистров данных и адресов и в дополнение к ним указатель команд (регистр адре­са команд) и регистр состояния (регистр флагов). Можно подразделить 12 регистров данных и адресов на три группы по четыре регистра, а именно на регистры данных, регистры указателей и индексов и регистры сегментов.

АДРЕСАЦИЯ

Так как у микропроцессора 8088 указатель команд и адресные ре­гистры имеют по 16 битов, то можно подумать, что он способен адресоваться к памяти объемом не более 64 байт (65 536 байт), т. е. имеет стандартный для 8-бито-' вых микропроцессоров диапазон адресов. Однако на самом деле микропроцессор 8088 всегда генерирует 20-битовые адреса. Он делает это за счет добавления 16-би­тового смещения к содержимому регистра сегмента, умноженному на 16. Таким образом,

физический адрес = смещение + 16 • (регистр сегмента).

В действительности микропроцессор 8088 вместо умножения на 16 использует содержимое регистра сегмента так, как если бы оно имело четыре дополнительных нулевых-бита (рис. 1. 1). Добавление нулей аналогично умножению, поскольку при каждом сдвиге на одну позицию влево двоичное число удваивается. Следователь­но, перемещение значения регистра сегмента на четыре позиции влево умножает его на 16:2 • 2 • 2 • 2 = 16.

Например, если смещение адреса имеет значение ЮН, где суффикс Н обозначает шестнадцатеричное число, а регистр сегмента содержит 2000Н, то микропроцессор 808С произведет вычисление физического адреса следующим образом (операнды показаны в двоичном виде):

0000 0000 0001 0000 (смещение) + 0010 0000 0000 0000 0000 (номер блока) 0010 0000 0000 0001 0000 (физический адрес).

Следовательно, мы получим 20-битовый адрес ячейки памяти 200ЮН.

Имея в своем распоряжении 20-битовый адрес, микропроцессор 8088 может получить доступ к любому из 1 048 576 байт. .(Данное значение называется "мега­байт" (Мбайт); 1 Мбайт = 1024 Кбайт.) Это в 16 раз превышает диапазон адресов микропроцессора 8088!

15 О

Смещение

clip_image002[4]

СЕГМЕНТЫ И СМЕЩЕНИЯ

У большинства микропроцессоров адрес ячейки памяти представляет собой одно число. А у микропроцессора 8088 адрес каждой ячейки памяти задается двумя числами: номером блока и смещением. Такой странный метод адресации обусловлен тем, что команды программы для микропроцессора 8088 и ее данные должны располагаться в разных частях памяти, другими словами, в разных сег­ментах. Если, например, Вам требуется адресоваться к ячейке с данными, то микропроцессору 8088 понадобится адрес блока памяти, с которого начинается сегмент данных (из регистра сегмента данных), и позиция желаемой ячейки в этом сегменте (ее смещение). Вспомните, как ищут в городе чей-нибудь дом: сначала находят улицу (считайте ее сегментом), а затем дом с нужным номером (смеще­нием) на этой улице.

К счастью, Вам достаточно задавать только смещение, а номер блока микропро­цессор 8088 выберет сам. Несколько позже мы обсудим это обстоятельство более детально.

ВОЗМОЖНОСТИ ПРОГРАММИРОВАНИЯ

Микропроцессор 8088 обладает впечатляющими возможностями прог­раммирования. Они пришлись особенно по душе тем программистам, которым ранее приходилось "бороться" с 8-битовыми микропроцессорами. Действительно, микропроцессор 8088 может выполнять арифметические операции над двоичными числами со знаком и без знака, длиной в 8 или 16 битов, а также над десятичными числами, хранящимися как в упакованном (по две цифры в байте), так и в неупа­кованном (по одной цифре в байте) виде. Он может также оперировать строками (например, сообщениями) длиной до 64 Кбайт.

Система команд микропроцессора 8088 содержит 92 основных типа команд и предусматривает семь различных способов адресации или режимов доступа к данным. Комбинации типов команд, режимов адресации (имеющие множество комбинаций операндов) и различных типов данных, которые мы только что упоми­нали, образуют тысячи команд, которые могут быть выполнены микропроцессором 8088. Действительно, сочетание всех этих свойств позволяет микропроцессору 8088 обеспечивать вдвое большую производительность по сравнению с 8085, если оба они работают с одинаковой скоростью.

МЕРА СКОРОСТИ

Как и электронные часы, микропроцессоры управляются кварцевым генератором. Кварцевый генератор испускает импульсы со стабильной фиксиро­ванной частотой, задающей скорость работы микропроцессора. В персональных ЭВМ PC и PC/XT кварцевый генератор испускает 4 770 000 импульсов в секунду.

Специалисты по вычислительной технике пользуются другой единицей измере­ния: числом колебаний в секунду, или герцами. Импульсы в секунду, колебания в секунду и герцы означают одно и то же, но в этой книге мы будем использовать термин "герц". Таким образом, персональная ЭВМ PC имеет тактовый генератор с частотой 4 770 000 Гц (4,77 МГц).

При частоте 4,77 МГц (4 770 000 колебаний в секунду) тактовый генератор персональной ЭВМ PC "тикает" каждые 210 не. Мы будем называть это значение циклом тактового генератора ЭВМ.

Самая быстрая команда (например, копирование содержимого одного регистра в другой регистр) выполняется за два цикла, или за 420 не. Самая медленная команда, деление двух 16-битовых чисел со знаком, выполняется за 206 циклов тактового генератора, или примерно за 43 мкс. Как видите, даже самая медленная команда выполняется всего за 0, 000043 с!

ОБЛАСТЬ ПОРТОВ ВВОДА-ВЫВОДА

В дополнение к области памяти объемом в 1 Мбайт микропроцессор 8088 может адресоваться к внешним устройствам через 65 536 (64 К) портов вво­да-вывода. Он имеет специальные команды ввода-вывода, которые позволяют Вам иметь непосредственный доступ к первым 256 портам (от 0 до 255). Другие команды позволяют Вам получить косвенный доступ к порту с помощью занесения идентифицирующего его номера (от 0 до 65 535) в регистр данных. Подобно ячей­кам памяти любой порт может быть 8- или 16-битовым.

РАСПРЕДЕЛЕНИЕ ПАМЯТИ

Большая часть адресного пространства в 1 Мбайт доступна для систем­ных и прикладных программ, но некоторые ячейки с самыми старшими и самыми младшими адресами используются микропроцессором 8088 для специальных целей. Шестнадцать старших байтов памяти отводятся под команды начальной загрузки системы, которые используются микропроцессором 8088 в момент вклю­чения питания. Первые 1024 ячейки отведены под адреса программ, которые исполняются микропроцессором 8088 при прерывании его работы внешним устрой­ством.

ПРЕРЫВАНИЯ

Время от времени всем нам приходится сталкиваться с прерываниями. Одни прерывания нам приятны, другие неприятны, третьи безразличны. При жела­нии Вы можете игнорировать некоторые прерывания, не обращая внимания, ска­жем, на телефонный или дверной звонок или на ребенка, дергающего Вас за рукав. (Да нет, игнорировать ребенка практически невозможно!) На прерывания других видов Вы просто обязаны реагировать; например, если Вы прокололи шину на железнодорожном переезде, то должны немедленно что-то предпринять.

Прерывания по сути являются требованиями к Вам обратить на них внимание. Аналогично периферийные устройства вычислительной системы могут потребо­вать, чтобы процессор "обратил на них внимание". Поэтому событие, которое заставляет процессор приостановить выполнение своей программы для выполне­ния некоторой затребованной деятельности, называется прерыванием.

Прерывания существенно увеличивают эффективность вычислительной систе­мы, поскольку они позволяют внешним устройствам "обращать на себя внимание" процессора только по мере надобности. Если бы в системе не было прерываний, тс процессору пришлось бы периодически проверять, не требует ли обслуживания какое-нибудь устройство системы. Это похоже на телефон без звонка: пользуясь им, Вам приходилось бы очень часто снимать трубку и проверять, не пытается ли кто-нибудь в Вами соединиться?

ТИПЫ ПРЕРЫВАНИЙ

Микропроцессор 8088 может обрабатывать прерывания двух видов: одни он может игнорировать, а другие обязан обслужить как можно скорее. Преры­вания могут быть инициированы внешними устройствами, например дисководами и. другими высокоскоростными периферийными устройствами; они могут быть также инициированы специальными командами или, в определенных ситуациях, самим микропроцессором 8088.

Микропроцессор 8088 может распознать 256 различных прерываний. Каждому из них однозначно соответствует код типа, по которому микропроцессор иденти­фицирует прерывание. Он использует этот код (целое число от 0 до 255) в качестве указателя ячейки, находящейся в области памяти с младшими адресами. Эта ячейка содержит адрес программы обработки данного прерывания, называемый вектором прерывания.

Некоторые из этих 256 прерываний используются системным программным обеспечением, поставляемым фирмой IBM к своим персональным ЭВМ IBM PC, а именно резидентной частью операционной системы (называемой BIOS), дисковой операционной системой DOS и интерпретатором языка Бейсик. Остальные прерыва­ния можно использовать по своему усмотрению. Более детально прерывания обсуждаются в гл. 6.

АДРЕСНАЯ ШИНА И ШИНА ДАННЫХ

Микропроцессор 8088 выполнен в виде интегральной микросхемы с 40 выводами, 20 из которых служат для вывода адресов ячеек памяти и образуют так называемую адресную шину. Первые 8 проводников адресной шины используются также для ввода данных в микропроцессор и вывода данных из него; они образуют 8-битовую шину данных микропроцессора 8088. Такое совмещение называется мультиплексированием шины данных и адресной шины. (Старшие четыре проводника адресной шины также мультиплексированы: по ним в микропроцессор поступает информация о состоянии операций с памятью и устройствами ввода-вы­вода.)

ПРОИСХОЖДЕНИЕ МИКРОПРОЦЕССОРА 8088

Автор: Vadim 0 коммент.

clip_image001

Первые микропроцессоры были 4-битовыми устройствами. Это озна­чает, что за один прием они могли обрабатывать только четыре бита информации. Для обработки более четырех битов они должны были выполнить несколько после­довательных операций. Конечно, это замедляло работу.

Первым промышленным 8-битовым микропроцессором (обрабатывавшим одно­временно 8 битов информации) стал микропроцессор 8008, выпущенный фирмой Intel в 1972 году. Он считается лучшим 8-битовым микропроцессором первого поко­ления. По своей архитектуре этот микропроцессор похож на калькулятор; он имеет аккумулятор, шесть регистров общего назначения, указатель стека (специальный регистр адреса рабочих ячеек), восемь регистров адреса и специальные команды для ввода и вывода данных. В 1973 году фирма Intel выпустила версию второго поколения-микропроцессора 8008, получившую название 8080.

По сравнению с микропроцессором 8008 микропроцессор 8080 мог адресоваться к большей памяти, имел расширенные возможности ввода-вывода, обладал допол­нительными командами и работал быстрее. Хотя идеи архитектуры микропроцес­сора 8008 были в основном перенесены фирмой Intel и на микропроцессор 8080, его внутренняя организация была улучшена настолько, что микропроцессор 8080 стал стандартом de facto для микропроцессоров второго поколения; и когда речь заходит о микропроцессорах, то многим людям первым делом приходит на ум именно микропроцессор 8080.

Достижения технологии позволили фирме Intel в 1976 году выпустить усовер­шенствованную версию микропроцессора 8080, названную 8085. Он отличался от микропроцессора 8080 конструкцией корпуса, имел сброс в начальное состояние (для инициализации микропроцессора), прерывания по вектору (для обслужива­ния периферийных устройств), последовательный порт ввода-вывода (для подклю­чения принтеров и других периферийных устройств). Кроме того, ему требовался только один источник питания +5 В (микропроцессору 8080 требовалось два источ­ника питания).

Ко времени выпуска микропроцессора 8085 фирма Intel встретилась с серьезной конкуренцией на рынке 8-битовых микропроцессоров. Начали пользоваться успехом микропроцессор Z80 фирмы Zilog Corporation, представляющий собой усовершенствование микропроцессора 8080, а также микропроцессоры 6800 фирмы Motorola и 6502 фирмы MOS Technology (ныне фирма Commodore), существенно отличавшиеся от 8080 по своей архитектуре. И вместо того, чтобы продолжать борьбу на переполненном рынке 8-битовых микропроцессоров, фирма Intel сделала качественный шаг вперед и в 1978 году выпустила 16-битовый микропроцессор 8086, который мог обрабатывать данные в 10 раз быстрее, чем микропроцессор 8080.

Микропроцессор 8086 программно совместим с микропроцессором 8080 на уров­не языка ассемблера. Это означает, что после некоторых минимальных преобразо­ваний программы, написанные для микропроцессора 8080, можно заново оттранс­лировать и выполнить на микропроцессоре 8086. Такая совместимость обеспечива­ется за счет того, что регистры микропроцессора 8080 и набор его команд являются как бы подмножествами регистров и набора команд микропроцессора 8086. Это позволило фирме Intel воспользоваться богатым опытом применения микропро­цессора 8080 и получить преимущество в сфере более сложных приложений.

Так как многие проектировщики все еще предпочитали пользоваться в своих 16-битовых системах более дешевыми 8-битовыми вспомогательными и перифе­рийными микросхемами, то фирма Intel выпустила версию микропроцессора 8086, имевшую то же устройство внутри, но 8-битовую Шину данных снаружи. Эта версия (микропроцессор 8088) идентична 8086, но затрачивает больше времени на переда­чи 16-битовых данных, которые выполняются с помощью двух последовательных 8-битовых передач. Однако в приложениях, где обрабатываются в основном 8-бито­вые значения, микропроцессор 8088 отстает по производительности от микропро* цессора 8086 не более чем на 10%.

Таким образом, Вы можете считать, что Ваша персональная ЭВМ фирмы IBM имеет 16-битовый микропроцессор. (И, следовательно, можете пользоваться много­численной литературой по микропроцессору 8086.) Завершим на этом введение и перейдем к обсуждению возможностей микропроцессора 8088.

Ярлыки:

ЧТО ТАКОЕ ЯЗЫК АССЕМБЛЕРА?

Автор: Vadim 0 коммент.

Подобно Бейсику язык ассемблера представляет собой набор слов, задающих ЭВМ действия, которые она должна выполнить. Но в отличие от языка Бейсик слова из набора команд языка ассемблера имеют непосредственное отноше­ние к компонентам ЭВМ. Описания действий ЭВМ, данные на языке Бейсик и на языке ассемблера, связаны между собой так же, как простое указание повернуть за угол и детальное описание процесса сокращений мышц и маневрирования при обходе препятствия. Обычному человеку в большинстве случаев достаточно простого указания; более детальные команды могут понадобиться только атлетам или альпинистам.

Программы, написанные на языке ассемблера, дают ЭВМ более детальные ко­манды, например "загрузить в регистр АХ значение 32", "поместить в регистр DL содержимое регистра CL", "запомнить содержимое регистра DL в ячейке памяти с адресом 3456". Как видите, язык Бейсик и язык ассемблера различаются способом задания действий ЭВМ: на Бейсике Вы даете общие указания, на языке ассемблера - конкретные.

Хотя программы на языке ассемблера пишутся дольше, чем аналогичные прог­раммы на Бейсике, они гораздо быстрее выполняются. Причиной этому служит уровень детализации команд. Здесь уместна аналогия с атлетом, который дости­гает лучших успехов в беге или прыжках за счет контроля каждого своего движе­ния. Для достижения большей производительности существенна точность выпол­няемых действий.

Так как язык ассемблера требует от Вас задания действий на уровне внутрен­них компонентов ЭВМ, то Вам надо понимать свойства и возможности интеграль­ной микросхемы, содержащей эти компоненты, а именно микропроцессора ЭВМ. В этой книге мы будем иметь дело с микропроцессором Intel 8088, работающим в персональных ЭВМ IBM PC/XT. Прежде чем описывать устройство этого микропро­цессора, коснемся истории его появления на свет.