Жанр: Учеба

Ассемблер и программирование для IBM PC

сторінка №10

байт или слово;
- имеют доступ к регистру или к памяти;
- сдвигают влево или вправо;
- сдвигают на величину до 8 бит (для байта) и 16 бит (для слова)
- сдвигают логически (без знака) или арифметически (со знаком).

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

Команды сдвига
----------------
При выполнении команд сдвига флаг CF всегда содержит значение
последнего выдвинутого бита. Существуют следующие команды сдвига:

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 заполняется нулем. Вторая команда сдвигает содержимое регистра
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: для заполнения
левого бита используется знаковый бит. Таким образом, положительные и
отрицательные величины сохраняют свой знак. В приведенном примере знаковый
бит содержит единицу.
При сдвигах влево правые биты заполняются нулями. Таким образом,
результат команд сдвига SHL и SAL индентичен.
Сдвиг влево часто используется для удваивания чисел, а сдвиг вправо -
для деления на 2. Эти операции осуществляются значительно быстрее, чем
команды умножения или деления. Деление пополам нечетных чисел (например, 5
или 7) образует меньшие значения (2 или 3, соответственно) и
устанавливает флаг CF в 1. Кроме того, если необходимо выполнить сдвиг на
2 бита, то использование двух команд сдвига более эффективно, чем
использование одной команды с загрузкой регистра CL значением 2.
Для проверки бита, занесенного в флаг CF используется команда JC
(переход, если есть перенос).

Команды циклического сдвига
-----------------------------
Циклический сдвиг представляет собой операцию сдвига, при которой
выдвинутый бит занимает освободившийся разряд. Существуют следующие
команды циклического сдвига:

ROR ;Циклический сдвиг вправо
ROL ;Циклический сдвиг влево
RCR ;Циклический сдвиг вправо с переносом
RCL ;Циклический сдвиг влево с переносом

Следующая последовательность команд иллюстрирует операцию
циклического сдвига 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 этого значения возможны следующие две команды:

SHL AX,1 ;Умножение пары регистров
RCL DX,1 ; DX:AX на 2

Здесь команда SHL сдвигает все биты регистра AX влево, причем самый
левый бит попадает в флаг CF. Затем команда RCL сдвигает все биты регистра
DX влево и в освободившийся правый бит заносит значение из флага CF.

ОРГАНИЗАЦИЯ ПРОГРАММ
________________________________________________________________

Ниже даны основные рекомендации для написания ассемблерных программ:

1. Четко представляйте себе задачу, которую должна решить
программа.
2. Сделайте эскиз задачи в общих чертах и спланируйте общую
логику программы. Например, если необходимо проверить операции
пересылки нескольких байт (как в примере на рис.7.5), начните c
определения полей с пересылаемыми данными. Затем спланируйте общую
стратегию для инициализации, условного перехода и команды LOOP.
Приведем основную логику, которую используют многие программисты в
таком случае:

инициализация стека и сегментных регистров
вызов подпрограммы цикла
возврат

Подпрограмма цикла может быть спланирована следующим образом:

инициализация регистров значениями адресов
и числа циклов

Метка: пересылка одного байта
увеличение адресов на 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 контролирует только нулевое значение,
при отрицательном программа будет продолжать циклиться.

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

- Выбирайте команды условного перехода соответственно операциям над
знаковыми или беззнаковыми данными.

- Для вызова процедуры используйте команду CALL, а для возврата из
процедуры - команду RET. Вызываемая процедура может, в свою очередь,
вызвать другую процедуру, и если следовать существующим соглашениям, то
команда RET всегда будет выбирать из стека правильный адрес возврата.
Единственные примеры в этой книге, где используется переход в процедуру
вместо ее вызова - в начале COM-программ.

- Будьте внимательны при использовании индексных операндов. Сравните:

MOV AX,SI
MOV AX,[SI]

Первая команда MOV пересылает в регистр AX содержимое регистра SI. Вторая
команда MOV для доступа к пересылаемому слову в памяти использует
относительный адрес в регистре SI.

- Используйте команды сдвига для удваивания значений и для деления
пополам, но при этом внимательно выбирайте соответствующие команды для
знаковых и беззнаковых данных.

ВОПРОСЫ ДЛЯ САМОПРОВЕРКИ
________________________________________________________________

7.1. Какое максимальное количество байт могут обойти команды короткий
JMP, LOOP и относительный переход? Какой машинный код операнда при этом
генерируется?

7.2. Команда JMP начинается на шест.0624. Определите адрес перехода,
если шест. объектный код для операнда команды JMP: а) 27, б) 6B, в) C6.

7.3. Напишите программу вычисления 12 чисел Фибоначчи: 1, 1, 2, 3, 5,
8, 13,... (каждое число в последовательности представляет собой сумму двух
предыдущих чисел). Для организации цикла используйте команду LOOP.
Выполните ассемблирование, компоновку и с помощью отладчика DEBUG
трассировку программы.

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 операнда с
типом 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, а
регистр 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.

ГЛАВА 8 Экранные операции I: Основные свойства


__________________________________________________________________________

Ц е л ь: Объяснить требования для вывода информации на экран, а также
для ввода данных с клавиатуры.

ВВЕДЕНИЕ
________________________________________________________________

В предыдущих главах мы имели дело с программами, в которых данные
определялись в операндах команд (непосредственные данные) или
инициализировались в конкретных полях программы. Число практических
применений таких программ в действительности мало. Большинство программ
требуют ввода данных с клавиатуры, диска или модема и обеспечивают вывод
данных в удобном формате на экран, принтер или диск. Данные,
предназначенные для вывода на экран и ввода с клавиатуры, имеют ASCII
формат.
Для выполнения ввода и вывода используется команда INT (прерывание).
Существуют различные требования для указания системе какое действие (ввод
или вывод) и на каком устройстве необходимо выполнить. Данная глава
раскрывает основные требования для вывода информации на экран и ввода
данных с клавиатуры.
Все необходимые экранные и клавиатурные операции можно выполнить
используя команду INT 10H, которая передает управление непосредственно в
BIOS. Для выполнения некоторых более сложных операций существует
прерывание более высокого уровня INT 21H, которое сначала передает
управление в DOS. Например, при вводе с клавиатуры может потребоваться
подсчет введенных символов, проверку на максимальное число символов и
проверку на символ Return. Прерывание DOS INT 21H выполняет многие из этих
дополнительных вычислений и затем автоматически передает управление в
BIOS.
Материал данной главы подходит как для монохромных (черно-белых, BW),
так и для цветных видеомониторов. В гл. 9 и 10 приведен материал для
управления более совершенными экранами и для использования цвета.

КОМАНДА ПРЕРЫВАНИЯ: INT
________________________________________________________________

Команда INT прерывает обработку программы, передает управление в DOS
или BIOS для определенного действия и затем возвращает управление в
прерванную программу для продолжения обработки. Наиболее часто прерывание
используется для выполнения операций ввода или вывода. Для выхода из
программы на обработку прерывания и для последующего возврата команда INT
выполняет следующие действия:

- уменьшает указатель стека на 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

Значение 02 в регистре AH указывает команде INT 10H на выполнение операции
установки курсора. Значение строки и столбца должны быть в регистре DX, а
номер экрана (или страницы) в регистре BH (обычно 0). Содержимое других
регистров несущественно. Для установки строки и столбца можно также
использовать одну команду MOV c непосредственным шест. значением:

MOV DX,050CH ;Строка 5, столбец 12

ОЧИСТКА ЭКРАНА
________________________________________________________________

Запросы и команды остаются на экране пока не будут смещены в
результате прокручивания ("скроллинга") или переписаны на этом же месте
другими запросами или командами. Когда программа начинает свое выполнение,
экран может быть очищен. Очищаемая область экрана может начинаться в любой
позиции и заканчиваться в любой другой позиции с большим номером.
Начальное значение строки и столбца заносится в регистр 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, в последующих разделах будут показаны расширенные методы,
введенные в DOS версии 2.0. Операции из базовой DOS работают во всех
версиях, хотя в руководстве по DOS рекомендуется применять расширенные
возможности для новых разработок. В базовой версии DOS команды вывода на
экран более сложны, но команды ввода с клавиатуры проще в использовании,
благодаря встроенным проверкам.

ВЫВОД НА ЭКРАН: БАЗОВАЯ ВЕРСИЯ DOS
________________________________________________________________

Вывод на экран в базовой версии DOS требует определения текстового
сообщения в области данных, установки в регистре AH значения 09 (вызов
функции DOS) и указания команды DOS INT 21H. В процессе выполнения
операции конец сообщения определяется по ограничителю ($), как это
показано ниже:

NAMPRMP DB 'Имя покупателя?','$'
MOV AH,09 ;Запрос вывода на экран
LEA DX,NAMPRMP ;Загрузка адреса сообщ.
INT 21H ;Вызов DOS

Знак ограничителя "$" можно кодировать непосредственно после символьной
строки (как показано в примере), внутри строки: 'Имя покупателя?$', или в
следующем операторе DB '$'. Используя данную операцию, нельзя вывести на
экран символ доллара "$". Кроме того, если знак доллара будет
отсутствовать в конце строки, то на экран будут выводиться все последующие
символы, пока знак "$" не встретиться в памяти.
Команда LEA загружает адрес области NAMPRMP в регистр DX для передачи
в DOS адреса выводимой информации. Адрес поля NAMPRMP, загружаемый в DX по
команде LEA, является относительным, поэтому для вычисления абсолютного
адреса данных 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 и
затем увеличивается на 1 при каждом выводе на экран, пока не достигнет
шест. значения FF.

__________________________________________________________________________

page 60,132
TITLE ALLASC (COM) Вывод на экран ASCII-символов 00-FF
CODESC SEGMENT PARA 'Code'
ASSUME CS:CODESG,DS:CODESG,SS:CODESG,ES:NOTHING
ORG 100H
BEGIN: JMP SHORT MAIN
CTR DB 00,'S'

; Основная процедура:
; ------------------
MAIN PROC NEAR
CALL B10CDR ;Очистить экран
CALL C10SET ;Установить курсор
CALL D10DISP ;Вывести символ на экран
RET
MAIN ENDP
; Очистка экрана:
; --------------
B10CLR PROC
MOV AX,0600H
MOV BH,07
MOV CX,0000 ;Левая верхняя позиция
MOV DX,184FH ;Правая нижняя позиция
INT 10H
RET
B10CLR ENDP
; Установка курсора в 00,00:
; -------------------------
C10SET PROC
MOV AN,02
MOV BN,00
MOV DX,0000
INT 10H
RET
C10SET ENDP
; Вывод на экран ASCII символов:
; -----------------------------
D10DISP PROC
MOV CX,256 ;256 итераций
LEA DX,CTR ;Адрес счетчика
D20
MOV AH,09 ;Функция вывода символа
INT 21H
INC CTR ;Увеличить счетчик
LOOP D20 ;Уменьшить CX,
; цикл, если не ноль
RET ;Вернуться
D10DISP ENDP

CODESG ENDS
END BEGIN
__________________________________________________________________________

Рис.8.1. Вывод на экран набора символов кода ASCII

Так как символ доллара не выводится на экран и кроме того коды от
шест.08 до шест.0D являются специальными управляющими символами, то это
приводит к перемещению курсора и другим управляющим воздействиям. Задание:
введите программу (рис.8.1), выполните ассемблирование, компоновку и
преобразование в COM-файл. Для запуска программы введите ее имя, например,
В:ASCII.COM.
Первая выведенная строка начинается с пробельного символа (шест.00),
двух "улыбающихся лиц" (шест.01 и 02) и трех карточных символов (шест.03,
04 и 05). Код 07 выдает звуковой сигнал. Код 06 должен отобразиться
карточным символом "пики", но управляющие символы от шест.08 до 0D сотрут
его. Код 0D является "возвратом каретки" и приводит к переходу на новую
(следующую)строку. Код шест.0E - представляется в виде музыкальной ноты.
Символы после шест.7F являются графическими.
Можно изменить программу для обхода управляющих символов. Ниже
приведен пример фрагмента программы, позволяющий обойти все символы между
шест.08 и 0D. Вы можете поэкспериментировать, обходя только, скажем,
шест.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, область ввода требует наличия списка
параметров, содержащего поля, которые необходимы при выполнении команды
INT. Во-первых, должна быть определена максимальная длина вводимого
текста. Это необходимо для предупреждения пользователя звуковым сигналом,
если набран слишком длинный текст; символы, превышающие максимальную длину
не принимаются. Во-вторых, в списке параметров должно быть определенное
поле, куда команда возвращает действительную длину введенного текста в
байтах.
Ниже приведен пример, в котором определен список параметров для
области ввода. LABEL представляет собой директиву с атрибутом BYTE. Первый
байт содержит максимальную длину вводимых данных. Так как это однобайтовое
поле, то возможное максимальное значение его - шест.FF или 255. Второй
байт необходим DOS для занесения в него действительного числа введенных
символов. Третьим байтом начинается поле, которое будет содержать
введенные символы.

NAMEPAR LABEL BYTE ;Список параметров:
MAXLEN DB 20 ; Максимальная длина
ACTLEN DB ? ; Реальная длина
NAMEFLD DB 20 DUP (' ') ; Введенн

Список сторінок

Поділитися у соцмережах

☏ Замовлення реклами: +3805044-68-872

© Асоціація електронних бібліотек України

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