
- •Битовые операции Булевские команды
- •Команды сдвигов
- •Средства Ассемблера для битовых операций
- •Int 21h
- •Задание a5 Пример программы, включающей битовые операции Формулировка задания
- •Тексты программ
- •If not (ta eq TypeByte or ta eq TypeWord)
- •If pattern gt 111b
- •Выполнение задания на машине.
- •Inspecting treat_array
- •6356:0000 D5 75
- •6356:0002 80D5 00f5
Битовые операции Булевские команды
Эти команды оперируют с отдельными битами ячейки, независимо от других битов ячейки.
Инвертировать |
not opr |
|
"ИЛИ" (дизъюнкция) |
or dst,src |
|
"И" (конъюнкция) |
and dst,src |
|
"Исключающее ИЛИ" |
xor dst,src |
|
Логическое сравнение |
test opr1,opr2 |
opr1
|
Команда notна флаги не действует, остальные команды сбрасывают CF и OF, а флаги SF, ZF, PF изменяют по обычным правилам. Рассмотрим серию примеров, иллюстрирующих работу этих команд.
Пример. Команда инвертирования битов. Операция НЕ применяется к каждому биту.
mov al, 10011101b ; AL = 9Dh
not al ; AL = 01100010b = 62h
Остальные команды двухоперандные. Обычно они используются по следующей схеме. В источник src помещается так называемая "маска" — непосредственный операнд, посредством которого изменяются биты приемника.
Пример. Установка и сброс битов в соответствии с маской.
1) В регистре DL установить 6-й, 3-й и 1-й
биты. Применяем дизъюнкцию с маской,
используя правила поглощения
маска |
0 |
1 |
0 |
0 |
1 |
0 |
1 |
0 |
DL |
b7 |
b6 |
b5 |
b4 |
b3 |
b2 |
b1 |
b0 |
DL
|
b7 |
1 |
b5 |
b4 |
1 |
b2 |
1 |
b0 |
Команда имеет вид or dl, 01001010b(илиor dl, 4Ah).
2) В регистре CH сбросить 4-й и 3-й биты.
Применяем конъюнкцию с маской, используя
правила поглощения
маска |
1 |
1 |
1 |
0 |
0 |
1 |
1 |
1 |
CH |
b7 |
b6 |
b5 |
b4 |
b3 |
b2 |
b1 |
b0 |
CH
|
b7 |
b6 |
b5 |
0 |
0 |
b2 |
b1 |
b0 |
Команда and ch,11100111b (или and ch,0E7h).
3) Инвертировать 4-й и 3-й биты регистра
BH. Применяем "исключающее ИЛИ",
используя правила
маска |
0 |
0 |
0 |
1 |
1 |
0 |
0 |
0 |
CH |
b7 |
b6 |
b5 |
b4 |
b3 |
b2 |
b1 |
b0 |
CH
|
b7 |
b6 |
b5 |
|
|
b2 |
b1 |
b0 |
Команда xor ch,11000b (или xor ch,18h).
Команда xorприменяется для обнуления регистров: кодxor ax,axкороче, чемmov ax, 0(проверьте!).
Вместо команды
cmp ax,0 ;AX = 0 ?
по той же причине предпочитают использовать команду and ax,axили or ax,ax. Они оставляют содержимое AX неизменным, но устанавливают или сбрасывают флаг ZF.
Команду test используют, чтобы проверить, установлен ли определенный бит операнда, и при этом не "испортить" операнд.
Пример. Установлен ли 5-й бит DL? Если ДА, перейти на метку m.
test dl,00100000b
jnz m
С помощью этой команды легко проверить делимость числа на степени двойки. Например, если два младших бита числа — нули, то оно делится на 4:
test cx, 11b
jz yes
Команды сдвигов
Эти команды перемещают содержимое ячейки влево или вправо. Одним из операндов этих команд является количество сдвигов cnt. Оно либо равно 1, либо определяется содержимым регистра CL (при этом CL сохраняет свое содержимое после операции). Начиная с 286 процессора количество сдвигов, отличное от единицы, можно указывать как непосредственный операнд.
Естественно, возникает вопрос (для определенности говорим о сдвиге на одну позицию вправо): куда девается младший бит (точнее, его содержимое)? что записывается в старший бит? В командах сдвига эти вопросы решаются по-разному.
Логические и арифметические сдвиги.
Логический/арифметический сдвиг влево |
shl/sal opr,cnt |
(Shift Logical/Arithmetic Left) | |
CF opr
0
|
Логический сдвиг вправо |
shr opr,cnt |
(Shift Logical Right) | |
opr CF 0
|
Арифметический сдвиг вправо |
sar opr,cnt |
(Shift Arithmetic Right) | |
opr CF
|
Флаг CF устанавливается в соответствии с рисунками. Флаг OF имеет смысл , если cnt = 1.
Сначала остановимся на формальном синтаксисе команд.
Неправильно |
Правильно |
1) sar ax,2(в 286 и выше — правильно!) |
sar ax,cl |
shr dx,bl(количество сдвигов только в CL) |
2) shl ax,1 |
Арифметические сдвиги предназначены для выполнения умножения и деления на степени двойки (табл.6.1).
Таблица 6.1 | ||
операнд |
умножение |
деление |
знаковый |
sal/shl |
sar |
беззнаковый |
shr |
Умножение на 2 — сдвиг влево и приписывание
справа нуля. Докажите, что OF = CF
SF.
Деление на 2 — сдвиг вправо, в CF попадает остаток от деления. При арифметическом сдвиге вправо дублируется знаковый бит: поэтому отрицательное число остается отрицательным.
Пример. Пусть AL = –120 = 10001000.sar al,1дает AL = –60 = 11000100. Проверьте.
К сожалению, результат деления с помощью команды sarне всегда совпадает с результатом деления, полученным с помощью командыidiv. Сравните результат от деления –5 на 2, полученный с помощью и той и другой команды.
Циклические сдвиги.
Циклический сдвиг влево |
rol opr,cnt |
(ROtate Left) | |
|
Циклический сдвиг вправо |
ror opr,cnt |
(ROtate Right) | |
|
Циклический сдвиг влево через перенос |
rcl opr,cnt |
(Rotate through Carry Left) | |
|
Циклический сдвиг вправо через перенос |
rcr opr,cnt |
(Rotate through Carry Right) | |
|
Пример. Двойное слово в DX:AX умножить на 4.
shl ax,1 ; Старший бит AX — в CF
rcl dx,1 ; CF — в младший бит DX
shl ax,1
rcl dx,1
Пример. Сосчитать количество единичных битов в AX. Результат поместить в BX.
xor bx,bx ;обнулить счетчик единичных битов
mov cx,16 ;разрядность слова — в CX
n: rol ax,1 ;циклический сдвиг влево, старший бит — в CF
adc bx,0 ;добавить величину CF к счетчику
loop n
После выполнения этого фрагмента в AX будет восстановлено первоначальное содержимое.
Пример. Вращать содержимое AX влево, пока в старшем (15-ом) бите не появится '1', и перейти на метку n1. Если AX = 0, то перейти на метку n0.
Воспользуемся командой rcl(можно иrol)
и тем, что OF = CFSF.
cmp ax,0
je n0 ; если AX = 0 — на n0
js n1 ; если старший бит установлен — на n1
mov cx,16 ; разрядность AX — в CX
m: rcl ax,1
jo n1 ; если CF = 0 и SF = 1 — на n1
loop m
(метки n0иn1не показаны)