Прямой ввод-вывод: организация и функции. Вывод на дисплей. Часть 1
"Среднеуровневый" ввод-вывод возможен только на консоль, работающую в "текстовом режиме", с помощью "базовых" прерываний MS-DOS и BIOS. Мы же пока пройдёмся по использованию этих функций в их "логическом" порядке.
2.1. Вывод символов на экран
Сразу следует отметить, что существуют три основных класса функций для вывода данных:
- Вывод одиночного символа на экран;
- Вывод последовательности символов на экран;
- Вывод форматированной последовательности символов на экран, включая преобразование двоичных форматов в текст.
Рассмотрим эти классы функций ниже:
2.1.1. Вывод одиночного символа
2.1.1.1. Реализация на языке Ассемблера
На языке Ассемблера возможен вывод одного байта информации. Для этого нужно воспользоваться функциями 09 и 0A прерывания BIOS 10H [1, 8]. Макет функции 9 прерывания 10H приведён на рисунке 2.1:
В регистр AL должен быть помещён выводимый на экран символ. Значение в регистре CX определяет число повторений символа на экране. Вывод на экран последовательности различных символов требует организацию цикла.
В текстовом режиме символы автоматически выводятся на экран и переходят с одной строки на другую. Так как регистр CX занят в функции, нельзя использовать цикл: LOOP. Кроме того, при выводе каждого символа необходимо передвигать курсор в следующий столбец (функция 02 ).
ФУНКЦИЯ 0A ;
Эта функция выводит символ в текущую позицию курсора. Функция 0A не устанавливает атрибуты символа, а оставляет старый атрибут. Для иллюстрации функции см. рисунок 2.2.
2.1.1.2. Реализация на языке ANSI C
Для стандарта ANSI C единственной функцией, осуществляющей вывод единичного символа на консоль прямым методом, является функция putch [3].
ФУНКЦИЯ: | putch; |
СИНТАКСИС: |
void putch( sim ); int sim |
ОПИСАНА В: | <conio.h> /* Используется только для описания функции */ |
ОПИСАНИЕ: | Функция putch записывает символ, код которого задаётся значением параметра sim, на дисплей. |
ВОЗВРАЩАЕТ: | Функция не возвращает значения. |
Смотри также функции ANSI C putc, putchar, fputc, fputchar.
2.1.1.3. Реализация на языке Ява
Вывод одиночного символа на языке Java соответствует выводу значения "примитивного символьного типа" char. Все типы данных выводятся на консоль с помощью двух системных методов: System.out.print и System.out.println [26]. Разница между этими методами состоит в том, что после вызова метода println происходит перевод курсора на новую строку, а при использовании метода print курсор остаётся после вывода на той же строке.
Алгоритм работы метода "print" следующий:
- Происходит перевод всех типов данных к типу данных String ;
- Выполняется конкатенация строк;
- Результирующая строка выводится на экран.
Чтобы использовать оператор вывода "print", просто после выражения запишите элемент (или несколько элементов, объединённых знаком "+" ), заключив его в круглые скобки, а потом в конце поставьте точку с запятой.
Пример приложения, выводящего две строки на экран консоли, смотри в пункте 2.1.2.4.
2.1.1.4. Язык Пролог
Для вывода символа на экран в указанную позицию на языке Turbo Prolog используется функция scr_char [53]. Её описание смотри ниже.
ФУНКЦИЯ: | SCR_CHAR |
СИНТАКСИС: | scr_char(Row,Column,Char), где Row - строка экрана в формате целого числа, Column - столбец экрана в формате целого числа, а Char - одиночный символ, выводимый на экран или считываемый с указанной позиции экрана; |
НАЗНАЧЕНИЕ: | Функция считывает символ с экрана или выводит его в указанную позицию; |
ШАБЛОНЫ: | (i,i,i) (i,i,o) ; |
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ: | Всегда успех; |
ОШИБКИ: | * 1001 Неверное значение позиции курсора. |
2.1.2. Вывод строки на экран
2.1.2.1. Реализация на языке Ассемблер
Функция 9 прерывания 21H выводит строку [1]. Адрес DS:DX должен указывать на первый символ строки. Строка должна заканчиваться символом '$', что означает, что символ '$' не может входить в выводимую строку. Строка может быть любой длины. Функция не переводит автоматически курсор на начало следующей строки после завершения вывода. Чтобы это выполнялось, надо добавить в конец строки символы: CR (0DH, "возврат каретки") и LF (0AH, "перевод строки"). Для иллюстрации смотри следующий пример:
Пример 2.1.
; --- в сегменте данных: FIR_STR DB 'Это первая строка',0DH, 0AH,'$' SEC_STR DB 'а это вторая строка$' ; --- вывод строки MOV AH, 9 ;Номер функции LEA DX, FIR_STR ;Загрузка адреса первой строки INT 21H LEA DX, SEC_STR ;Загрузка адреса второй строки INT 21H
Интерпретируются следующие управляющие коды: (см. таблицу 2.2).
Функция 40H прерывания 21H [1, 8]предназначена для вывода в файл, поэтому она требует дескриптора файла или устройства. Дисплей имеет заранее предназначенный дескриптор #1. Надо поместить это число в BX, а число байтов в строке - в CX. Адрес: DS:DX должен указывать на выводимую строку. Функция выводит текст с нормальными (белый текст на чёрном фоне) атрибутами.
Пример 2.2.
; --- в сегменте данных ABZATS DB 100 DUP('A') ; --- вывод 100 байт текста абзаца MOV AH, 40H ;Номер функции MOV BX, 1 ;дескриптор дисплея. MOV CX, 100 ;число выводимых символов LEA DX, ABZATS ;адрес абзаца INT 21H
При выводе с помощью этой функции можно использовать escape - последовательности (см. таблицу 2.1).
У ЭВМ IBM PC/AT и более современных есть ещё одна функция 13H прерывания BIOS 10H [8]. При выводе строки содержимое регистров ES:BP должно указывать на выводимую строку символов, а длина строки должна быть в CX. DX указывает на позицию курсора, откуда будет начинаться строка (вычисляется как смещение от начала страницы ES:BP, которая выводится, без учёта байтов-атрибутов). В BH должен быть указан номер страницы. Наконец, номер кода от 0 до 3, содержащийся в регистре AL, указывает способ вывода строки:
- AL = 0 строка состоит только из символов, курсор неподвижен;
- AL = 1 строка состоит только из символов, курсор двигается;
- AL = 2 в строке чередуются символы и атрибуты, курсор неподвижен;
- AL = 3 в строке чередуются символы и атрибуты, курсор двигается.
Когда значение AL равно 0 или 1, атрибуты должны находиться в регистре BL. Все символы будут выводиться с этими атрибутами. Данная функция будет воспринимать символы из таблицы 2.2, интерпретируя их как управляющие команды, а не печатные символы.
Пример 2.3.
; --- в сегменте данных ABZATS DB 100 DUP('A') ; --- вывод 100 байт текста абзаца ; --- подготовительные операции PUSH BP ;Сохранение BP PUSH ES ; Сохранение ES PUSH DS POP ES ; ES = DS ; --- вызов функции MOV AH,13H ;Номер функции MOV DX,0 ;С начала абзаца MOV CX, 100 LEA BP, ABZATS ;Адрес абзаца MOV AL, 1 MOV BL, 07H ;Текст белый по чёрному фону MOV BH, 0 ;Экранная страница INT 10H ; --- заключительные операции: POP ES ;Возврат ES POP BP ;Возврат BP