Средства BIOS
Функции DOS вывода на экран позволяют перенаправлять вывод в файл, но не позволяют вывести текст в любую позицию экрана и не позволяют изменить цвет текста. DOS предполагает, что для более тонкой работы с экраном программы должны использоваться видеофункции BIOS. BIOS (базовая система ввода-вывода) — это набор программ, расположенных в постоянной памяти компьютера, которые выполняют его загрузку сразу после включения и обеспечивают доступ к некоторым устройствам, в частности к видеоадаптеру. Все функции видеосервиса BIOS вызываются через прерывание 10h. Рассмотрим функции, которые могут быть полезны для вывода текстов на экран (полностью видеофункции BIOS описаны в приложении 2).
Выбор видеорежима
BIOS предоставляет возможность переключения экрана в различные текстовые и графические режимы. Режимы отличаются друг от друга разрешением (для графических) и количеством строк и столбцов (для текстовых), а также количеством возможных цветов.
INT 10h, АН = 00 — Установить видеорежим
Ввод: |
AL = номер режима в младших 7 битах |
Вывод: |
Обычно никакого, но некоторые BIOS (Phoenix и AMI) помещают в AL 30Н для текстовых режимов и 20h для графических |
Вызов этой функции приводит к тому, что экран переводится в выбранный режим. Если старший бит AL не установлен в 1, экран очищается. Номера текстовых режимов — 0, 1, 2, 3 и 7. 0 и 1 — 16-цветные режимы 40x25 (с 25 строками по 40 символов в строке), 2 и 3 — 16-цветные режимы 80x25, 7 — монохромный режим 80x25. Мы не будем пока рассматривать графические режимы, хотя функции вывода текста на экран DOS и BIOS могут работать и в них. Существует еще много текстовых режимов с более высоким разрешением (80x43, 80x60, 132x50 и т.д.), но их номера для вызова через эту функцию различны для разных видеоадаптеров (например, режим 61h — 132x50 для Cirrus 5320 и 132x29 для Genoa 6400). Однако, если видеоадаптер поддерживает стандарт VESA BIOS Extention, в режимы с высоким разрешением можно переключаться, используя функцию 4Fh.
INT 10h, АН = 4Fh, AL = 02 — Установить SuperVGA-видеорежим
Ввод: |
ВХ = номер режима в младших 13 битах |
Вывод: |
AL = 4Fh, если эта функция поддерживается АН = 0, если переключение произошло успешно АН = 1, если произошла ошибка |
Если бит 15 регистра ВХ установлен в 1, видеопамять не очищается. Текстовые режимы, которые можно вызвать с использованием этой функции: 80x60 (режим 108h), 132x25 (109h), 132x43 (10Ah), 132x50 (10Bh), 132x60 (10Ch).
Видеорежим, используемый в DOS по умолчанию, — текстовый режим 3.
Управление положением курсора
INT 10h, АН = 02 — Установить положение курсора
Ввод: |
АН = 02 ВН = номер страницы DH = строка DL = столбец |
С помощью этой функции можно установить курсор в любую позицию экрана, и дальнейший вывод текста будет происходить из этой позиции. Отсчет номера строки и столбца ведется от верхнего левого угла экрана (символ в левой верхней позиции имеет координаты 0, 0). Номера страниц 0 – 3 (для режимов 2 и 3)и 0 – 7 (для режимов 1 и 2) соответствуют области памяти, содержимое которой в данный момент отображается на экране. Можно вывести текст в неактивную в настоящий момент страницу, а затем переключиться на нее, чтобы изображение изменилось мгновенно.
INТ 10h, АН = 03 — Считать положение и размер курсора
Ввод: |
АН = 03 ВН = номер страницы |
Вывод: |
DH, DL = строка и столбец текущей позиции курсора СН, CL = первая и последняя строки курсора |
Возвращает текущее состояние курсора на выбранной странице (каждая страница использует собственный независимый курсор).
Вывод символов на экран
Каждый символ на экране описывается двумя байтами — ASCII-кодом символа и байтом атрибута, указывающим цвет символа и фона, а также является ли символ мигающим.
Атрибут символа:
Бит 7: символ мигает (по умолчанию) или фон яркого цвета (если его действие было переопределено видеофункцией 10h).
Биты 6 – 4: цвет фона.
Бит 3: символ яркого цвета ( по умолчанию) или фон мигает (если его действие было переопределено видеофункцией 11h).
Биты 2 – 0: цвет символа.
Цвета кодируются в битах, как показано в таблице 18.
Таблица 18. Атрибуты символов
|
Обычный цвет |
Яркий цвет |
000b |
черный |
темно-серый |
001b |
синий |
светло-синий |
010b |
зеленый |
светло-зеленый |
011b |
голубой |
светло-голубой |
100b |
красный |
светло-красный |
101b |
пурпурный |
светло-пурпурный |
110b |
коричневый |
желтый |
111b |
светло-серый |
белый |
INT 10h, АН = 08 — Считать символ и атрибут символа в текущей позиции курсора
Ввод: |
АН = 08 ВН = номер страницы |
Вывод: |
АН = атрибут символа AL = ASCII-код символа |
INT 10h, АН = 09 — Вывести символ с заданным атрибутом на экран
Ввод: |
АН = 09 ВН = номер страницы AL = ASCII-код символа BL = атрибут символа СХ = число повторений символа |
С помощью этой функции можно вывести на экран любой символ, включая даже символы CR и LF, которые обычно интерпретируются как конец строки. В графических режимах СХ не должен превышать число позиций, оставшееся до правого края экрана.
INT 10h, АН = 0Ah — Вывести символ с текущим атрибутом на экран
Ввод: |
АН = 0Ah ВН = номер страницы AL = ASCII-код символа СХ = число повторений символа |
Эта функция также выводит любой символ на экран, но в качестве атрибута символа используется атрибут, который имел символ, находившийся ранее в этой позиции.
INT 10h, АН = 0Eh — Вывести символ в режиме телетайпа
Ввод: |
АН = 0Eh ВН = номер страницы AL = ASCII-код символа |
Символы CR (0Dh), LF (0Ah), BEL (7) интерпретируются как управляющие символы. Если текст при записи выходит за пределы нижней строки, экран прокручивается вверх. В качестве атрибута используется атрибут символа, находившегося в этой позиции.
INT 10h, AH = 13h — Вывести строку символов с заданными атрибутами
Ввод: |
АН = 13h AL = режим вывода:бит 0 — переместить курсор в конец строки после вывода бит 1 — строка содержит не только символы, но также и атрибуты, так что каждый символ описывается двумя байтами: ASCII-код и атрибут биты 2 – 7 зарезервированы СХ = длина строки (только число символов) BL = атрибут, если строка содержит только символы DH,DL = строка и столбец, начиная с которых будет выводиться строки ES:BP = адрес начала строки в памяти |
<
/p>
Функция 13h выводит на экран строку символов, интерпретируя управляющие символы CR (0Dh), LF (0Ah), BS (08) и BEL (07). Если строка подготовлена в формате символ,атрибут — гораздо быстрее просто скопировать ее в видеопамять, о чем рассказано в следующем разделе.
Воспользуемся теперь функциями BIOS, чтобы усовершенствовать программу DOSOUT1 и вывести на экран все 256 символов, включая даже символы перевода строки. Кроме того, для лучшей читаемости таблицы после каждого символа будет выводиться пробел.
; biosout.asm ; Выводит на экран все ASCII-символы без исключения .model tiny .code org 100h ; Начало СОМ-файла start: mov ax,0003h int 10h ; Видеорежим 3 (очистка экрана ; и установка курсора в 0, 0) mov dx,0 ; DH и DL будут использоваться ; для хранения положения курсора. ; Начальное положение - 0,0 mov si,256 ; SI будет счетчиком цикла mov al,0 ; Первый символ - с кодом 00h mov ah,9 ; Номер видеофункции "вывод символа с атрибутом" mov cx,1 ; Выводится один символ за раз mov bl,00011111b ;атрибут символа - белый на синем cloop: int 10h ; Вывести символ на экран push ax ; Сохранить текущий символ и номер функции mov ah,2 ; Номер видеофункции 2 - ; изменить положение курсора inc dl ; Увеличить текущий столбец на 1 int 10h ; Переместить курсор mov ax,0920h ; АН = 09, AL = 20h (ASCII-код пробела) int 10h ; Вывести пробел mov ah,2 ; Номер видеофункции 2 inc dl ; Увеличить столбец на 1 int 10h ; Переместить курсор pop ax ; Восстановить номер функции в ah ; и текущий символ в al inc al ; Увеличить AL на 1 - следующий символ test al,0Fh ; Если AL не кратен 16, jnz continue_loop ; продолжить цикл, push ax ; иначе - сохранить номер функции ; и текущий символ mov ah,2 ; Номер видеофункции 2 inc dh ; Увеличить номер строки на 1 mov dl,0 ; Столбец = 0 int 10h ; Установить курсор на начало следующей строки pop ax ; Восстановить номер видеофункции ; и текущий символ continue_loop: dec si ; Уменьшить SI на 1, ; если он не стал нулем - продолжить jnz cloop ; CX используется внутри цикла, ; так что нельзя использовать команду LOOP ; для его организации ret ; Завершение СОМ-файла end start
Так как функция 09 выводит символ в позиции курсора, но не перемещает сам курсор, это приходится делать каждый раз специально.
Функции BIOS удобны для переключения и настройки видеорежимов, но часто оказывается, что вывод текста на экран гораздо быстрее и проще выполнять просто копированием изображения в видеопамять.
Так же как и для вывода на экран, BIOS предоставляет больше возможностей по сравнению с DOS для считывания данных и управления клавиатурой. Например, функциями DOS нельзя определить нажатие комбинаций клавиш типа Ctrl-Alt-Enter или нажатие двух клавиш Shift одновременно, DOS не может определить момент отпускания нажатой клавиши, и наконец, в DOS нет аналога функции С ungetch(), помещающей символ в буфер клавиатуры, как если бы его ввел пользователь. Все это можно осуществить, используя различные функции прерывания 16h и операции с байтами состояния клавиатуры.
INT 16h, АН = 0, 10h, 20h — Чтение символа с ожиданием
Ввод: |
АН = 00h (83/84-key), 10h (101/102-key), 20h (122-key) |
Вывод: |
AL = ASCII-код символа, 0 или префикс скан-кода АН = скан-код нажатой клавиши или расширенный ASCII-код |
Каждой клавише на клавиатуре соответствует так называемый скан-код (см. приложение 1), соответствующий только этой клавише. Этот код посылается клавиатурой при каждом нажатии и отпускании клавиши и обрабатывается BIOS (обработчиком прерывания INT 9). Прерывание 16h дает возможность получить код нажатия, не перехватывая этот обработчик. Если нажатой клавише соответствует ASCII-символ, то в АН возвращается код этого символа, а в AL — скан-код клавиши. Если нажатой клавише соответствует расширенный ASCII-код, в AL возвращается префикс скан-кода (например, Е0 для серых клавиш) или 0, если префикса нет, а в АН — расширенный ASCII-код. Функция 00Н обрабатывает только комбинации, использующие клавиши 84-клавишной клавиатуры, l0h обрабатывает все 101 – 105-клавишные комбинации, 20h — 122-клавишные. Тип клавиатуры можно определить с помощью функции 09h прерывания 16h, если она поддерживается BIOS (поддерживается ли эта функция, можно узнать с помощью функции C0h прерывания 15h).
INT 16h, АН = 1, 11h, 21h — Проверка символа
Ввод: |
АН = 01h (83/84-key), 11h (101/102-key), 21h (122-key) |
Вывод: |
ZF = 1, если буфер пуст ZF = 0, если в буфере присутствует символ, в этом случае AL = ASCII-код символа, 0 или префикс скан-кода АН = скан-код нажатой клавиши или расширенный ASCII-код |
<
/p>
Символ остается в буфере клавиатуры, хотя некоторые BIOS удаляют символ из буфера при обработке функции 01h, если он соответствует расширенному ASCII-коду, отсутствующему на 84-клавишных клавиатурах.
INT 16h, АН = 05h — Поместить символ в буфер клавиатуры
Ввод: |
АН = 05h СН = скан-код CL = ASCII-код |
Вывод: |
AL = 00, если операция выполнена успешно AL = 01h, если буфер клавиатуры переполнен АН модифицируется многими BIOS |
Обычно можно поместить 0 вместо скан-кода в СН, если функция, которая будет выполнять чтение из буфера, будет использовать именно ASCII-код. Например, следующая программа при запуске из DOS вызывает команду DIR (но при запуске из некоторых оболочек, например FAR, этого не произойдет).
; ungetch.asm ; заносит в буфер клавиатуры команду DIR так, чтобы она ; выполнилась сразу после завершения программы ; .model tiny .code org 100h ; СОМ-файл start: mov cl,'d' ; CL = ASCII-код буквы "d" call ungetch mov cl,'i' ; ASCII-код буквы "i" call ungetch mov cl,'r' ; ASCII-код буквы "r" call ungetch mov cl,0Dh ; перевод строки ungetch: mov ah,5 ; AH = номер функции mov ch,0 ; CH = 0 (скан-код неважен) int 16h ; поместить символ в буфер ret ; завершить программу
end start
INT 16h, AH = 02h, 12h, 22h — Считать состояние клавиатуры
Ввод: |
АН = 02h (83/84-key), 12h (101/102-key), 22h (122-key) |
Вывод: |
AL = байт состояния клавиатуры 1 АН = байт состояния клавиатуры 2 (только для функций 12h и 22h) |
Байт состояния клавиатуры 1 (этот байт всегда расположен в памяти по адресу 0000h:0417h или 0040h:0017h):
Бит 7: Ins включена
Бит 6: CapsLock включена
Бит 5: NumLock включена
Бит 4: ScrollLock включена
Бит 3: Alt нажата (любая Alt для функции 02h, часто только левая Alt для 12h/22h)
Бит 2: Ctrl нажата (любая Ctrl)
Бит 1: Левая Shift нажата
Бит 0: Правая Shift нажата
Байт состояния клавиатуры 2 (этот байт всегда расположен в памяти по адресу 0000h:0418h или 0040h:0018h):
Содержание раздела