2.3.4 Выводим строку символов с заданными атрибутами
INT 10h, AH = 13h - Вывести строку символов с заданными атрибутами
Ввод: | АН = 13h AL = режим вывода: Бит 0 - переместить курсор в конец строки после вывода бит 1 - строка содержит не только символы, но также и атрибуты, так что каждый символ описывается двумя байтами: ASCII-код и атрибут биты 2 - 7 зарезервированы СХ = длина строки (только число символов) BL = атрибут, если строка содержит только символы DH,DL = строка и столбец, начиная с которых будет выводиться строки ES: BP = адрес начала строки в памяти |
Функция 13h выводит на экран строку символов, интерпретируя управляющие символы CR (0Dh), LF (0Ah), BS (08) и BEL (07). Если строка подготовлена в формате символ, атрибут - гораздо быстрее просто скопировать ее в видеопамять.
Функции BIOS удобны для переключения и настройки видеорежимов, но часто оказывается, что вывод текста на экран гораздо быстрее и проще выполнять просто копированием изображения в видеопамять.
3. Прямая работа с видеопамятью
Все, что изображено на мониторе - и графика, и текст, одновременно присутствует в памяти, встроенной в видеоадаптер. Для того чтобы изображение появилось на мониторе, оно должно быть записано в память видеоадаптера. Для этого отводится специальная область памяти, начинающаяся с абсолютного адреса 0B800h: 0000h (для текстовых режимов) и заканчивающаяся на 0B800h: FFFFh. Все, что программы пишут в эту область памяти, немедленно пересылается в память видеоадаптера. В текстовых режимах для хранения каждого изображенного символа используются два байта: байт с ASCII-кодом символа и байт с его атрибутом, так что по адресу 0B800h: 0000h лежит байт с кодом символа, находящимся в верхнем левом углу экрана; по адресу 0B800h: 0001h лежит атрибут этого символа; по адресу 0B800h: 0002h лежит код второго символа в верхней строке экрана и т.д.
Таким образом, любая программа может вывести текст на экран, простой командой пересылки данных, не прибегая ни к каким специальным функциям DOS или BIOS.
Пример работ с видеопамятью.
Пример № 3.1
. model tiny | ; модель памяти, в которой сегменты кода, данных и стека объединены. |
. code | ; сегмент кода, который содержит данные. |
org 100h | ; начало СОМ-файла |
begin: | ; метка начала кода программы |
mov ax,0003h | ; видеорежим 3 (очистка экрана) |
int 10h | ; прерывание DOS - очистка экрана; |
mov ax,0B800h | ; загружаем в сегментный регистр ES число 0B800h |
mov es,ax | |
mov di,0 | ; загружаем в регистр DI нуль |
mov ah,31 | ; заносим в регистр ah - атрибут символа |
mov al, < ASCII-код символа > | заносим в регистр al - любой ASCII-код символа |
mov es: [di],ax | ; заносим по адресу 0B800: 0000h атрибут и ASCII-код символа |
mov ah,10h | ; вызываем функцию 10h - чтобы можно было остановить программу до нажатия любой клавиши |
int 16h | ; вызываем прерывание 16h - сервис работы с клавиатурой BIOS |
ret | ; функция DOS "завершить программу" |
end begin | ; метка окончания кода программы |
При подготовке данных для копирования в видеопамять в этой программе в строках (7) и (8) загружаем в сегментный регистр ES число 0B800h, которое соответствует сегменту дисплея в текстовом режиме. В строке (9) загружаем в регистр DI нуль. Это будет смещение относительно сегмента 0B800h. В строках (10) и (11) в регистр AH заносится атрибут символа (31 - ярко-белый символ на синем фоне) и в AL - ASCII-код символа (01 - рожица) соответственно.
В строке (12) заносим по адресу 0B800: 0000h (т.е. первый символ в первой строке дисплея - верхний левый угол) атрибут и ASCII-код символа (31 и 01 соответственно).
4. Задание для выполнения.
4.1 С помощью редактора эмулятора EMU 8086 напишите программы примеры, которых приведены в данной лабораторной работе.
4.2 Создайте файлы типа MZ и *.com.
4.3 Изучите структуру откомпилированных программ.
4.4 Получите задание у преподавателя (один из пяти вариантов табл. №1) напишите программу вывода на экран строки ‘Hello’.
4.5 Напишите программу работы переключения SuperVGA-видеорежимов (согласно вариантов табл. №2)
4.6 Подготовьте отчет, который должен содержать тексты программ, а также укажите описание работы команд программ.
4.7 В отчете должны содержаться ответы на следующие вопросы.
5. Контрольные вопросы
5.1 Перечислите функции вывода на экран средствами операционной системы DOS?
5.2 Принцип работы функции DOS 02h?
5.3 Укажите основные управляющие символы вывода на экран?
5.4 Каким образом осуществить вывод программы в файл?
5.5 Укажите отличие функции DOS 02h от 06h?
5.6 Прерывание int 29h. Преимущества использования?
5.7 С помощью каких функций можно установить нужный видеорежим (текстовый, цветной, монохромный)?
5.8 Отметьте основные моменты установки super VGA-видеорежимов?
5.9 Укажите функции и прерывания управления положением курсора.
5.10 Перечислите функции считывания положения и размера курсора?
5.11 Вывод символов на экран средствами BIOS. Функции?
5.12 Прямая работа с видеопамятью. Принципы работы с видеопамятью?
5.13 Укажите преимущества вывода на экран с помощью непосредственной работы с видеопамятью?
5.14 Область памяти видеоадаптера?
5.15 Укажите код третьего символа в верхней строке экрана для работы с видеопамятью?
5.16 Если в примере № 1.2 длину строку указать большую, чем указанная что в данном случае будет выводиться на экрана
Табл. №1
№ вар. | Функция вывода (DOS) | Функция вывода (BIOS) | Видеопамять |
02h | Ah=02h | ‘Hello’ | |
06h | Ah=08h | ||
09h | Ah=09h | ||
40h | Ah=0Ah | ||
29h | Ah=13h |
Примечание: В примерах, в которых возможно задание различных параметров вывода (цвет символа, фона; номер строки, столбца, страницы и т.д.) выводите на экран слово "hello" с параметрами отличными от стандартных.
Табл. №2
№ вар. | SuperVGA-видеорежим |
108h | |
109h | |
10Ah | |
10Bh | |
10Ch |
КОМАНДЫ ЛОГИЧЕСКИХ ОПЕРАЦИЙ
Цель работы: ознакомиться с работой команд логических операций: and, or, xor, test, not и реализацией их работы на практике.
Краткие теоретические сведения.
Логические операции являются важным элементом в проектировании микросхем и имеют много общего в логике программирования. Команды AND, OR, XOR и TEST - являются командами логических операций. Эти команды используются для сброса и установки бит и для арифметических операций в коде ASCII. Все эти команды обрабатывают один байт или одно слово в регистре или в памяти, и устанавливают флаги CF, OF, PF, SF, ZF.
Команда AND.
Команда AND (Логическое И) осуществляет логическое (побитовое) умножение первого операнда на второй. Исходное значение первого операнда (приемника) теряется, замещаясь результатом умножения. В качестве первого операнда команды and можно указывать регистр (кроме сегментного) или ячейку памяти, в качестве второго - регистр (кроме сегментного), ячейку памяти или непосредственное значение, однако не допускается определять оба операнда одновременно как ячейки памяти. Операнды могут быть байтами или словами. Команда воздействует на флаги SF, ZF и PF.
Правила побитового умножения:
Первый операнд-бит 0101 | Бит результата 0001 |
Второй операнд-бит 0011 |
Пример 1
mov AX,0FFEh
and AX,5555h; AX=0554h
Пример 2
mov ax,00101001b
add ax,11110111b ; ax=00100001b
Команда OR
Команда OR (Логическое ВКЛЮЧАЮЩЕЕ ИЛИ) выполняет операцию логического (побитового) сложения двух операндов. Результат замещает первый операнд (приемник); второй операнд (источник) не изменяется. В качестве первого операнда можно указывать регистр (кроме сегментного) или ячейку памяти, в качестве второго - регистр (кроме сегментного), ячейку памяти или непосредственное значение, однако не допускается определять оба операнда одновременно как ячейки памяти. Операнды команды OR могут быть байтами или словами. Команда воздействует на флаги OF, SF, ZF, PF и CF, при этом флаги CF и OF всегда сбрасываются в 0.
Правила побитового сложения:
Первый операнд-бит 0101 | Бит результата 0111 |
Второй операнд-бит 0011 |
Пример 1
mov AX,000Fh
mov BX,00F0h
or AX,BX; AX=00FFh, BX=00F0h
Пример 2
mov AX,00101001b
mov BX,11110111b
or AX,BX ; mov dx,11111111b
Пример 3
mov AX,000Fh
or AX,8001h ; AX=800Fh
Команда XOR.
Команда ХОR (Логическое ИСКЛЮЧАЮЩЕЕ ИЛИ) выполняет операцию логического (побитового) ИСКЛЮЧАЮЩЕГО ИЛИ над своими двумя операндами. Результат операции замещает первый операнд; второй операнд не изменяется. Каждый бит результата устанавливается в 1, если соответствующие биты операндов различны, и сбрасывается в 0, если соответствующие биты операндов совпадают.
В качестве первого операнда команды ХОR можно указывать регистр (кроме сегментного) или ячейку памяти, в качестве второго - регистр (кроме сегментного), ячейку памяти или непосредственное значение, однако не допускается определять оба операнда одновременно как ячейки памяти. Операнды могут быть байтами или словами. Команда воздействует на флаги OF, SF, ZF, PF и CF, причем флаги OF и CF всегда сбрасываются, а остальные флаги устанавливаются в зависимости от результата.
Правила побитового исключающего или:
Первый операнд-бит 0101 | Бит результата 0110 |
Второй операнд-бит 0011 |
Пример 1
mov AX,0Fh
хог AX,0FFFFh; AX=FFF0h
Пример 2
mov AX,00101001b
mov BX,11110111b
xor ax,bx; 11011110b
Пример 3
mov SI,0AAAAh
mov BX,5555h
xor SI,BX ; SI=FFFFh,BX=5555h
Пример 4
хог ВХ, ВХ ; Обнуление ВХ
Команда TEST.
Команда TEST (Логическое сравнение) выполняет операцию логического умножения И над двумя операндами и, в зависимости от результата, устанавливает флаги SF, ZF и PF. Флаги OF и CF сбрасываются, a AF имеет неопределенное значение. Состояние флагов можно затем проанализировать командами условных переходов. Команда TEST не изменяет ни один из операндов.
В качестве первого операнда команды TEST можно указывать регистр (кроме сегментного) или ячейку памяти, в качестве второго - регистр (кроме сегментного), ячейку памяти или непосредственное значение, однако не допускается определять оба операнда одновременно как ячейки памяти. Операнды могут быть байтами или словами и представлять числа со знаком или без знака.
Правила побитового умножения:
Первый операнд-бит 0101 | Бит результата 0001 |
Второй операнд-бит 0011 |
Флаг SF устанавливается в 1, если в результате выполнения команды образовалось число с установленным знаковым битом.
Флаг ZF устанавливается в 1, если в результате выполнения команды образовалось число, состоящее из одних двоичных нулей.
Флаг PF устанавливается в 1, если в результате выполнения команды образовалось число с четным количеством двоичных единиц в его битах.
Пример 1
test AX,1
jne label2: ; Переход, если бит 0 в АХ установлен
je label1: ; Переход, если бит 0 в АХ сброшен
Пример №1.4.1.1
. model tiny | ; модель памяти в которой сегменты кода, данных и стека объединены. |
. code | ; сегмент кода, который содержит данные. |
org 100h | ; начало СОМ-файла |
begin: | ; метка начала кода программы |
mov СX,<число1 > | ; загружаем в CX число1 <любое число1> |
mov BX,<число2> | ; загружаем в BX число2 <любое число2> |
test cx,bx | ; логически сравниваем числа в регистрах cx с bx |
jne label2 | ; если одно из значений не равно 0 то переходим на метку label2 |
je label1 | ; если одно из значений равно 0 то переходим на метку label1 |
ret | ; функция DOS "завершить программу" (не выполняется) |
label1: | ; начало блока метки Label1 |
mov ah,9 | ; помещаем номер функции DOS "вывод строки (9)" в регистр АН. |
mov dx,offset string | помещает в регистр DX смещение метки String относительно начала сегмента данных |
int 21h | ; функция DOS "вывод строки" |
ret | ; функция DOS "завершить программу" |
String db 'одно из чисел равно 0$' | ; cтрока с содержащая выводимые данные. |
label2: | ; начало блока метки Label2 |
mov ah,9 | ; помещаем номер функции DOS "вывод строки (9)" в регистр АН. |
mov dx,offset string1 | помещает в регистр DX смещение метки String1 относительно начала сегмента данных |
int 21h | ; функция DOS "вывод строки" |
ret | ; функция DOS "завершить программу" |
string1 db 'не равны 0$' | ; cтрока с содержащая выводимые данные. |
end begin | ; метка окончания кода программы |
Данный пример сравнивает два значения (строка (6)), если одно из двух значений равно нулю тогда переходим на метку label1 (строка (10)) далее выполняются команды, следующие после этой метки, в случае если одно из двух значений равно нулю тогда переходим на метку label2
Пример 2
test SI,8
jne bityes ; Переход, если бит 3 в SI установлен
je bitno ; Переход, если бит 0 в АХ сброшен
Пример 3
test DX,0FFFFh
jz null ; Переход, если DX=0
jnz smth; Переход, если DX не 0
Команда NOT.
Команда NOT (NOT Инверсия, дополнение до 1, логическое отрицание) выполняет инверсию битов указанного операнда, заменяя 0 на 1 и наоборот. В качестве операнда можно указывать регистр (кроме сегментного) или ячейку памяти размером как в байт, так и в слово. Не допускается использовать в качестве операнда непосредственное значение. Команда не воздействует на флаги процессора.
Правила побитовой инверсии:
Операнд-бит 0 1 | Бит результата 1 0 |
Пример 1
mov AX,0FFFFh
not AX; AX=0000h
Пример 2
mov SI,5551h
not SI; SI=AAAEh
Характерные примеры работы команд логических операций.
Для следующих несвязанных примеров, предположим, что:
AL содержит 1100 0101
BH содержит 0101 1100:
1. AND AL,BH; Устанавливает в AL 0100 0100
2. OR BH,AL; Устанавливает в BH 1101 1101
3. XOR AL,AL; Устанавливает в AL 0000 0000
4. AND AL,00; Устанавливает в AL 0000 0000
5. AND AL,0FH; Устанавливает в AL 0000 0101
6. OR CL,CL; Устанавливает флаги SF и ZF
Примеры 3 и 4 демонстрируют способ очистки регистра.
В примере 5 обнуляются левые четыре бита регистра AL.
Можно применить команду OR для следующих целей:
1. OR CX,CX; Проверка CX на нуль
JZ; Переход, если нуль
2. OR CX,CX; Проверка знака в CX
JS; Переход, если отрицательно
3. Задание для выполнения.
Запустить эмулятор EMU8086.
Пользуясь правилами оформления ассемблерных программ, наберите код примера №1.4.1.1, запустите код на выполнение.
Проанализируйте работу кода примера №1.4.1.1
С помощью справки эмулятора EMU8086 выясните работу команд (jne, je, js, jz)
Получите задание у преподавателя (один из четырех вариантов (команды (and, or, xor, test, not))) и, пользуясь правилами оформления ассемблерных программ, напишите три программы характеризующие (показывающие) работу их с числами (двоичной, десятеричной, шестнадцатеричной систем счисления) согласно перечислению приведенных примеров.
Результаты работы продемонстрируйте преподавателю.
4. Контрольные вопросы
4.1 Назначение команд логических операций?
4.2 Команда and основное назначение?
4.3 Команда or основное назначение?
4.4 Команда xor основное назначение?
4.5 Команда test основное назначение?
4.6 Команда not основное назначение?
4.7 Альтернативная работа команд (test, xor, and)?
4.8 Допустим что будит
4.9 В чем заключается работа связки команд jne, je?
4.10 В чем заключается работа связки команд js, jz?
4.11 Что произойдет, если в примере №1.4.1.1 мы изменим строку (8) на следующую (jne label1)?
ЛАБОРАТОРНАЯ РАБОТА №8
ОЗНАКОМЛЕНИЕ С РАБОТОЙ ЦИКЛОВ
Цель работы: ознакомиться со структурой и реализацией циклов в программе.
Краткие теоретические сведения.
Циклы, позволяющие выполнить некоторый участок программы многократно, в любом языке являются одной из наиболее употребительных конструкций. В системе команд МП 86 циклы реализуются, главным образом, с помощью команды loop (петля), хотя имеются и другие способы организации циклов. В большинстве случаях число шагов в цикле определяется содержимым регистра СХ, поэтому максимальное число шагов составляет 64 К.
Организация циклических переходов, как на языках высокого уровня, так и на языке assembler представляет собой замечательное средство, позволяющее значительно снизить код исполняемой программы.
В общем виде любой цикл записывается в ассемблере как условный переход.
Организация цикла с помощью команды LOOP (Первый способ).
Команда loop (анг. петля) выполняет декремент содержимого регистра СХ (счетчик), и если оно не равно 0, осуществляет переход на указанную метку вперед или назад в том же программном сегменте в диапазоне - 128... + 127 байт. Обычно метка помещается перед первым предложением тела цикла, а команда loop является последней командой цикла. Содержимое регистра СХ рассматривается как целое число без знака, поэтому максимальное число повторений группы включенных в цикл команд составляет 65536 (если перед входом в цикл СХ=0). Команда не воздействует на флаги процессора.
Команда | Назначение | Процессор |
LOOP метка | Организация циклов | 8086 |
Простейший пример организации циклического перехода (со счетчиком в регистре cx) на языке Assembler:
. model tiny | ; модель памяти, в которой сегменты кода, данных и стека объединены. |
. code | ; сегмент кода, который содержит и данные. |
org 100h | ; начало СОМ-файла |
begin: | ; метка начала кода программы |
mov cx,10 | ; загружаем в (регистр-счетчик) CX количество повторов (отсчет будет идти от 10 до 0) |
Label1: | ; создаем метку (Label - метка). |
mov ah,9 | ; помещаем номер функции DOS "вывод строки (9)" в регистр АН. |
mov dx,offset String | помещает в регистр DX смещение метки String относительно начала сегмента данных |
int 21h | ; функция DOS "вывод строки" |
loop Label1 | ; оператор loop уменьшает на единицу CX и, если он не равен нулю, переходит на метку Label1 (строка 6) |
ret | ; функция DOS "завершить программу" |
string db 'privet $' | ; cтрока с содержащая выводимые данные. |
end begin | ; метка окончания кода программы |
В строке (5) загружаем в CX количество повторов (отсчет будет идти от 10 до 0). В строке (6) создаем метку (Label - метка). Далее (строки (7) - (9)) выводим сообщение. И в строке (10) оператор loop уменьшает на единицу CX и, если он не равен нулю, переходит на метку Label1 (строка (6)). Таким образом, строка будет выведена на экран десять раз. Когда программа перейдет на строку (11), регистр CX будет равен нулю.
Организация цикла с помощью команды JMP (Второй способ).
Команда jmp передает управление в указанную точку того же или другого программного сегмента. Адрес возврата не сохраняется. Команда не воздействует на флаги процессора.
Команда jmp имеет пять разновидностей:
переход прямой короткий (в пределах - 128... + 127 байтов);
переход прямой ближний (в пределах текущего программного сегмента);
переход прямой дальний (в другой программный сегмент);
переход косвенный ближний;
переход косвенный дальний.
Все разновидности переходов имеют одну и ту же мнемонику jmp, хотя и различающиеся коды операций. Во многих случаях транслятор может определить вид перехода по контексту, в тех же случаях, когда это невозможно, следует использовать атрибутные операторы (short - прямой короткий переход; near ptr - прямой ближний переход; far ptr - прямой дальний переход; word ptr - косвенный ближний переход; dword ptr - косвенный дальний переход).
Команда | Назначение | Процессор |
JMP метка | Безусловный переход | 8086 |
. model tiny | ; модель памяти, в которой сегменты кода, данных и стека объединены. |
. code | ; сегмент кода, который содержит данные. |
org 100h | ; начало СОМ-файла |
begin: | ; метка начала кода программы |
label1: | ; создаем метку |
mov ah,9 | ; помещаем номер функции DOS "вывод строки (9)" в регистр АН. |
mov dx,offset String | помещает в регистр DX смещение метки String относительно начала сегмента данных |
int 21h | ; функция DOS "вывод строки" |
jmp Label1 | ; переход на строку с меткой Label1 |
add cx,12 | ; прибавить к значению регистра cx число 12 (данная команда не выполняется) |
dec cx | ; уменьшить значение регистра cx на 1 (данная команда не выполняется) |
ret | ; функция DOS "завершить программу" |
string db "PRIVET",13,10,'$' | ; cтрока с содержащая выводимые данные. |
end begin | ; метка окончания кода программы |
В результате работы программы будет зациклен блок строк (6) - (10) (Вывод строки PRIVET многочисленное количество раз) Строки (10) - (11).
Организация цикла с помощью команд DEC и JNZ (Третий способ).
С помощь этих операторов можно создавать циклы, которые будут работать быстрее оператора Loop. Комбинированная работа команд DEC и JNZ уменьшает содержимое регистра CX на 1 и выполняет переход на метку, если в CX не равен нулю.
Команда DEC, кроме того, устанавливает флаг нуля во флаговом регистре в состояние 0 или 1. Команда JNZ затем проверяет эту установку.
Аналогично командам JMP и LOOP операнд в команде JNZ содержит значение расстояния между концом команды JNZ и адресом перехода (Label1), которое прибавляется к командному указателю. Это расстояние должно быть в пределах от - 128 до +127 байт.
Следующий пример будет работать так же, как и Пример №1.1, только быстрее.
. model tiny | ; модель памяти, в которой сегменты кода, данных и стека объединены. |
. code | ; сегмент кода, который содержит данные. |
org 100h | ; начало СОМ-файла |
begin: | ; метка начала кода программы |
mov cx,10 | ; загружаем в (регистр-счетчик) CX количество повторов (отсчет будет идти от 10 до 0) |
Label1: | ; создаем метку (Label - метка). |
mov ah,9 | ; помещаем номер функции DOS "вывод строки (9)" в регистр АН. |
mov dx,offset String | помещает в регистр DX смещение метки String относительно начала сегмента данных |
int 21h | ; функция DOS "вывод строки" |
dec cx | ; оператор DEC уменьшает на единицу CX и, если он не равен нулю, переходит на метку Label1 |
jnz Label1 | ; условный переход на строку с меткой Label1 |
ret | ; функция DOS "завершить программу" |
string db 'priver ',13,10, '$' | ; cтрока с содержащая выводимые данные |
end begin | ; метка окончания кода программы |
0 комментариев