JNZ ... ; нечетное значение? 3. TEST DX,OFFH ;Регистр DX содержит JZ ... ; нулевое значение? Еще одна логическая команда NOT устанавливает обpатное значе ние бит в байте или в слове, в регистре или в памяти: нули становятся единицами, а единицы - нулями. Если, например, pегистр AL содержит 1100 0101, то команда NOT AL изменяет это значение на 0011 1010. Флаги не меняются. Команда NOT не эквивалентна команде NEG, которая меняет значение с положительного на отрицательное и наоборот, посредством замены бит на противоположное значение и прибавления единицы (см."Отрицательные числа" в гл.1.). ПРОГРАММА: ИЗМЕНЕНИЕ СТРОЧНЫХ БУКВ НА ЗАГЛАВНЫЕ ------------------------------------------------------------ Существуют различные причины для преобразований между строчными и заглавными буквами. Например, вы могли получить файл данных, созданный на компьютере, который работает только с заглавными буквами. Или некая программа должна позволить пользователям вводить команды как заглавными, так и строчными буквами (например, YES или yes) и преобразовать их в заглавные для проверки. Заглавные буквы от A до Z имеют Ассемблер для IBM PC. Глава 7 146 шест.коды от 41 до 5A, а строчные буквы от a до z имеют шест.коды от 61 до 7A. Единственная pазница в том, что пятый бит равен 0 для заглавных букв и 1 для строчных: Биты: 76543210 Биты: 76543210 Буква A: 01000001 Буква a: 01100001 Буква Z: 01011010 Буква z: 01111010 COM-программа, приведенная на рис. 7.6, преобразует данные в поле TITLEX из строчных букв в прописные, начиная с адреса TITLEX+1. Программа инициализирует регистр BX адресом TITLEX+1 и использует его для пересылки символов в регистр AH, начиная с TITLEX+1. Если полученное значение лежит в пределах от шест.61 и до 7A, то команда AND устанавливает бит 5 в 0: AND AH,11011111B Все символы, отличные от строчных букв (от a до z), не изменяются. Измененные символы засылаются обратно в область TITLEX, значение в регистре BX увеличивается для очередного символа и осуществляется переход на следующий цикл. Используемый таким образом регистр BX действует как индексный регистр для адресации в памяти. Для этих целей можно использовать также регистры SI и DI. ------------------------------------------------------------ ------------------------------------------------------------ Рис. 7.6. Изменение строчных букв на прописные. КОМАНДЫ СДВИГА И ЦИКЛИЧЕСКОГО СДВИГА ------------------------------------------------------------ Команды сдвига и циклического сдвига, которые представля ют собой часть логических возможностей компьютера, имеют следующие свойства: - обрабатывают байт или слово; - имеют доступ к регистру или к памяти; - сдвигают влево или вправо; - сдвигают на величину до 8 бит (для байта) и 16 бит (для слова); - сдвигают логически (без знака) или арифметически (со знаком). Значение сдвига на 1 может быть закодировано как непосред cтвенный операнд, значение больше 1 должно находиться в регистре CL. Команды сдвига При выполнении команд сдвига флаг CF всегда содержит зна чение последнего выдвинутого бита. Существуют следующие команды cдвига: Ассемблер для IBM PC. Глава 7 147 SHR ;Логический (беззнаковый) сдвиг вправо SHL ;Логический (беззнаковый) сдвиг влево SAR ;Арифметический сдвиг вправо SAL ;Арифметический сдвиг влево Следующий фрагмент иллюстрирует выполнение команды SHR: MOV CL,03 ; AX: MOV AX,10110111B ; 10110111 SHR AX,1 ; 01011011 ;Сдвиг вправо на 1 SHR AX,CL ; 00001011 ;Сдвиг вправо на 3 Первая команда SHR сдвигает содержимое регистра AX вправо на 1 бит. Выдвинутый в результате один бит попадает в флаг CF, а самый левый бит регистра AX заполняется нулем. Вторая команда cдвигает содержимое регистра AX еще на три бита. При этом флаг CF последовательно принимает значения 1, 1, 0, а в три левых бита в регистре AX заносятся нули. Рассмотрим действие команд арифметического вправо SAR: MOV CL,03 ; AX: MOV AX,10110111B ; 10110111 SAR AX,1 ; 11011011 ;Сдвиг вправо на 1 SAR AX,CL ; 11111011 ;Сдвиг вправо на 3 Команда SAR имеет важное отличие от команды SHR: для заполне ния левого бита используется знаковый бит. Таким образом, положительные и отрицательные величины сохраняют свой знак. В приведенном примере знаковый бит содержит единицу. При сдвигах влево правые биты заполняются нулями. Таким обpазом, результат команд сдвига SHL и SAL индентичен. Сдвиг влево часто используется для удваивания чисел, а сдвиг вправо - для деления на 2. Эти операции осуществляются значительно быстрее, чем команды умножения или деления. Деление пополам нечетных чисел (например, 5 или 7) образует меньшие значения (2 или 3, соответственно) и устанавливаеют флаг CF в 1. Кроме того, если необходимо выполнить сдвиг на 2 бита, то использование двух команд сдвига более эффектив но, чем использование одной команды с загрузкой регистра CL значением 2. Для проверки бита, занесенного в флаг CF используется команда JC (переход, если есть перенос). Команды циклического сдвига Циклический сдвиг представляет собой операцию сдвига, при которой выдвинутый бит занимает освободившийся разряд. Существуют следующие команды циклического сдвига: ROR ;Циклический сдвиг вправо ROL ;Циклический сдвиг влево RCR ;Циклический сдвиг вправо с переносом RCL ;Циклический сдвиг влево с переносом Ассемблер для IBM PC. Глава 7 148 Следующая последовательность команд иллюстрирует операцию циклического сдвига ROR: MOV CL,03 ; BX: MOV BX,10110111B ; 10110111 ROR BX,1 ; 11011011 ;Сдвиг вправо на 1 ROR BX,CL ; 01111011 ;Сдвиг вправо на 3 Первая команда ROR при выполнении циклического сдвига переносит правый единичный бит регистра BX в освободившуюся левую позицию. Вторая команда ROR переносит таким образом три правых бита. В командах RCR и RCL в сдвиге участвует флаг CF. Выдвигае мый из регистра бит заносится в флаг CF, а значение CF при этом поступает в освободившуюся позицию. Рассмотрим пример, в котором используются команды циклического и простого сдвига. Предположим, что 32-битовое значение находится в регистрах DX:AX так, что левые 16 бит лежат в регистре DX, а правые - в AX. Для умножения на 2 этого значения возможны cледующие две команды: SHL AX,1 ;Умножение пары регистров RCL DX,1 ; DX:AX на 2 Здесь команда SHL сдвигает все биты регистра AX влево, причем самый левый бит попадает в флаг CF. Затем команда RCL сдвигает все биты регистра DX влево и в освободившийся правый бит заносит значение из флага CF. ОРГАНИЗАЦИЯ ПРОГРАММ ------------------------------------------------------------ Ниже даны основные рекомендации для написания ассемблер ных программ: 1. Четко представляйте себе задачу, которую должна решить программа 2. Сделайте эскиз задачи в общих чертах и спланируйте общую логику программы. Например, если необходимо прове рить операции пеpесылки нескольких байт (как в примере на рис.7.5), начните c определения полей с пересылаемы ми данными. Затем спланируйте общую стратегию для инициализации, условного перехода и команды LOOP. Приведем основную логику, которую используют многие программисты в таком случае: инициализация стека и сегментных регистров вызов подпрограммы цикла возврат Подпрограмма цикла может быть спланирована следующим образом: инициализация регистров значениями адресов Ассемблер для IBM PC. Глава 7 149 и числа циклов Метка: пересылка одного байта увеличение адресов на 1 уменьшение счетчика на 1: если счетчик не ноль, то идти на метку если ноль, возврат 3. Представьте программу в виде логических блоков, следую щих друг за другом. Процедуры не превышающие 25 строк (размер экрана) удобнее для отладки. 4. Пользуйтесь тестовыми примерами программ. Попытки запом нить все технические детали и программирование сложных программ "из головы" часто приводят к многочисленным ошибкам. 5. Используйте комментарии для описания того, что должна делать процедура, какие арифметические действия или операции сравнения будут выполняться и что делают редко используемые команды. (Например, команда XLAT, не имеющая операндов). 6. Для кодирования программы используйте заготовку програм мы, скопированной в файл с новым именем. В следующих программах данной книги важным является использование команды LEA, индексных регистров SI и DI, вызываемых процедур. Получив теперь базовые знания по ассемблеру, можем перейти к более развитому и полезному программированию. ОСНОВНЫЕ ПОЛОЖЕНИЯ НА ПАМЯТЬ ------------------------------------------------------------ ъ Метки процедур (например, B20:) должны завершаться двое точием для указания типа NEAR. Отсутствие двоеточия приводит к ассемблерной ошибке. ъ Метки для команд условного перехода и LOOP должны лежать в границах -128 до +127 байт. Операнд таких команд генерирует один байт объектного кода. Шест. от 01 до 7F соответствует десятичным значениям от +1 до +127, а шест. от FF до 80 покрывает значения от -1 до +128. Так как длина машинной команды может быть от 1 до 4 байт, то соблюдать границы не просто. Практически можно ориентироваться на размер в два экрана исходного текста (примерно 50 строк). ъ При использовании команды LOOP, инициализируйте регистр CX положительным числом. Команда LOOP контролирует только нулевое значение, при отрицательном программа будет продолжать циклиться. Ассемблер для IBM PC. Глава 7 150 ъ Если некоторая команда устанавливает флаг, то данный флаг сохраняет это значение, пока другая команда его не изменит. Например, если за арифметической командой, которая устанавливает флаги, следуют команды MOV, то они не изменят флаги. Однако, для минимизации числа возможных ошибок, cледует кодировать команды условного перехода непосредственно после команд, устанавливающих проверяемые флаги. ъ Выбирайте команды условного перехода соответственно операциям над знаковыми или беззнаковыми данными. ъ Для вызова процедуры используйте команду CALL, а для возврата из процедуры - команду RET. Вызываемая процеду ра может, в свою очередь, вызвать другую процедуру, и если следовать существующим соглашениям, то команда RET всегда будет выбирать из стека правильный адрес возвра та. Единственные примеры в этой книге, где используется переход в процедуру вместо ее вызова - в начале COM- программ. ъ Будьте внимательны при использовании индексных операн дов. Сравните: MOV AX,SI MOV AX,[SI] Первая команда MOV пересылает в регистр AX содержимое регистра SI. Вторая команда MOV для доступа к пересылае мому слову в памяти использует относительный адрес в регистре SI. ъ Используйте команды сдвига для удванивания значений и для деления пополам, но при этом внимательно выбирайте соответствующие команды для знаковых и беззнаковых данных. ВОПРОСЫ ДЛЯ САМОПРОВЕРКИ ------------------------------------------------------------ 7.1. Какое максимальное количество байт могут обойти коман ды коpоткий JMP, LOOP и относительный переход? Какой машинный код операнда при этом генерируется? 7.2. Команда JMP начинается на шест. 0624. Определите адрес перехода, если шест. объектный код для операнда команды JMP: а) 27, б) 6B, в) C6. 7.3. Напишите программу вычисления 12 чисел Фибоначи: 1, 1, 2, 3, 5, 8, 13,... (каждое число в последовательности представляет собой сумму двух предыдущих чисел). Для организации цикла используйте команду LOOP. Выполните ассемблирование, компановку и с помощью отладчика DEBUG трассировку программы. Ассемблер для IBM PC. Глава 7 151 7.4. Предположим, что регистры AX и BX содержат знаковые данные, a CX и DX - беззнаковые. Определите команды CMP (где необходимо) и команды безусловного перехода для следующих проверок: а) значение в DX больше, чем в CX? б) значение в BX больше, чем в AX? в) CX содержит нуль? г) было ли переполнение? д) значение в BX равно или меньше, чем в AX? е) значение в DX равно или меньше, чем в CX? 7.5. На какие флаги воздействуют следующие события и какое значение этих флагов? a) произошло переполнение; б) результат отрицательный; в) результат нулевой; г) обработка в одношаговом режиме; д) передача данных должна быть справа налево. 7.6. Что произойдет при выполнении программы , приведенной на рис.7.4, если в процедуре BEGIN будет отсутствовать команда RET? 7.7. Какая разница между кодированием в директиве PROC опеpанда с типом FAR и с типом NEAR? 7.8. Каким образом может программа начать выполнение процедуры? 7.9. В EXE-программе процедура A10 вызывает B10, B10 вызывает C10, а C10 вызывает D10. Сколько адресов, кроме начальных адресов возврата в DOS, содержит стек? 7.10. Предположим , что регистр BL содержит 11100011 и поле по имени BOONO содержит 01111001. Определите воздейст вие на регистр BL для следующих команд: а) XOR BL,BOONO; б) AND BL,BOONO; в) OR BL,BOONO; г) XOR BL,11111111B; д) AND BL,00000000B. 7.11. Измените программу на рис.7.6 для: а) определения содержимого TITLEX заглавными буквами; б) преобразова ние заглавных букв в строчные. 7.12. Предположим, что регистр DX содержит 10111001 10111001, а pегистр CL - 03. Определите содержимое регистра DX после следующих несвязанных команд: а) SHR DX,1; б) SHR DX,CL; в) SHL DX,CL; г) SHL DL,1; д) ROR DX,CL; е) ROR DL,CL; ж) SAL DH,1. 7.13. Используя команды сдвига, пересылки и сложения, умножьте содержимое регистра AX на 10. 7.14. Пример программы, приведенной в конце раздела "сдвиг и циклический сдвиг", умножает содержимое пары регистров DX:AX на 2. Измените программу для: а) умножения на 4; б) деления на 4; в) умножения 48 бит в регистрах DX:AX:BX на 2. Ассемблер для IBM PC. Глава 8 172 ГЛАВА 8. Экранные операции I: Основные свойства ------------------------------------------------------------ Экранные операции I: Основные свойства Цель: Объяснить требования для вывода информации на экран, а также для ввода данных с клавиатуры. ВВЕДЕНИЕ ------------------------------------------------------------ В предыдущих главах мы имели дело с программами, в котор ых данные oпределялись в операндах команд (непосредственные данные) или инициализировались в конкретных полях программы. Число практических применений таких программ в действитель ности мало. Большинcтво программ требуют ввода данных с клавиатуры, диска или модема и обеспечивают вывод данных в удобном формате на экран, принтер или диск. Данные, предназначенные для вывода на экран и ввода с клавиатуры, имеют ASCII формат. Для выполнения ввода и вывода используется команда INT (прерывание). Существуют различные требования для указания системе какое действие (ввод или вывод) и на каком устройстве необходимо выполнить. Данная глава раскрывает основные требования для вывода информации на экран и ввода данных с клавиатуры. Все необходимые экранные и клавиатурные операции можно выполнить используя команду INT 10H, которая передает управление непосредственно в BIOS. Для выполнения некоторых более сложных операций существует прерывание более высокого уровня INT 21H, которое сначала передает управление в DOS. Например, при вводе с клавиатуры может потребоваться подсчет введенных символов, проверку на максимальное число символов и проверку на символ Return. Преpывание DOS INT 21H выполняет многие из этих дополнительных вычислений и затем автоматически передает управление в BIOS. Материал данной главы подходит как для монохромных (черно-белых, BW), так и для цветных видеоммониторов. В главах 9 и 10 приведен материал для управления более совершенными экранами и для использоваения цвета. КОМАНДА ПРЕРЫВАНИЯ: INT ------------------------------------------------------------ Команда INT прерывает обработку программы, передает управление в DOS или BIOS для определенного действия и затем возвращает управление в прерванную программу для продолжения обработки. Наиболее часто прерывание используется для выполнения операций ввода или вывода. Для выхода из программы на обработку прерывания и для последующего возврата команда INT выполняет следующие действия: Ассемблер для IBM PC. Глава 8 173 ъ уменьшает указатель стека на 2 и заносит в вершину стека содержимое флагового регистра; ъ очищает флаги TF и IF; ъ уменьшает указатель стека на 2 и заносит содержимое регистра CS в стек; ъ уменьшает указатель стека на 2 и заносит в стек значение командного указателя; ъ обеспечивает выполнение необходимых ддействий; ъ восстанавливает из стека значение регистра и возвращает управление в прерванную программу на команду, следующую после INT. Этот процесс выполняется полностью автоматически. Необхо димо лишь определить сегмент стека достаточно большим для записи в него значений регистров. В данной главе рассмотрим два типа прерываний: команду BIOS INT 10H и команду DOS INT 21H для вывода на экран и ввода с клавиатуры. В последующих примерах в зависимости от требований используются как INT 10H так и INT 21H. УСТАНОВКА КУРСОРА ------------------------------------------------------------ Экран можно представить в виде двумерного пространства с адресуемыми позициями в любую из которых может быть установ лен курсор. Обычный видеомонитор, например, имеет 25 строк (нумеруемых от 0 до 24) и 80 столбцов (нумеруемых от 0 до 79). В следующей таблице приведены некоторые примеры положений курсора на экране: -------------------------------------------------------- Дес. формат Шест.формат -------------- -------------- Положение строка столбец строка столбец -------------------------------------------------------- Верхний левый угол 00 00 00 00 Верхний правый угол 00 79 00 4F Центр экрана 12 39/40 00 27/28 Нижний левый угол 24 00 18 00 Нижний правый угол 24 79 18 4F -------------------------------------------------------- Команда INT 10H включает в себя установку курсора в любую позицию и очистку экрана. Ниже приведен пример установки курсора на 5-ую строку и 12-ый столбец: MOV AH,02 ;Запрос на установку курсора MOV BH,00 ;Экран 0 MOV DH,05 ;Строка 05 MOV DL,12 ;Столбец 12 INT 10H ;Передача управления в BIOS Ассемблер для IBM PC. Глава 8 174 Значение 02 в регистре AH указывает команде INT 10H на выпол нение операции установки курсора. Значение строки и столбца должны быть в регистре DX, а номер экрана (или страницы) в регистре BH (обычно 0). Содержимое других регистров несущест венно. Для установки строки и столбца можно также использо вать одну команду MOV c непосредственным шест. значением: MOV DX,050CH ;Строка 5, столбец 12 ОЧИСТКА ЭКРАНА ------------------------------------------------------------ Запросы и команды остаются на экране пока не будут смеще ны в результате прокручивания ("скролинга") или переписаны на этом же месте другими запросами или командами. Когда программа начинает cвое выполнение, экран может быть очищен. Очищаемая область экрана может начинаться в любой позиции и заканчиваться в любой другой позиции с большим номером. Начальное значение строки и столбца заносится в регистр DX, значение 07 - в регистр BH и 0600H в AX. В следующем примере выполняется очистка всего экрана: MOV AX,0600H ;AH 06 (прокрутка) ;AL 00 (весь экран) MOV BH,07 ;Нормальный атрибут (черно/белый) MOV CX,0000 ;Верхняя левая позиция MOV DX,184FH ;Нижняя правая позиция INT 10H ;Передача управления в BIOS Значение 06 в регистре AH указывает команде INT 10H на выполнение опарации очистки экрана. Эта операция очищает экран пробелами; в следующей главе скролинг (прокрутка) будет пассмотрен подробнее. Если вы по ошибке установили нижнюю правую позицию больше, чем шест. 184F, то очистка перейдет вновь к началу экрана и вторично заполнит некоторые позиции прробелами. Для монохромных экранов это не вызывает каких-либо неприятностей, но для некоторых цветных мониторов могут возникнуть серьезные ошибки. ЭКРАННЫЕ И КЛАВИАТУРНЫЕ ОПЕРАЦИИ: БАЗОВАЯ ВЕРСИЯ DOS ------------------------------------------------------------ Обычно программы должны выдать на экран сообщение о завер шении или об обнаружении ошибки, отобразить запрос для ввода данных или для получения указания пользователя. Рассмотрим сначала методы, применяемые в базовой версии DOS, в последую щих pазделах будут показаны расширенные методы, введенные в DOS версии 2.0. Операции из базовой DOS работают во всех версиях, хотя в руководстве по DOS рекомендуется применять расширенные возможности для новых разработок. В базовой версии DOS команды вывода на экран более сложны, но команды ввода с клавиатуры проще в использовании, благодаря встроен ным проверкам. Ассемблер для IBM PC. Глава 8 175 ВЫВОД НА ЭКРАН: БАЗОВАЯ ВЕРСИЯ DOS ------------------------------------------------------------ Вывод на экран в базовой версии DOS требует определения текстового сообщения в области данных, установки в регистре AH значения 09 (вызов функциии DOS) и указания команды DOS INT 21H. В процессе выполнения операции конец сообщения определяется по oграничителю ($), как это показано ниже: NAMPRMP DB 'Имя покупателя?','$' . . MOV AH,09 ;Запрос вывода на экран LEA DX,NAMPRMP ;Загрузка адреса сообщ. INT 21H ;Вызов DOS Знак ограничителя "$" можно кодировать непосредственно после cимвольной строки (как показано в примере), внутри строки: 'Имя покупателя?$', или в следующем операторе DB '$'. Используя данную операцию, нельзя вывести на экран символ доллара "$". Кроме того, если знак доллара будет отсутство вать в коце строки, то на экран будут выводиться все последующие символы, пока знак "$" не встретиться в памяти. Команда LEA загружает адрес области NAMPRMP в регистр DX для передачи в DOS адреса выводимой информации. Адрес поля NAMPRMP, загружаемый в DX по команде LEA, является oтноси тельным, поэтому для вычисления абсолютного адреса данных DOS складывает значения регистров DS и DX (DS:DX). ПРОГРАММА: ВЫВОД НА ЭКРАН НАБОРА СИМВОЛОВ КОДА ASCII ------------------------------------------------------------ Большинство из 256 кодов ASCII имеют символьное представ ление, и могут быть выведены на экран. Шест. коды 00 и FF не имеют символов и выводятся на экран в виде пробелов, хотя символ пробела имеет в ASCII шест. код 20. На рис. 8.1 показана COM-программа, которая выводит на экран полный набор символов кода ASCII. Программа вызывает три процедуры; B10CLR, C10SET и D10DISP. Процедура B10CLR очищает экран, а процедура C10SET устанавливает курсор в положение 00,00. Процедура D10DISP выводит содержимое поля CTR, которое в начале инициализировано значением 00 и затем yвеличивается на 1 при каждом выводе на экран, пока не достигнет шест. значения FF. ------------------------------------------------------------ ------------------------------------------------------------ Рис. 8.1. Вывод на экран набора символов кода ASCII Так как символ доллара не выводится на экран и кроме того коды от шест. 08 до шест. 0D являются специальными управляющими cимволами, то это приводит к перемещению Ассемблер для IBM PC. Глава 8 176 курсора и другим управляющим воздействиям. Задание: введите программу (рис.8.1), выполните ассемблирование, компановку и преобразование в COM-файл. Для запуска программы введите ее имя, например, В:ASCII.COM. Первая выведенная строка начинается с пробельного символа (шест.00), двух "улыбающихся лиц" (шест. 01 и 02) и трех карточных символов (шест.03, 04 и 05). Код 07 выдает звуко вой сигнал. Код 06 должен отобразиться карточным символом "пики", но управляющие символы от шест.08 до 0D сотрут его. Код 0D является "возвратом каретки" и приводит к переходу на новую (следующую)строку. Код шест.0E - представляется в виде музыкальной ноты. Символы после шест. 7F являются графически ми. Можно изменить программу для обхода управляющих символов. Ниже приведен пример фрагмента программы, позволяющий обойти все символы между шест. 08 и 0D. Вы можете поэкспериментировать, oбходя только, скажем, шест. 08 (возврат на символ) и 0D (возврат каретки): CMP CTR,08H ;Меньше чем 08? JB D30 ; да - принять CMP CTR,0DH ; Меньше/равно 0D? JBE D40 ; да - обойти D30: MOV AH,40H ;Вывод символов < 08 ... ; и > 0D INT 21H D40: INC CTR ВВОД ДАННЫХ С КЛАВИАТУРЫ: БАЗОВАЯ ВЕРСИЯ DOS ------------------------------------------------------------ Процедура ввода данных с клавиатуры проще, чем вывод на экран. Для ввода, использующего базовую DOS, область ввода требует наличия cписка параметров, содержащего поля, которые необходимы при выполнении команды INT. Во-первых, должна быть определена максимальная длина вводимого текста. Это необходимо для предупреждения пользователя звуковым сигна лом, если набран слишком длинный текст; символы, превышающие максимальную длину не принимаются. Во-вторых, в списке параметров должно быть определенное поле, куда команда возвращает действительную длину введенного текста в байтах. Ниже приведен пример, в котором определен список парамет ров для области ввода. LABEL представляет собой директиву с атрибутом BYTE. Первый байт содержит максимальную длину вводимых данных. Так как это однобайтовое поле, то возможное максимальное значение его - шест. FF или 255. Второй байт необходим DOS для занесения в него действительного числа введенных символов. Третьим байтом начинается поле, которое будет содержать введенные символы. NAMEPAR LABEL BYTE ;Список параметров: Ассемблер для IBM PC. Глава 8 177 MAXLEN DB 20 ; Максимальная длина ACTLEN DB ? ; Реальная длина NAMEFLD DB 20 DUP (' ') ; Введенные символы Так как в списке параметров директива LABEL не занимает места, то NAMEPAR и MAXLEN указывают на один и тот же aдрес памяти. В трансляторе MASM для определения списка параметров в виде структуры может использоваться также директива STRUC. Однако, в связи с тем, что ссылки на имена, определенные внутри, требуют специальной адресации, воздержимся cейчас от рассмотрения данной темы до главы 24 "Директивы ассемблера". Для запроса на ввод необходимо поместить в регистр AH номер функции - 10 (шест. 0AH), загрузить адрес списка пара метров (NAMEPAR в нашем примере) в регистр DX и выполнить INT 21H: MOV AH,0AH ;Запрос функции ввода LEA DX,NAMEPAR ;Загрузить адреса списка параметров INT 21H ;Вызвать DOS Команда INT ожидает пока пользователь не введет с клавиа туры текст, проверяя при этом, чтобы число введенных cимво лов не превышало максимального значения, указанного в списке параметров (20 в нашем примере). Для указания конца ввода пользователь нажимает клавишу Return. Код этой клавиши (шест. 0D) также заносится в поле ввода (NAMEFLD в нашем примере). Если, например, пользователь ввел имя BROWN (Return), то cписок параметров будет содержать информацию: дес.: |20| 5| В| R| O| W| N| #| | | | | ... шест.: |14|05|42|52|4F|57|4E|0D|20|20|20|20| ... Во второй байт списка параметров (ACTLEN в нашем примере) команда заносит длину введенного имени - 05. Код Return находится по адресу NAMEFLD +5. Символ # использован здесь для индикации конца данных, так как шест. 0D не имеет отображаемого символа. Поскольку максимальная длина в 20 символов включает шест.0D, то действительная длина вводимого текста может быть только 19 символов. ПРОГРАММА: ВВОД И ВЫВОД ИМЕН ------------------------------------------------------------ EXE-программа, приведенная на рис. 8.2, запрашивает ввод имени, затем отображает в середине экрана введенное имя и включает звуковой сигнал. Программа продолжает запрашивать и отображать имена, пока пользователь не нажмет Return в ответ на очередной запрос. Рассмотрим ситуацию, когда пользователь ввел имя TED SMITH: ------------------------------------------------------------ ------------------------------------------------------------ Рис. 8.2. Ввод и отображение имен Ассемблер для IBM PC. Глава 8 178 1. Разделим длину 09 на 2 получим 4, и 2. Вычтем это значение из 40, получим 36 Команда SHR в процедуре E10CENT сдвигает длину 09 на oдин бит вправо, выполняя таким образом деление на 2. Значение бит 00001001 переходит в 00000100. Команда NEG меняет знак +4 На -4. Команда ADD прибавляет значение 40, получая в регистре DL номер начального столбца - 36. При установке курсора на строку 12 и столбец 36 имя будет выведено на экран в следующем виде: Строка 12: TED SMITH | | Столбец: 36 40 В процедуре E10CODE имеется команда, которая устанавлива ет cимвол звукового сигнала (07) в области ввода непосред ственно после имени: MOV NAMEFLD[BX],07 Предшествующая команда устанавливает в регистре BX значение длины, и команда MOV затем, комбинируя длину в регистре BX и адрес поля NAMEFLD, пересылает код 07. Например, при длине имени 05 код 07 будет помещен по адресу NAMEFLD+05 (замещая значение кода Return). Последняя команда в процедуре E10CODE устанавливает ограничитель "$" после кода 07. Таким образом, когда процедура F10CENT выводит на экран имя, то генериpует ся также звуковой сигнал. Ввод единственного символа Return При вводе имени, превышающего по длине максимальное значение, указанное в списке параметров, возникает звуковой сигнал и система oжидает ввода только символа Return. Если вообще не вводить имя, а только нажать клавишу Return, то система примет ее и yстановит в списке параметров нулевую длину следующим образом: Список параметров (шест.): |14|00|0D|... Для обозначения конца вводимых имен пользователь может прос то нажать Return в ответ на очередной запрос на ввод имени. Прогpамма определяет конец ввода по нулевой длине. Замена символа Return Вводимые значения можно использовать для самых разных целей, например: для печати сообщений, сохранения в таблице, записи на диск. При этом, возможно, появится необходимость замены символа Return (шест.0D) в области NAMEFLD на символ пробела (шест.20). Поле NAMELEN содержит Ассемблер для IBM PC. Глава 8 179 действительную длину или отноcительный адрес кода 0D. Если, например, NAMELEN содержит длину 05, то адрес кода 0D равен NAMEFLD+5. Можно занести эту длину в регистр BX для индексной адресации в поле NAMEFLD: MOV BH,00 ;Установить в регистре BX MOV BL,NAMELEN ; значение 0005 MOV NAMEFLD[BX],20H ;Заменить 0D на пробел Третья команда MOV заносит символ пробела (шест.20) по адресу, oпределенному первым операндом: адрес поля NAMEFLD плюс содержимое регистра BX, т.е. NAMEFLD+5. Очистка области ввода Вводимые символы заменяют предыдущее содержимое области ввода и остаются там, пока другие символы не заменят их. Рассмотрим следующие три успешных ввода имен: Ввод NAMEPAR (шест.) 1. BROWN |14|05|42|52|4F|57|4E|0D|20|20|20| ... |20| 2. HAMILTON |14|08|48|41|4D|49|4C|54|4F|4E|0D| ... |20| 3. ADAMS |14|05|41|44|41|4D|53|0D|4F|4E|0D| ... |20| Имя HAMILTON заменяет более короткое имя BROWN. Но, так как имя ADAMS короче имени HAMILTON, то оно заменяет только HAMIL. Код Return заменяет символ T. Остальные буквы - ON oстаются после имени ADAMS. Для очистки поля NAMEFLD до ввода очередного имени может служить следующая программа: MOV CX,20 ;Установить 20 циклов MOV SI,0000 ;Начальная позиция поля B30: MOV NAMEFLD[si],20H ;Переслать один пробел INC SI ;Следующая позиция поля LOOP B30 ;20 циклов Вместо регистра SI можно использовать DI или BX. Более эффек тивный способ очистки поля, предпологающий пересылку слова из двух пробелов, требует только десять циклов. Однако, ввиду того что поле NAMEFLD определено как DB (байтовое), необходимо изменить длину в команде пересылки, посредством операнда WORD, a также воспользоваться операндом PTR (указатель), как показано ниже: MOV CX,10 ;Установить 10 циклов LEA SI,NAMEFLD ;Начальный адрес B30: MOV WORD PTR[SI],2020H ;Переслать два пробела INC SI ;Получить адрес INC SI ; следующего слова LOOP B30 ;10 циклов Ассемблер для IBM PC. Глава 8 180 Команда MOV по метке B30 обозначает пересылку слова из двух пробелов по адресу, находящемуся в регистре SI. В последнем примеpе используется команда LEA для инициализации регистра SI и несколько иной способ в команде MOV по метке В30, так как нельзя закодировать, например, следующую команду: MOV WORD PTR[NAMEFLD],2020H ;Неправильно Очистка входной области решает проблему ввода коротких имен, за которыми следуют предыдущие данные. Еще более эффек тивный cпособ предпологает очистку только тех байт, которые расположены после введенного имени. ЭКРАННЫЕ И КЛАВИАТУРНЫЕ ОПЕРАЦИИ: РАСШИРЕННАЯ ВЕРСИЯ DOS ------------------------------------------------------------ Рассмотрим теперь расширенные возможности, введенные в DOS 2.0 (реализованные в стиле операционной системы UNIX). Если вы используете более младшую версию DOS, то не сможете выполнить примеры из данного раздела. Расширенные возможнос ти включают файловый номер (file handle), который yстанав ливается в регистре BX, когда требуется выполнить операцию ввода/вывода. Существуют следующие стандартные файловые номера: 0 Ввод (обычно с клавиатуры) CON 1 Вывод (обычно на экран) CON 2 Вывод по ошибке (на экран) CON 3 Ввод/вывод на внешнее устройство AUX 4 Вывод на печать LPT1 или PRN Прерывание DOS для ввода/вывода - INT 21H, необходимая функция запрашивается через регистр AH: шест.3F - для ввода, шест.40 - для вывода. В регистр CX заносится число байт для ввода/вывода, а в регистр DX - адрес области ввода/вывода. В результате успешного выполнения операции ввода/вывода очищается флаг переноса (CF) и в регистр AX устанавливается действительное число байт, участвующих в операции. При неуспешной oперации устанавливается флаг CF, а код ошибки (в данном случае 6) заносится в регистр AX. Поскольку регистр AX может содержать как длину данных, так и код ошибки, то единственный способ определить наличие ошибки - проверить флаг CF, хотя ошибки чтения с клавиатуры и вывода на экран - явления крайне редкие. Аналогичным oбразом используются файловые номера для дисковых файлов, здесь oшибки ввода/вывода встречаются чаще. Можно использовать эти функции для перенаправления ввода- вывода на другие устройства, однако эта особенность здесь не рассматpивается. ВЫВОД НА ЭКРАН: РАСШИРЕННАЯ ВЕРСИЯ DOS ------------------------------------------------------------ Ассемблер для IBM PC. Глава 8 181 Следующие команды иллюстрируют операцию вывода на экран в расширенной версии DOS: DISAREA DB 20 DUP(' ') ;Область данных ... MOV AH,40H ;Запрос на вывод MOV BX,01 ;Выводное устройство MOV CX,20 ;Максимальное число байт LEA DX,DISAREA ;Адрес области данных INT 21H ;Вызов DOS Команда LEA загружает в регистр DX адрес DISAREA для возможности DOS локализовать информацию, предназначенную для вывода. В результате успешной операции флаг переноса очищает ся (это можно проверить), а в регистре AX устанавливается число выведенных символов. Ошибка в данной операции может произойти, если yстановлен неправильный файловый номер. В этом случае будет установлен флаг CF и код ошибки (в данном случае 6) в регистре AX. Поскольку регистр AX может содержать или длину, или код ошибки, то единственный способ определить состояние ошибки - проверить флаг CF. Упражнение: Вывод на экран Воспользуемся отладчиком DEBUG для проверки внутренних эффектов прерывания. Загрузите DEBUG и после вывода на экран приглашения введите A 100 для ввода ассемблерных команд (не машинных коман) по адpесу 100. Не забудьте, что DEBUG предполагает, что все числа вводятся в шеснадцатеричном формате. 100 MOV AH,40 102 MOV BX,01 105 MOV CX,хх (введите длину вашего имени) 108 MOV DX,10E 10B INT 21 10D RET 10E DB 'Ваше имя' программа устанавливает в регистре AH запрос на вывод и устанавливает шест. значение 10F в регистре DX - адрес DB, содержащей ваше имя в конце программы. Когда вы наберете все команды, нажмите еще раз Return. С помощью команды U (U 100,10D) дисассемблируйте программу для проверки. Затем используйте команды R и T для трассиров ки выполнения. При выполнении команды INT 21H отладчик перейдет в BIOS, поэтому при достижении адреса 10B введите команду GO (G 10D) для перехода к команде RET. Ваше имя будет выведено на экран. С помощью команды Q вернитесь в DOS. ВВОД С КЛАВИАТУРЫ: РАСШИРЕННЫЙ DOS ------------------------------------------------------------ Ассемблер для IBM PC. Глава 8 182 Ниже приведены команды, иллюстрирующие использование функции ввода с клавиатуры в расширенной версии DOS: INAREA DB 20 DUP (' ') ;Область ввода MOV AH,3FH ;Запрос на ввод MOV BX,00 ;Номер для клавиатуры MOV CX,20 ;Максимум байт для ввода LEA DX,INAREA ;Адрес области ввода INT 21H ;Вызов DOS Команда LEA загружает относительный адрес INAREA в регистр DX. Команда INT ожидает, пока пользователь не введет cимволы с клавиатуры, но не проверяет превышает ли число введенных символов максимальное значение в регистре CX (20 в приведенном примере). Нажатие клавиши Return (код шест. 0D) указывает на завершение ввода. Например, после ввода текста "PC Users Group" INAREA будет содержать: PC Users Group, шест.0D, шест.0A После введенного текста непосредственно следует символ воз врата коретки (шест. 0D), который был введен, и символ конца строки (шест. 0A), который не был введен. В силу данной особенности максимальное число символов и размер области ввода должны предусматpивать место для двух символов. Если будет введено cимволов меньше максимальноого значения, то область памяти за введенными символами сохранит прежнее значение. В результате успешной операции будет очищен флаг CF (что можно проверить) и в регистре AX будет установлено число байт, введенных с клавиатуры. В предыдущем примере это число будет равно 14 плюс 2 для перевода коретки и конца строки, т.е.16. Соответствующим образом программа может определить действительное число введенных символов. Хотя данное свой ство весьма тривиально для ответов типа YES или NO, оно может быть полезно для ответов с пеpеменной длиной, таких, например, как имена. Ошибка ввода может возникнуть, если определен неправиль ный номер файла. В этом случае будет установлен флаг CF и в регистр AX будет помещен код ошибки (6 в данном случае). Так как регистр AX может содержать или длину введенных данных, или код ошибки, то единственный способ определения наличия ошибки - проверка флага CF. Если вводить текст, который превышает максимальную длину, yстановленную в регистре CX, то будут приниматься все символы. Рассмотрим ситуацию, когда регистр CX содержит 08,а пользователь введет символы "PC Exchange". В результате первые восемь символов "PC Excha" попадут в область ввода без кодов возврата каретки и конца строки. В регистре AX будет установлена длина 08. Следующая команда INT будет принимать данные не с клавиатуры, а из собственного буфера, поскольку там еще остались предыдущие данные. Таким образом, Ассемблер для IBM PC. Глава 8 183 в область ввода будут приняты символы "ngе", символ перевода коретки и символ новой строки, в регистре AX будет установ лено значение 05. Обе операции ввода являются вполне нормаль ными и флаг CF будет очищен. Первый INT: PC Excha AX = 08 Второй INT: ngе,0D,0A AX = 05 Программа может определить факт ввода законченного текста, если а) в регистре AX получится значение меньше, чем в регистре CX или б) если содержимые AX и CX равны, но последние два символа в области ввода - 0D и 0A. Встроенные в DOS проверки по функции 0AH для ввода с клавиатуры имеют более мощные средства. Их выбор для исполь зования в программах является предпочтительным. Упражнение: Ввод данных Выполним упражнение в котором можно проследить операцию ввода c клавиатурры с помощью отладчика DEBUG. Предполагае мая программа позволяет вводить до 12 символов, включая символы конца каретки и конца строки. Загрузите DEBUG и после вывода на экран приглашения введите A 100 для ввода ассемблерных команд, начиная c адреса 100. Не забудьте, что DEBUG предпологает, что все числа вводятся в шеснадцатиричном формате. 100 MOV AH,3F 102 MOV BX,00 105 MOV CX,0C 108 MOV DX,10F 10B INT 21 10D JMP 100 10F DB ' ' Программа устанавливает регистры AH и BX для запроса на ввод c клавиатуры, заносит максимальную длину ввода в ре гистр CX и загружает в регистр DX значение 10F - область DB в конце программы. В эту область будут помещаться вводимые символы. Когда вы наберете все команды, нажмите еще раз Return. С помощью команды U 100,108 выполните дисассемблирование программы для проверки. Затем используйте команды R и T для трассировки четырех команд MOV. Остановившись по адресу 10B, введите G 10D для выполнения команды INT (входить в BIOS не следует). Теперь отладчик позволит ввести данные, завершаемые клавишей Return. Проверьте содержимое регистра AX, состояние флага CF и используя команду D 10F, просмот рите введенные данные в памяти. Для завершения работы введите команду Q. ИСПОЛЬЗОВАНИЕ СИМВОЛОВ ВОЗВРАТА КАРЕТКИ, КОНЦА СТРОКИ И ТАБУЛЯЦИИ ДЛЯ ВЫВОДА НА ЭКРАН Ассемблер для IBM PC. Глава 8 184 ------------------------------------------------------------ Ассемблер для IBM PC. Глава 9 200 ГЛАВА 9. Экранные операции II: Расширенные возможности ------------------------------------------------------------ Экранные операции II: Расширенные возможности Цель: Показать более развитые возможности управления экраном, включая прокрутку, инвертирование, мигание, а также использование скэн-кодов для ввода с клавиатуры. ВВЕДЕНИЕ ------------------------------------------------------------ В главе 8 были показаны основные возможности системы для управления выводом на экран и ввода с клавиатуры. В данной главе приводятся более развитые возсожности, обеспечисающие прокрутку данных на экране и установку байта-атрибута для подчеркивания, мигания, выделения яркости. Материал первого раздела этой главы (по прерыванию BIOS 10) подходит, как для монохромных, так и для цветных дисплеев. Другие расширенные возможности включают использование cкэн-кодов для определения нажатой клавиши или комбинации клавишей на клавиатуре. Монохромный дисплей Для работы монохромного дисплея имеется память объемом 4К, начинающаяся по адресу шест. B0000 (дисплейный буфер). Эта память обеспечивает: - 2К для символов на экране(25 строк х 80 столбцов); - 2К для байтов-атрибутов, обеспечивающих инвертирование, мигание, выделение яркостью и подчеркивание. Цветной/графический дисплей Для работы стандартного цветного графического дисплея имеется 16 Кбайт памяти (дисплейный буфер), начинающийся по адресу шест.B8000. Такой дисплей может являться текстовым (для нормального ASCII-кода) или графическим и работать как в цветном, так и в черно-белом (BW) режиме. Дисплейный буфер обеспечивает экpанные страницы, пронумерованные от 0 до 3 для экрана на 80 cтолбцов и от 0 до 7 для экрана на 40 столбцов. Номер страницы по умолчанию - 0. В следующей главе будет подробно рассмотрено управление цветом и графикой. БАЙТ АТРИБУТОВ ------------------------------------------------------------ Байт атрибутов, как для монохромного, так и для графичес кого дисплея в текстовом (не графическом) режиме определяет характеристики каждого отображаемого символа. Байт-атрибут имеет следующие 8 бит: Ассемблер для IBM PC. Глава 9 201 Фон Текст Атрибут: BL R G B I R G B Номер битов: 7 6 5 4 3 2 1 0 Буквы RGB представляют битовые позиции, управляющие красным (red), зеленым (green) и синим (blue) лучем в цветном моноторе. Бит 7 (BL) устанавливает мигание, а бит 3 (I) - уровень яркости. На монохромных мониторах текст высвечивается зеленым или оранжевым на темном фоне, хотя в данной главе такое изображение называется черно-белым (BW). Для модификации атрибутов можно комбинировать биты следующим oбразом: Эффект выделения Фон Текст RGB RGB Неотображаемый (черный по черному) 000 000 Подчеркивание (не для цвета) 000 001 Нормальный (белый по черному) 000 111 Инвертированный (черный по белому) 111 000 Цветные мониторы не обеспечивают подчеркивания; вместо этого установка бит подчеркивания выбирает синий цвет для текста и получается отображение синим по черному. Ниже приведены некоторые атрибуты, основанные на комбинации битов фона, текста, мигания и выделения яркостью: Двоичный Шест. Эффект выделения код код 0000 0000 00 Неотображаемый (для паролей) 0000 0111 07 Белый по черному (нормальный) 1000 0111 87 Белый по черному (мигание) 0000 1111 0F Белый по черному (яркий) 0111 0000 70 Черный по белому (инвертированый) 1111 0000 F0 Черный по белому (инверт. мигающий) Эти атрибуты подходят для текстового режима, как для моно хромных, так и для цветных дисплеев. В следующей главе будет показано, как выбирать конкретные цвета. Для генерации атри бута можно использовать команду INT 10H. При этом регистр BL должен содержать значение байта-атрибута, а регистр AH один из следующих кодов: 06 (прокрутка вверх), 07 (прокрутка вниз), 08 (ввод атрибута или символа), 09 (вывод атрибута или символа). Если программа установила некотоpый атрибут, то он остается таким, пока программа его не изменит. Если установить значение байта атрибута равным шест.00, то символ вообще не будет отображен. ПРЕРЫВАНИЕ BIOS INT 10H ------------------------------------------------------------ Ассемблер для IBM PC. Глава 9 202 Прерывание INT 10H обеспечивает управление всем экраном. В регистре AH устанавливается код, определяющий функцию прерывания. Команда cохраняет содержимое регитров BX, CX, DX, SI и BP. Ниже описывается все возможные функции. AH=00: Установка режима. Данная функция позволяет пере ключать цветной монитор в текстовый или графический режим. Установка pежима для выполняемой в текущий момент программы осуществляется c помощью INT 10H. При установке происходит очистка экрана. Содержимое регистра AL может быть следующим: 00 40 х 25 черно-белый текстовый режим 01 40 х 25 стандартный i6-цветовой текстовый режим 02 80 х 25 черно-белый текстовый режим 03 80 х 25 стандартный 16-цветовой текстовый режим 04 320 х 200 стандартный 4-цветовой графический режим 05 320 х 200 черно-белый графический режим 06 640 х 200 черно-белый графический режим 07 80 х 25 черно-белый стандартный монохромный 08 - 0A форматы для модели PCjr 0D 320 х 200 16-цветовой графический режим (EGA) 0E 640 х 200 16-цветовой графический режим (EGA) 0F 640 х 350 черно-белый графический режим (EGA) 10 640 х 350 64-цветовой графический режим (EGA) EGA (Enhanced Graphics Adapter) - обозначает усовершенст вованный графический адаптер. Следующий пример показывает установку стандартного 16-цветового текстового режима MOV AH,00 ;Функция установки режима MOV AL,03 ;Стандартный цветной текст 80 х 25 INT 10H ;Вызвать BIOS Для определения типа адаптера, установленного в системе, служит прерывание BIOS INT 11H. Данная команда возвращает в регистре AX значение, в котором биты 5 и 4 указывают на видео режим: 01 40 х 25 черно-белый режим в цветном адаптере 10 80 х 25 черно-белый режим в цветном адаптере 11 80 х 25 черно-белый режим в черно-белом адаптере Программа, работающая с неизвестным типом монитора, может провеpить тип по регистру AX после INT 11H и затем устано вить необходимый режим. AH=01: Установка размера курсора. Курсор не является символом из набора ASCII-кодов. Компьютер имеет собственное аппаратное обеспечение для управления видом курсора. Для этого имеется специальная обработка по INT прерыванию. Обычно символ курсоpа похож на символ подчеркивания. Используя INT 10H, можно управлять вертикальным размером курсора: биты 4-0 в регистре CH для верхней линии Ассемблер для IBM PC. Глава 9 203 сканирования, а биты 4-0 в регистре CL - для нижней. Можно установить любой pазмер курсора по вертикали: от 0 до 13 для монохромных и EGA монитоpов и от 0 до 7 для большинства цветных мониторов. Приведем пример для увеличения размера курсора от его верхней до нижней линии сканирования: MOV AH,01 ;Установить размер курсора MOV CH,00 ;Верхняя линия сканирования MOV CL,13 ;Нижняя линия сканирования INT 10H ;Вызвать BIOS В результате выполнения этих команд курсор превратится в сплошной мигающий прямоугольник. Можно установить любой размер курсора между верхней и нижней границами, например, 04/08, 03/10 и т.д. Курсор сохраняет свой вид, пока программа не изменит его. Использование размеров 12/13 (для моно) и 6/7 (для цвета) переводит курсор в его нормальный вид. AH=02: Установка позиции курсора. Эта функция устанавлива ет курcор в любую позицию на экране в соответствии с коорди натами cтроки и столбца. Номер страницы обычно равен 0, но может иметь значение от 0 до 3 при 80 столбцах на экране. Для установки позиции курсора необходимо занести в регистр AH значение 02, в регистр BH номер страницы и в регистр DX координаты строки и столбца: MOV AH,02 ;Установить положение курсора MOV BH,00 ;Страница 0 MOV DH,строка ;Строка MOV DL,столбец ;Столбец INT 10H ;Вызвать BIOS AH=03: Чтение текущего положения курсора. Программа может определить положение курсора на экране (строку и столбец), а также pазмер курсора, следующим образом: MOV AH,03 ;Определить положение курсора MOV BH,00 ;Установить страницу 0 INT 10H ;Вызвать BIOS После возврата регистр DH будет содержать номер строки, а регистр DL - номер столбца. В регистре CH будет верхняя линия cканирования, а в регистре CL - нижняя. AH=04: Чтение положения светового пера. Данная функция используeтся в графическом режиме для определения положения светового пеpа. AH=05: Выбор активной страницы. Новая страница устанавли вается для цветных текстовых режимов от 0 до 3. Для режима 40 х 25 возможно устанавливать до 8 страниц (от 0 до 7), а для режима 80 х 25 - до 4 страниц (от 0 до 3). Ассемблер для IBM PC. Глава 9 204 MOV AH,05 ;Установить активную страницу MOV AL,страница ;Номер страницы INT 10H ;Вызвать BIOS AH=06: Прокрутка экрана вверх. Когда программа пытается выдать текст на строку ниже последней на экране, то происхо дит переход на верхнюю строку. Даже если с помощью прерыва ния будет специфиpован нулевой столбец, все равно предпола гается новая строка, и нижние строки на экране будут испорчены. Для решения этой проблемы используется прокрутка экрана. Ранее код 06 использовался для очистки экрана. В тексто вом режиме установка в регистре AL значения 00 приводит к полной прокрутке вверх всего экрана, очищая его пробелами. Установка ненулевого значения в регистре AL определяет количество строк прокрутки экрана вверх. Верхние строки уходят с экрана, а чистые строки вводятся снизу. Следующие команды выполняют прокрутку всего экрана на одну строку: MOV AX,0601H ;Прокрутить на одну строку вверх MOV BH,07 ;Атрибут: нормальный, черно-белый MOV CX,0000 ;Координаты от 00,00 MOV DX,184FH ; до 24,79 (полный экран) INT 10H ;Вызвать BIOS Для прокрутки любого количества строк необходимо устано вить соответствующее значение в регистре AL. Регистр BH содержит атрибут для нормального или инвертированного отобра жения, мигания, установки цвета и т.д. Значения в регистрах CX и DX позволяют прокручивать любую часть экрана. Ниже объясняется стандартный подход к прокрутке: 1. Определить в элементе ROW (строка) значение 0 для установки строки положения курсора. 2. Выдать текст и продвинуть курсор на следующую строку. 3. Проверить, находится ли курсор на последней строке (CMP ROW,22). 4. Если да, то увеличить элемент ROW (INC ROW) и выйти. 5. Если нет, то прокрутить экран на одну строку и, исполь зуя ROW переустановить курсор. AH=07: Прокрутка экрана вниз. Для текстового режима прокрутка экрана вниз обозначает удаление нижних строк и вставка чистых строк сверху. Регистр AH должен содержать 07, значения остальных регистpов аналогичны функции 06 для прокрутки вверх. AH=08: Чтение атрибута/символа в текущей позиции курсора. Для чтения символа и байта атрибута из дисплейного буфера, как в текстовом, так и в графическом режиме используются следующие команды: Ассемблер для IBM PC. Глава 9 205 MOV AH,08 ;Запрос на чтение атр./симв. MOV BH,00 ;Страница 0 (для текстового реж.) INT 10H ;Вызвать BIOS Данная функция возвращает в регистре AL значение символа, а в AH - его атрибут. В графическом режиме функция возвращает шест. 00 для не ASCII-кодов. Так как эта функция читает только один cимвол, то для символьной строки необходима организация цикла. AH=09: Вывод атрибута/символа в текущую позицию курсора. Для вывода на экран символов в текстовом или графическом режиме с установкой мигания, инвертирования и т.д. можно воспользоваться следующими командами: MOV AH,09 ;Функция вывода MOV AL,символ ;Выводимый символ MOV BH,страница ;Номер страницы (текст.реж.) MOV BL,атрибут ;Атрибут или цвет MOV CX,повторение ;Число повторений символа INT 10H ;Вызвать BIOS В регистр AL должен быть помещен выводимый на экран символ. Значение в регистре CX определяет число повторений символа на экране. Вывод на экран последовательности различных симво лов требует организации цикла. Данная функция не перемещает курсор. В следующем примере на экран выводится пять мигающих "сердечек" в инвертированном виде: MOV AH,09 ;Функция вывода MOV AL,03H ;Черви (карточная масть) MOV BH,00 ;Страница 0 (текст. режим) MOV BL,0F0H ;Мигание, инверсия MOV CX,05 ;Пять раз INT 10H ;Вызвать BIOS В текстовом (но не в графическом) режиме символы автомати чески выводятся на экран и переходят с одной строки на другую. Для вывода на экран текста запроса или сообщения необходимо составить программу, которая устанавливает в регистре CX значение 01 и в цикле загружает в регистр AL из памяти выводимые символы текста. Так как регистр CX в данном случае занят, то нельзя использовать команду LOOP. Кроме того, при выводе каждого символа необходимо дополнительно продвигать курсор в следующий столбец (функция 02). В графическом режиме регистр BL используется для определе ния цвета графики. Если бит 7 равен 0, то заданный цвет заме няет текущий цвет точки, если бит 7 равен 1, то происходит комбинация цветов с помощью команды XOR. AH=0A: Вывод символа в текущую позицию курсора. Единствен ная разница между функциями 0A и 09 состоит в том, что функция 0A не устанавливает атрибут: Ассемблер для IBM PC. Глава 9 206 MOV AH,0AH ;Функция вывода MOV AL,символ ;Выводимый символ MOV BH,страница ;Номер страницы (для текста) MOV CX,повторение ;Число повторений символа INT 10H ;Вызвать BIOS Для большинства применений команда прерывания DOS INT 21H более удобна. AH=0E: Вывод в режиме телетайпа. Данная функция позволяет использовать монитор, как простой терминал. Для выполнения этой функции необходимо установить в регистре AH шест. значение 0E, в pегистр AL поместить выводимый символ, цвет текста (в графическом режиме) занести в регистр BL и номер страницы для текстового режима - в регистр BH. Звуковой сигнал (код 07H), возврат на одну позицию (08H), конец строки (0AH) и возврат каретки (0DH) действуют, как команды для форматизации экрана. Данная функция автоматически продви гает курсор, переводит символы на следующую cтроку, выполня ет прокрутку экрана и сохраняет текущие атрибуты экрана. AH=0F: Получение текущего видео режима. Данная функция возвращает в регистре AL текущий видео режим (см.функцию AH=00), в pегистре AH - число символов в строке (20, 40 или 80), в регистре BH - номер страницы. AH=13: Вывод символьной строки (только для AT). Данная функция позволяет на компьютерах типа AT выводить на экран символьные строки с установкой атрибутов и перемещением курсора: MOV AH,13H ;Функция вывода на экран MOV AL,сервис ;0, 1, 2 или 3 MOV BH,страница ; LEA BP,адрес ;Адрес строки в ES:BP MOV CX,длина ;Длина строки MOV DX,экран ;Координаты на экране INT 10H ;Вызвать BIOS Возможен следующий дополнительный сервис: 0 - использовать атрибут и не перемещать курсор; 1 - использовать атрибут и переместить курсор; 2 - вывести символ, затем атрибут и не перемещать курсор; 3 - вывести символ, затем атрибут и переместить курсор. ПРОГРАММА: МИГАНИЕ, ИНВЕРСИЯ И ПРОКРУТКА ------------------------------------------------------------ Ассемблер для IBM PC. Глава 9 207 Программа, приведенная на рис. 9.1, принимает ввод имен с клавиатуры и выводит их на экран. Запрос выдается в инвертированном отображении, имена принимаются в нормальном отображении, а вывод имен осуществляется с 40 столбца в той же строке с миганием и инвертированием: Name? Francis Bacon Francis Bacon [мигание] | | Столбец 0 Столбец 40 Для управления положением курсора в программе определены переменные ROW (вертикальное перемещение вниз) и COL (гори зонтальное перемещение вправо). Команда INT 10H не перемеща ет курсор автоматически. Программа выводит имена сверху вниз, пока не достигнет 20-й строки. После этого выполняется прокрутка экрана вверх на одну строку для каждого нового запроса. Для ввода имен в процедуре D10INPT используется команда DOS INT 21H. Для замены на BIOS INT 10H необходимо: 1. Инициализировать счетчик для адреса области ввода и счетчик для длины имени. 2. Выполнить INT 10H (функция 08) с 08 в регистре AH и 00 в BH. Функция возвращает каждый символ в регистре AL. 3. Если регистр AL не содержит символа RETURN и счетчик длины достиг максимального значения, выдать звуковой сигнал и выйти из процедуры. 4. Переслать содержимое AL в область ввода имени. 5. Если регистр AL содержит символ RETURN, выйти из процедуры. 6. Увеличить счетчик длины и адрес области ввода имени. 7. Переместить курсор на один столбец. 8. Перейти на пункт 2. При выходе из процедуры область ввода содержит имя и символ RETURN, а счетчик - число введенных символов. РАСШИРЕННЫЙ ASCII КОД ------------------------------------------------------------ ASCII-коды от 128 до 255 (шест. 80-FF) представляют собой ряд специальных символов полезных при формировании запросов, меню, специальных значков с экранными атрибутами. Например, используя cледующие символы можно нарисовать прямоугольник: Шест. Символ DA Верхний левый угол BF Верхний правый угол C0 Нижний левый угол D9 Нижний правый угол C4 Горизонтальная линия B3 Вертикальная линия Ассемблер для IBM PC. Глава 9 208 Следующие команды с помощью INT 10H выводят горизонталь ную линию на 25 позиций в длину: MOV AH,09 ;Функция вывода на экран MOV AL,0C4H ;Горизонтальная линия MOV BH,00 ;Страница 0 MOV BL,0FH ;Выделение яркостью MOV CX,25 ;25 повторений MOV 10H ;Вызвать BIOS Напомним, что курсор не перемещается. Вывод вертикальной линии включает цикл, в котором курсор перемещается вниз на одну строку и выводится символ шест. B3. Для штриховки может быть полезен символ с точками внутри: Шест. Символ B0 Одна четверть точек (светлая штриховка) B1 Половина точек (средняя штриховка) B2 Три четверти точек (темная штриховка) ------------------------------------------------------------ ------------------------------------------------------------ Рис. 9.1. Мигание, инвертирование и прокрутка Можно извлечь много полезных идей, изучая программное обеспечение с профессионально организованным выводом, или самому изобрести оригинальные идеи для отображения информации. ДРУГИЕ ОПЕРАЦИИ ВВОДА/ВЫВОДА В DOS ------------------------------------------------------------ Ниже перечислены другие функции DOS, которые могут оказаться полезными в работе. Код функции устанавливается в регистре AH и, затем, выдается команда INT 21H. AH=01: Ввод с клавиатуры с эхо отображением. Данная функ ция возвращает значение в регистре AL. Если содержимое AL не равно нулю, то оно представляет собой стандартный ASCII- cимвол, например, букву или цифру. Нулевое значение в регист ре AL свидетельствует о том, что на клавиатуре была нажата специальная функциональная клавиша, например, Номе, F1 или PgUp. Для определения скэн-кода клавиш, необходимо повторить вызов функции (см. "Дополнительные функциональные клавиши" в последующих разделах). Данная функция реагирует на запрос Ctrl/Break. AH=02: Вывод символа. Для вывода символа на экран в текущую позицию курсора необходимо поместить код данного символа в pегистр DL. Коды табуляции, возврата каретки и конца строки действуют обычным образом. Ассемблер для IBM PC. Глава 9 209 AH=07: Прямой ввод с клавиатуры без эхо отображения. Дан ная функция работает аналогично функции 01 с двумя отличия ми: введенный символ не отображается на экране, т.е. нет эхо, и oтсутствует реакция на запрос Ctrl/Break. AH=08: Ввод с клавиатуры без эхо отображения. Данная функ ция действует аналогично функции 01 с одним отличием: введенный символ не отображается на экран, т.е. нет эхо. AH=0B: Проверка состояния клавиатуры. Данная функция возвращает шест.FF в регистре AL, если ввод с клавиатуры возможен, в противном случае - 00. Это средство связано с функциями 01, 07 и 08, которые не ожидают ввода с клавиатуры. ВВОД С КЛАВИАТУРЫ ПО КОМАНДЕ BIOS INT 16H ------------------------------------------------------------ Команда BIOS INT 16H выполняет специальную операцию, которая в соответствии с кодом в регистре AH обеспечивает следующие три функции ввода с клавиатуры. AH=00: Чтение символа. Данная функция помещает в регистр AL oчередной ASCII символ, введенный с клавиатуры, и устанавливает скэн код в регистре AH. (Скэн-коды объясняются в следующем разделе). Если на клавиатуре нажата одна из специальных клавишей, например, Номе или F1, то в регистр AL заносится 00. Автоматическое эхо символа на экран по этой функции не происходит. AH=01: Определение наличия введенного символа. Данная функция сбрасывает флаг нуля (ZF=0), если имеется символ для чтения с клавиатуры; очередной символ и скэн-код будут помещены в регистры AL и AH соответственно и данный элемент останется в буфере. AH=02: Определение текущего состояния клавиатуры. Данная функция возвращает в регистре AL состояние клавиатуры из адреса памяти шест. 417: Бит 7 Состояние вставки активно (Ins) 6 Состояние фиксации верхнего регистра (Caps Lock) переключено 5 Состояние фиксации цифровой клавиатуры (Num Lock) переключено 4 Состояние фиксации прокрутки (Scroll Lock) переключено 3 Нажата комбинация клавишей Alt/Shift 2 Нажата комбинация клавишей Ctrl/Shift 1 Нажата левая клавиша Shift 0 Нажата правая клавиша Shift Ассемблер для IBM PC. Глава 9 210 ФУНКЦИОНАЛЬНЫЕ КЛАВИШИ ------------------------------------------------------------ Клавиатура располагает тремя основными типами клавишей: 1. Символьные (алфавитно-цифровые) клавиши: буквы от a до z, цифры от 0 до 9, символы %, $, # и т.д. 2. Функциональные клавиши: Номе, End, Возврат на позицию, стрелки, Return, Del, Ins, PgUp, PgDn и программно- функциональные клавиши. 3. Управляющие клавиши: Alt, Ctrl и Shift, которые работают совместно с другими клавишами. Функциональная клавиша не вырабатывает какой-либо символ, но чаще формирует запрос на некоторые действия. Аппаратная реализация не требует от функциональных клавишей выполнения каких-либо специфических действий. Задачей программиста является определить, например, что нажатие клавиши Номе должно присести к установке курсора в верхний левый угол экрана, или нажатие клавиши End должно установить курсор в конец текста на экране. Можно легко запрограммировать функциональные клавиши для выполнения самых различных действий. Каждая клавиша имеет собственный скэн-код от 1 (Esc) до 83 (Del) или от шест.01 до шест.53. Посредством этих скэн- кодов программа может определить нажатие любой клавиши. Нпример, запрос на ввод одного символа с клавиатуры включает загрузку 00 в регистр AH и обращение к BIOS через INT 16H: MOV AH,00 ;Функция ввода с клавиатуры INT 16H ;Вызвать BIOS Данная операция имеет два типа ответов в зависимости от того, нажата символьная клавиша или функциональная. Для символа (например, буква A) клавиатура посылает в компьютер два элемента информации: 1. ASCII-код символа A (шест.41) в регистре AL; 2. Скэн-код для клавиши A (шест.1E) в регистре AH. Если нажата функциональная клавиша (например, Ins) клавиатура также передает два элемента: 1. Нуль в регистре AL; 2. Сскэн-код для клавиши Ins (шест.52) в регистре AH. Ассемблер для IBM PC. Глава 9 211 Таким образом, после выполнения команы INT 16H необходимо прежде проверить содержимое регистра AL. Если AL содержит нуль, то была нажата функциональная клавиша, если не нуль, то получен код символьной клавиши. Ниже приведен пример такой проверки: MOV AH,00 ;Функция ввода INT 16H ;Вызвать BIOS CMP AL,00 ;Функциональная клавиша? JZ exit ; да - выйти Скэн-Коды На рис. 9.2 приведены скэн-коды для некоторых функциональ ных клавишей. Клавиатура имеет по две клавиши для таких символов как *, + и -. Нажатие "звездочки", например, устанавливает код символа шест.2A в регистре AL и один из двух скэн-кодов в регистре AH в зависимости от того, какая из клавишей была нажата: шест.09 для звездочки над цифрой 8 или шест.29 для звездочки на клавише PrtSc. Ниже приведена логика проверки скэн-кода для звездочки: CMP AL,2AH ;Звездочка? JNE EXIT1 ; нет - выйти CMP AH,09H ;Какой скэн-код? JE EXIT2 ------------------------------------------------------------ Функциональные клавиши Скэн-коды Alt/A - Alt/Z 1E - 2C F1 - F10 3B - 44 Home 47 Стрелка вверх 48 PgUp 49 Стрелка влево 4B Стрелка вправо 4D End 4F Стрелка вниз 50 PgDn 51 Ins 52 Del 53 ------------------------------------------------------------ Рис. 9.2. Скэн-коды некоторых функциональных клавишей Приведем пример программы для установки курсора в строку 0 и cтолбец 0 при нажатии клавиши Номе (скэн-код 47): MOV AH,00 ;Выполнить ввод с клавиатуры INT 16H ; CMP AL,00 ;Функциональная клавиша? JNE EXIT1 ; нет -- выйти CMP AH,47H ;Скэн-код для клавиши Home? Ассемблер для IBM PC. Глава 9 212 JNE EXIT2 ; нет -- выйти MOV AH,02 ; MOV BH,00 ;Установить курсор MOV DX,00 ; по координатам 0,0 INT 10H ;Вызвать BIOS Функциональные клавиши F1 - F10 генерируют скэн-коды от шест.3B до шест.44. Следующий пример выполняет проверку на функциональную клавишу F10: CMP AH,44H ;Клавиша F10? JE EXIT1 ; Да По адресу EXIT1 программа может выполнить любое необходимое действие. Полный список скэн-кодов приводится в руководстве по языку BASIC. Техническое описание IBM PC содержит подробное описание всех скэн-кодов, а также описание использования клавишей Alt, Ctrl и Shift. ОСНОВНЫЕ ПОЛОЖЕНИЯ НА ПАМЯТЬ ------------------------------------------------------------ ъ Монохромный дисплей использует 4К байт памяти, 2К байт на символы и 2К байт на атрибуты для каждого символа. ъ Цветной дисплей использует 16К байт памяти и может рабо тать в цветном или черно-белом (BW) режимах. Возможно использование, как текстового режима для отображения ASCII-символов, так и графического режима для любых изображений. ъ Байт-атрибут используется и для монохромных дисплеев и для цветных в текстовом режиме. Атрибут обеспечивает мигание, инвертирование и выделение яркостью. Для цветных дисплеев в текстовом режиме биты RGB позволяют выбирать цвета, но не имеют режима подчеркивания. ъ Команда BIOS INT 10H обеспечивает полную экранную обработку: установку режимов, установку положения курсора, прокрутку экрана, чтение с клавиатуры и вывод на экран. ъ Если ваша программа выводит вниз экрана, то не забывай те выполнять прокрутку прежде, чем курсор выйдет из последней строки. ъ При использовании атрибутов для мигания и инвертирова ния, не забывайте сбрасывать их в отключенное состояние. ъ Для функций по команде INT 10H, выплняющих чтение и вывод на экран, помните о перемещении курсора. ъ Команда BIOS INT 16H обеспечивает прием и распознавание функциональных клавишей. ъ Функциональные клавиши предполагают запрограммированный вызов некоторых действий. Ассемблер для IBM PC. Глава 9 213 ъ Каждая клавиша на клавиатуре имеет конкретный скэн-код, пронумерованный от 1 (Esc) до 83 (Del), или от шест.01 до шест.53. ъ Нажатие символьной клавиши на клавиатуре передает код символа в регистр AL и скэн-код клавиши в регистр AH. ъ Нажатие функциональной клавиши на клавиатуре передает нуль в регистр AL и скэн-код клавиши в регистр AH. ВОПРОСЫ ДЛЯ САМОПРОВЕРКИ ------------------------------------------------------------ 9.1. Определите атрибуты экрана для а) мигания с подчеркива нием, б) нормальной яркости, в) инвертирования с выделением яркостью. 9.2. Составте процедуры для а) установки режима экрана BW (черно-белый) на 80 столбцов, б) установки вида курсо ра, начинающегося на 5 линии сканирования и заканчиваю щегося на 12 линии, в) прокрутки экрана на 10 строк, г) вывода десяти мигающих символов штриховки с половиной точек (шест. B1). 9.3. Напишите скэн-коды для следующих функциональных клавишей: а) стрелка вверх, б) клавиша F3, в) Home, г) PgUp. 9.4. Используя отладчик DEBUG, проверте воздействие на содер жимое регистра AX при нажатии клавишей на клавиатуре. Для ввода ассемблерных команд используйте команду A 100 (Return). Ведите следующие команды: MOV AH,00 INT 16H JMP 100 Используя команду U 100,104, дисассемблируйте программу и с помощью G 104 выполните команды MOV и INT. На команде INT выполнение программы остановиться и система перейдет в ожидание вашего ввода. Для проверки регистра AH нажмите любую клавишу. Продолжая вводить команду G 104, и, нажимая различные клавиши, проверьте работу программы. Для выхода введите команду Q. 9.5. Составте команды для определения нажатия клавиши: если нажата клавиша PgDn, то необходимо установить курсор по координатам - строка 24 и столбец 0. Ассемблер для IBM PC. Глава 10 228 ГЛАВА 10. Экранные операции III: Цвет и графика ------------------------------------------------------------ Экранные операции III: Цвет и графика Цель: Показать расширенные возможности компьютера, связанные с использованием цвета и графики на экране. ВВЕДЕНИЕ ------------------------------------------------------------ Данная глава знакомит с использованием цвета для текстово го и графического режимов. Существуют следующие три типа видео монитоpов, используемые для изображения цветной графики (в порядке возpастания стоимости и качества): 1. Немодифицированный цветной телевизионный приемник (обычный домашний телевизор), применяемый многими для своих компьютеров. 2. Комбинированный видеомонитор, принимающий цветовой сигнал без радиочастотной модуляции, и используемый для передачи по радиоволнам. Обеспечивает высокое качество изображения. 3. RGB-монитор, посылающий входные сигналы на три раздель ные электронные пушки - красную, зеленую и синию для каждого из трех основных цветов. Являясь наиболее дорогим, RGB-монитор обеспечивает наилучшее качество изображения. Стандартный адаптер для цветного графического монитора (CGA - Color/Graphics Adapter) использует 16К байт памяти, начинающейся по адресу шест.B8000, 8К байт - для символов и 8К байт для их атрибутов. При работе в формате 80х25 адаптер может хранить четыре страницы (0-3) дисплейного буфера по 4К байт каждая. При работе в формате 40х25 адаптер может хранить восемь страниц (0-7) по 2К байт каждая. По умолчанию используется нулевая страница (в начале дисплейной памяти). Программа может вывести на экран любую страницу и в это время формировать другую страницу в памяти для последующего вывода на экран. Усовершенствованный графический адаптер (EGA - Enhanced Graphics Adapter) обеспечивает более высокую разрешающую способность, по сравнению со стандартным цветным адаптером (CGA) и в большинстве случаев является совместимым с ним. Разрешающая способность обеспечивает 320х200, 640х200 и 640х350 точек на экране. Цветные адаптеры имеют два основных режима работы: текстовой (алфовитно-цифровой) и графический, и возможны также дополнительные режимы между двумя основными. По умолчанию используется текстовой режим. Установка режима описана в главе 9 в разделе "Преpывание BIOS INT 10H" Ассемблер для IBM PC. Глава 10 229 (AH=0). Для установки графического режима или возврата в текстовой режим используется прерывание BIOS INT 10H, как это показано в двух следующих примерах: MOV AH,00 ;Режим MOV AH,00 ;Режим MOV AL,03 ;Цвет+текст MOV AL,04 ;Графика среднего INT 10H INT 10H ; разрешения ТЕКСТОВЫЙ (АЛФАВИТНО-ЦИФРОВОЙ) РЕЖИМ ------------------------------------------------------------ Текстовой режим предназначен для обычных вычислений с вы водом букв и цифр на экран. Данный режим одинаков для черно- белых (BW) и для цветных мониторов за исключением того, что цветные мониторы не поддерживают атрибут подчеркивания. Текстовой режим обеспечивает работу с полным набором ASCII кодов (256 символов), как для черно-белых (BW), так и для цветных мониторов. Каждый символ на экране может отображать ся в одном из 16 цветов на одном из восьми цветов фона. Бордюр экрана может иметь также один из 16 цветов. Цвета Тремя основными цветами являются красный, зеленый и синий. Комбинируя основные цвета, друг с другом, можно получить восемь цветов, включая черный и белый. Используя два уровня яркости для каждого цвета, получим всего 16 цветов: I R G B I R G B Черный 0 0 0 0 Серый 1 0 0 0 Синий 0 0 0 1 Ярко-синий 1 0 0 1 Зеленый 0 0 1 0 Ярко-зеленый 1 0 1 0 Голубой 0 0 1 1 Ярко-голубой 1 0 1 1 Красный 0 1 0 0 Ярко-красный 1 1 0 0 Сиреневый 0 1 0 1 Ярко-сиреневый 1 1 0 1 Коричневый 0 1 1 0 Желтый 1 1 1 0 Белый 0 1 1 0 Ярко-белый 1 1 1 1 Таким образом любые символы могут быть отображены на экране в oдном из 16 цветов. Фон любого символа может иметь один из первых восьми цветов. Если фон и текст имеют один и тот же цвет, то текст получается невидимым. Используя байт атрибута, можно получить также мигающие символы. Байт-атрибут Текстовой режим допускает использование байта атрибута, рассмотpенного в главе 9. В приведенной ниже таблице, атрибут BL обозначает мигание (BLinking), RGB - соответствен но красный, зеленый и синий цвет, I - выделение яркостью: Фон Текст Ассемблер для IBM PC. Глава 10 230 Атрибут: BL R G B I R G B Номера битов: 7 6 5 4 3 2 1 0 Мигание и выделение яркостью относится к тексту. Ниже приведены некоторые типичные атрибуты: Текст по фону Бит: 7 6 5 4 3 2 1 0 BL R G B I R G B Шест. Черный по черному 0 0 0 0 0 0 0 0 00 Синий по черному 0 0 0 0 0 0 0 1 01 Красный по синему 0 0 0 1 0 1 0 0 14 Голубой по зеленому 0 0 1 0 0 0 1 1 23 Светло-сиреневый по белому 0 1 1 1 1 1 0 1 7D Серый по зеленому, мигание 1 0 1 0 1 0 0 0 A8 Байт-атрибут используется аналагично показанному для черно-белого (BW) монитора. Тип монитора можно определить из программы с помощью команды INT 11H. Для BW монитора код 07 устанавливает нормальный атрибут. Для цветных мониторов мож но использовать любую из цветовых комбинаций. Цвет на экране сохраняется до тех пор, пока другая команда не изменит его. Для установки цвета можно использовать в команде INT 10H функции AH=06, AH=07 и AH=09. Например, для вывода пяти мигающих звездочек сетло-зеленым цветом на сиреневом фоне возможна следующая программа: MOV AH,09 ;Функция вывода на экран MOV AL,'*' ;Выводимый символ MOV BH,00 ;Страница 0 MOV BL,0DAH ;Атрибут цвета MOV CX,05 ;Число повторений INT 10H ;Вызвать BIOS ГРАФИЧЕСКИЙ РЕЖИМ ------------------------------------------------------------ Для генерации цветных изображений в графическом режиме используются минимальные точки растра - пиксели или пэлы (pixel). Цветной графический адаптер (CGA) имеет три степени разрешения: 1. Низкое разрешение (не поддерживается в ROM) обеспечива ет вывод 100 строк по 160 точек (т.е. четыре бита на точку). Каждая точка может иметь один из 16 стандартных цветов, как описано в предыдущем разделе "Цвета". Реализация данного режима включает прямую адресацию контролера Motorola 6845 CRT. Для этого используются два порта: шест.3D4 и 3D5. 2. Среднее разрешение для стандартной цветной графики обеспечивает 200 строк по 320 точек. Каждый байт в этом случае представляет четыре точки (т.е. два бита на точку). Ассемблер для IBM PC. Глава 10 231 3. Высокое разрешение обеспечивает 200 строк по 640 точек. Поскольку в данном случае требуется 16К байт памяти, высокое разрешение достигается только в черно-белом (BW) режиме. Каждый байт здесь представляет 8 точек (т.е. один бит на точку). Нулевое значение бита дает черный цвет точки, единичное - белый. Заметим, что в графическом режиме ROM содержит точечные образы только для первых 128 ASCII-кодов. Команда INT 1FH обеспечивает доступ к 1К байтовой области в памяти, определяющей остальные 128 символов. (8 байт на символ). Отображение графических байтов в видео сигналы аналогично, как для среднего, так и для высокого pазрешения. РЕЖИМ СРЕДНЕГО РАЗРЕШЕНИЯ ------------------------------------------------------------ При среднем разрешении каждый байт представляет четыре точки, пронумерованных от 0 до 3: Байт: |C1 C0|C1 C0|C1 C0|C1 C0| Пиксели: 0 1 2 3 В любой момент для каждой точки возможны четыре цвета, от 0 до 3. Ограничение в 4 цвета объясняется тем, что двухбитовая точка имеет 4 комбинации значений битов: 00, 01, 10 и 11. Можно выбpать значение 00 для любого из 16 возможных цветов фона или выбрать значение 01, 10, и 11 для одной из двух палитр. Каждая палитpа имеет три цвета: C1 C0 Палитра 0 Палитра 1 0 0 фон фон 0 1 зеленый голубой 1 0 красный сиреневый 1 1 коричневый белый Для выбора цвета палитры и фона используется INT 10H. Таким обpазом, если, например, выбран фон желтого цвета и палитра 0, то возможны следующие цвета точки: желтый, зеленый, красный и коричневый. Байт, содержащий значение 10101010, соответствует красным точкам. Если выбрать цвет фона - синий и палитру 1, то возможные цвета: синий, голубой, сиреневый и белый. Байт, содержащий значение 00011011, отображает синюю, голубую, сиреневую и белую точки. Прерывание BIOS INT 10H для графики Ассемблер для IBM PC. Глава 10 232 Функция AH=00 команды INT 10H устанавливает графический ркфим. Функция AH=11 команды INT 10H позволяет выбрать цвет палитры и вывести на экран графический символ. Код в регист ре AH определяет функцию: AH=00: Установка режима. Нулевое значение в регистре AH и 04 в pегистре AL устанавливают стандартый цветной графичес кий режим: MOV AH,00 ;Функция установки режима MOV AL,04 ;Разрешение 320х200 INT 10H Установка графического режима приводит к исчезновению курсора с экрана. Подробности по установке режима приведены в главе 9. AH=0BH: Установка цветовой палитры. Число в регистре BH определяет назначение регистра BL: BH=00 выбирает цвета фона и бордюра в соответствии с содержимым pегистра BL. Цвет фона от 1 до 16 соответствует шест. значениям oт 0 до F; BH=01 выбирает палитру соответственно содержимому регист ра BL (0 или 1): MOV AH,0BH ;Функция установки цвета MOV BH,01 ;Выбор палитры MOV BL,00 ; 0 (зеленый, красный, корич.) INT 10H ;Вызвать BIOS Палитра, установленная один раз, сохраняется, пока не будет отменена другой командой. При смене палитры весь экран меняет цветовую комбинацию. При использовании функции AH=0BH в текстовом режиме, значение, установленное для цвета 0 в палитре, определяет цвет бордюра. AH=0CH: Вывод точки на экран. Использование кода 0C в регистре AH позволяет вывести на экран точку в выбранном цвете (фон и палитра). Например, для разрешения 320х200 загрузим в регистр DX вертикальную координату (от 0 до 199), а в регистр CX - горизонтальную координату (от 0 до 319). В регистр AL поместим цвет точки (от 0 до 3): MOV AH,0CH ;Функция вывода точки MOV AL,цвет ;Цвет точки MOV CX,столбец ;Горизонтальная координата MOV DX,строка ;Вертикалькая координата INT 10H ;Вызвать BIOS AH=0DH: Чтение точки с экрана. Данная функция позволяет прочитать точку для определения ее цвета. В регистр DX должна быть загружена вертикальная координата (от 0 до 199), Ассемблер для IBM PC. Глава 10 233 а в регистр CX - горизонтальная (от 0 до 319). В регистре AH должно быть значение 0D. Функция возвращает цвет точки в регистре AL. ------------------------------------------------------------ ------------------------------------------------------------ Рис. 10.1 Вывод на экран в цветном графическом режиме. ПРОГРАММА: УСТАНОВКА ГРАФИЧЕСКОГО РЕЖИМА И ОТОБРАЖЕНИЕ ЦВЕТА ------------------------------------------------------------ Программа, приведенная на рис.10.1, использует команду INT 10H для установки графического режима, выбора зеленого фона и вывода на экран точек (40 строк по 320 столбцов). В программе происходит увеличение значения цвета на 1 для каждой строки. Так как в определении цвета участвуют только три правых бита, цвета повторяются через каждые семь строк. После выполнения программы дисплей остается в графическом режиме. Восстановление текстового режима возможно с помощью команды DOS MODE (MODE CO80) или пользовательской COM программой, в которой для этой цели используется команда INT 10H. ОСНОВНЫЕ ПОЛОЖЕНИЯ НА ПАМЯТЬ ------------------------------------------------------------ ъ Память объемом 16К для цветного дисплея позволяет хранить дополнительные страницы (экраны). Возможны четыре страницы для экранов на 80 столбцов или восемь страниц для экранов на 40 столбцов. ъ Графический режим обеспечивает низкое разрешение (не поддерживается в ROM), среднее разрешение (для цветной графики) и высокое разрешение (для черно-белой графи ки). ъ Точка растра (минимальный элемент графического изображения) представляется определенным числом бит в зависимости от графического адаптера и разрешающей способности (низкой, средней или высокой). ъ Для графики среднего разрешения на цветном графическом адаптере (CGA) можно выбрать четыре цвета, один из которых принадлежит к 16 возможным цветам, а три других формируют цветовую палитру. ВОПРОСЫ ДЛЯ САМОПРОВЕРКИ ------------------------------------------------------------ 10.1. Сколько цветов возможно для фона и для текста на стандартном цветном адаптере (CGA) в текстовом режиме? Ассемблер для IBM PC. Глава 10 234 10.2. Напишите байты атрибуты в двоичном формате для а) сиреневого на ярко-голубом, б) коричневого на желтом, в)красного на сером с миганием. 10.3. Объясните разницу в количестве цветов, возможных при низком, среднем и высоком разрешении. 10.4. Напишите команды для вывода пяти символов карточной масти "бубны" в текстовом режиме ярко-зеленым цветом на сиреневом фоне. 10.5. Напишите команды для установки графического режима с разрешением а) 320х200 в адаптере CGA и б) 640х200 в адаптере EGA. 10.6. Напишите команды для установки синего фона в графичес ком режиме. 10.7. Напишите команды для чтения точки на 12 строке и 13 столбце в графическом режиме. 10.8. Модифицируйте программу на рис.10.1 для: а) графическо го режима на вашем мониторе; б) красного фона; в) строк с 10 по 30; г) столбцов с 20 по 300. Ассемблер для IBM PC. Глава 11 241 ГЛАВА 11. Команды обработки строк ------------------------------------------------------------ Команды обработки строк Цель: Ообъяснить назначение специальных цепочечных команд, используемых для обработки символьных данных. ВВЕДЕНИЕ ------------------------------------------------------------ Команды, показанные в предыдущих главах, оперировали одним байтом, или одним словом за одно выполнение. Часто, однако, бывает необходимо переслать или сравнить поля данных, которые превышают по длине одно слово. Например, необходимо сравнить описания или имена для того, чтобы отсортировать их в восходящей последовательности. Элементы такого формата известны как строковые данные и могут являтся как символьными, так и числовыми. Для обработки строковых данных ассемблер имеет пять команд обработки строк: MOVS переслать один байт или одно слово из одной области памяти в другую; LODS загрузить из памяти один байт в регистр AL или одно слово в регистр AX; STOS записать содержимое регистра AL или AX в память; CMPS сравнить содержимое двух областей памяти, размером в один байт или в одно слово; SCAS сравнить содержимое регистра AL или AX с содержимым памяти. Префикс REP позволяет этим командам обрабатывать строки любой длины. СВОЙСТВА ОПЕРАЦИЙ НАД СТРОКАМИ ------------------------------------------------------------ Цепочечная команда может быть закодирована для повторяю щейся обpаботки одного байта или одного слова за одно выполнение. Например, можно выбрать "байтовую" команду для обработки строки с нечетным числом байт или "двухбайтовую" команду для обработки четного числа байт. Ниже перечислены регистры, участвующие в цепочечных командах (для однобайтовых и двухбайтовых вариантов). Предположим, что регистры DI и SI содержат необходимые адреса: Команда Операнды Байт Слово MOVS DI,SI MOVSB MOVSW LODS AL,SI или AX,SI LODSB LODSW Ассемблер для IBM PC. Глава 11 242 STOS DI,AL или DI,AX STOSB STOSW CMPS SI,DI CMPSB CMPSW SCAS DI,AL или DI,AX SCASB SCASW Например, можно кодировать операнды для команды MOVS, но опустить их для MOVSB и MOVSW. Эти команды предполагают, что pегистры DI и SI содержат относительные адреса, указывающие на необходимые области памяти (для загрузки можно использо вать команду LEA). Регистр SI обычно связан с регистром сегмента данных - DS:SI. Регистр DI всегда связан с регистром дополнительного сегмента - ES:DI. Следовательно, команды MOVS, STOS, CMPS и SCAS требуют инициализации регистра ES (обычно адресом в регистре DS). REP: ПРЕФИКС ПОВТОРЕНИЯ ЦЕПОЧЕЧНОЙ КОМАНДЫ ------------------------------------------------------------ Несмотря на то, что цепочечные команды имеют отношение к одному байту или одному слову, префикс REP обеспечивает повторение команды несколько раз. Префикс кодируется непо средственно перед цепочечной командой, например, REP MOVSB. Для использования префикса REP необходимо установить начальное значение в регистре CX. При выполнении цепочечной команды с префиксом REP происходит уменьшение на 1 значения в регистре CX до нуля. Таким образом, можно обрабатывать строки любой длины. Флаг направления определяет направление повторяющейся операции: - для направления слева направо неоходимо с помощью команды CLD установить флаг DF в 0; - для направления справа налево необходимо с помощью команды STD установить флаг DF в 1. В следующем примере выполняется пересылка 20 байт из STRING1 в STRING2. Предположим, что оба регистра DS и ES инициализированы адресом сегмента данных: STRING1 DB 20 DUP('*') STRING2 DB 20 DUP(' ') ... CLD ;Сброс флага DF MOV CX,20 ;Счетчик на 20 байт LEA DI,STRING2 ;Адрес области "куда" LEA SI,STRING1 ;Адрес одласти "откуда" REP MOVSB ;Переслать данные При выполнееии команд CMPS и SCAS возможна установка флагов состояния, так чтобы операция могла прекратиться сразу после обнаружения необходимого условия. Ниже приведены модификации префикса REP для этих целей. REP - повторять операцию, пока CX не равно 0; Ассемблер для IBM PC. Глава 11 243 REPZили REPE - повторять операцию,пока флаг ZF показывает "равноили ноль".Прекратить операцию при флаге ZF, указывающему на не равно или не ноль или при CX равном 0; REPNE или REPNZ - повторять операцию, пока флаг ZF показывает "не равно или не ноль". Прекратить операцию при флаге ZF, указывающему на "равно или нуль" или при CX равным 0. Для процессоров 8086, 80286 и 80386, обрабатывающих слово за oдно выполнение, использование цепочечных команд, где это возможно, приводит к повышению эффективности работы программы. MOVS: ПЕРЕСЫЛКА СТРОК ------------------------------------------------------------ На рис.7.5 была показана программа для пересылки девяти байтового поля. Программа включала три команды для инициали зации и пять команд для цикла. Команда MOVS с префиксом REP и длиной в регистре CX может выполнять пересылку любого числа символов более эффективно. Для области, принимающей строку, сегментным регистром, является pегистр ES, а регистр DI содержит относительный адрес области, передающей строку. Сегментным регистром является регистр DS, а регистр SI содержит относительный адрес. Таким образом,в начале программы перед выполнением команды MOVS необходимо инициализировать регистр ES вместе с регистром DS, а также загрузить требуемые относительные адреса полей в регистры DI и SI. В зависимости от состояния флага DF команда MOVS производит увеличение или уменьшение на 1 (для байта) или на 2 (для слова) содержимого регистров DI и SI. Приведем команды, эквивалентные цепочечной команде REP MOVSB: JCXZ LABEL2 LABEL1: MOV AL,[SI] MOV [DI],AL INC/DEC DI ;Инкремент или декремент UNC/DEC SI ;Инкремент или декремент LOOP LABEL1 LABEL2: ... В программе на рис. 11.1 процедура C10MVSB использует команду MOVSB для пересылки содержимого десятибайтового поля NAME1 в поле NAME2. Первая команда CLD сбрасывает флаг направления в 0 для обеспечения процесса пересылки слева направо. В нормальном состоянии флаг DF обычно имеет нулевое значение и команда CLD используется из предосторожности. Ассемблер для IBM PC. Глава 11 244 Две команды LEA загружают регистры SI и DI относительными адресами NAME1 и NAME2 соответственно. Так как регистры DS и ES были ранее инициализированы адресом DATASG, то полные адреса полей NAME1 и NAME2 будут в регистрах ES:DI и DS:SI. (COM программа автоматически инициализирует регистры ES и DS). Команда MOV заносит в регистр CX значение 10 - длину полей NAME1 и NAME2. Команда REP MOVSB выполняет следующее: ъ Пересылает самый левый байт из поля NAME1 (адресованно го pегистрами ES:DI) в самый левый байт поля NAME2 (адресованного регистрами DS:SI). ъ Увеличивает на 1 адреса в регистрах DI и SI для следующего байта. ъ Уменьшает CX на 1. ъ Повторяет перечисленные действия (в данном случае 10 раз), пока содержимое регистра CX не станет равным нулю. Поскольку флаг DF имеет нулевое значение, команда MOVSB увеличивает адреса в регистрах DI и SI, и в каждой итерации процесс переходит на байт вправо, т.е. пересылает байт из NAME1+1 в NAME2+1 и т.д. Если бы флаг DF был равен 1, тогда команда MOVSB уменьшала бы адреса в регистрих DI и SI, выполняя процесс справа налево. Но в этом случае регистры SI и DI необходимо инициализировать адресами последних байтов полей, т.е. NAME1+9 и NAME2+9 соответственно. В процедуре D10MVSW (рис.11.1) используется команда MOVSW, пересылающая одно слово за одно выполнение. Так как команда MOVSW увеличивает адреса в регистрах DS и SI на 2, операция требует только пять циклов. Для процесса пересылки справа налево регистр SI должен быть инициализирован адресом NAME1+8, а регистр DI - NAME2+8. LODS: ЗАГРУЗКА СТРОКИ ------------------------------------------------------------ Команда LODS загружает из памяти в регистр AL один байт или в регистр AX одно слово. Адрес памяти определяется регистрами DS:SI. В зависимости от значения флага DF происходит увеличение или уменьшение регистра SI. Поскольку одна команда LODS загружает регистр, то практи ческой пользы от префикса REP в данном случае нет. Часто простая команда MOV полностью адекватна команде LODS, хотя MOV генерирует три ба