0101 0101 0101
0011 0011 0011
---- ---- ----
Результат: 0001 0111 0110
Для следующих несвязанных примеров, предположим, что 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. Хотя команды сравнения CMP могут
быть понятнее, можно применить команду OR для следующих целей:
1. OR CX,CX ;Проверка CX на нуль
JZ ... ;Переход, если нуль
2. OR CX,CX ;Проверка знака в CX
JS ... ;Переход, если отрицательно
Команда TEST действует аналогично команде AND, но устанавливает
только флаги, а операнд не изменяется. Ниже приведено несколько примеров:
1. TEST BL,11110000B ;Любой из левых бит в BL
JNZ ... ; равен единице?
2. TEST AL,00000001B ;Регистр AL содержит
JNZ ... ; нечетное значение?
3. TEST DX,OFFH ;Регистр DX содержит
JZ ... ; нулевое значение?
Еще одна логическая команда NOT устанавливает обpатное значение бит в
байте или в слове, в регистре или в памяти: нули становятся единицами, а
единицы - нулями. Если, например, pегистр AL содержит 1100 0101, то
команда NOT AL изменяет это значение на 0011 1010. Флаги не меняются.
Команда NOT не эквивалентна команде NEG, которая меняет значение с
положительного на отрицательное и наоборот, посредством замены бит на
противоположное значение и прибавления единицы (см. "Отрицательные числа"
в гл.1.).
ПРОГРАММА: ИЗМЕНЕНИЕ СТРОЧНЫХ БУКВ НА ЗАГЛАВНЫЕ
________________________________________________________________
Существуют различные причины для преобразований между строчными и
заглавными буквами. Например, вы могли получить файл данных, созданный на
компьютере, который работает только с заглавными буквами. Или некая
программа должна позволить пользователям вводить команды как заглавными,
так и строчными буквами (например, YES или yes) и преобразовать их в
заглавные для проверки. Заглавные буквы от A до Z имеют шест. коды от 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 увеличивается для очередного символа и осуществляется переход
на следующий цикл.
__________________________________________________________________________
TITLE CASE (COM) Перекод. в заглавные буквы
0000 CODESG SEGMENT PARA 'CODE'
ASSUME CS:CODESG,DS:CODESG,SS:CODESG
0001 ORG 100H
0001 EB 1C 90 BEGIN: JMP MAIN
; -------------------------------------------
0003 43 68 61 6E 67 65 TITLEX DB 'Change to uppercase letters'
20 74 6F 20 75 70
70 65 72 63 61 73
65 20 6C 65 74 74
65 72 73
; -------------------------------------------
011E MAIN PROC NEAR
011E 8D 1E 0104 R LEA BX,TITLEX+1 ;Адрес первого симв.
0122 B9 001F MOV CX,31 ;Число символов
0125 B20:
0125 8A 27 MOV AH,[BX] ;Символ из TITLEX
0127 80 FC 61 CMP AH,61H ;Это
012A 72 0A JB B30 ; прописная
012C 80 FC 7A CMP AH,7AH ; буква
012F 77 05 JA B30 ; ?
0131 80 E4 DF AND AH,11011111B ;Да - преобразовать
0134 88 27 MOV [BX],AH ;Записать в TITLEX
0136 B30:
0136 43 INC BX ;Следующий символ
0137 E2 EC LOOP B20 ;Повторить цикл 31 раз
0139 C3 RET
013A MAIN ENDP
013A CODESG ENDS
END BEGIN
__________________________________________________________________________
Рис.7.6. Изменение строчных букв на прописные.
Используемый таким образом регистр BX действует как индексный регистр
для адресации в памяти. Для этих целей можно использовать также регистры
SI и DI.
КОМАНДЫ СДВИГА И ЦИКЛИЧЕСКОГО СДВИГА
________________________________________________________________
Команды сдвига и циклического сдвига, которые представляют собой
часть логических возможностей компьютера, имеют следующие свойства:
- обрабатывают байт или слово;
- имеют доступ к регистру или к памяти;
- сдвигают влево или вправо;
- сдвигают на величину до 8 бит (для байта) и 16 бит (для слова)
- сдвигают логически (без знака) или арифметически (со знаком).
Значение сдвига на 1 может быть закодировано как непосредcтвенный
операнд, значение больше 1 должно находиться в регистре CL.
Команды сдвига
----------------
При выполнении команд сдвига флаг CF всегда содержит значение
последнего выдвинутого бита. Существуют следующие команды cдвига:
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 ;Циклический сдвиг влево с переносом
Следующая последовательность команд иллюстрирует операцию
циклического сдвига 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.
Приведем основную логику, которую используют многие программисты в
таком случае:
инициализация стека и сегментных регистров
вызов подпрограммы цикла
возврат
Подпрограмма цикла может быть спланирована следующим образом:
инициализация регистров значениями адресов
и числа циклов
Метка: пересылка одного байта
увеличение адресов на 1
уменьшение счетчика на 1:
если счетчик не ноль, то идти на метку
если ноль, возврат