Ещё о командах ассемблера.
Обратите внимание: Большинство примеров ниже использует 8 битные числа, это сделано для того, чтобы вам было легче понять, как это работает.
Функции сдвига (сдвиг логический операнда влево/вправо)
SHL операнд, количество_сдвигов
SHR операнд, количество_сдвигов
SHL и SHR сдвигают биты операнда (регистр/память) влево или вправо соответственно на один разряд.
Указанное выше действие повторяется количество раз, равное значению второго операнда.
Пример:
; al = 01011011 (двоичное)
shr al, 3
Это означает: сдвиг всех битов регистра al на 3 разряда вправо. Так что al станет 00001011. Биты слева заполняются нулями, а биты справа выдвигаются. Последний выдвинутый бит, становится значением флага переноса cf.
Бит переноса это бит флагового регистра процессора. Этот регистр не такой как eax или ecx, к которому вы можете непосредственно обращаться (хотя есть опкоды, которые это делают), его содержание, зависит от результатов многих команд. Об этом я вам расскажу позже, единственное, что вы должны сейчас запомнить, это то, что флаг переноса это бит во флаговом регистре и что он может быть установлен (т.е. равен 1) или сброшен (равен 0).
Команда shl такая же, как и shr, но сдвигает влево.
; bl = 11100101 (двоичное)
shl bl, 2
После выполнения команды регистр bl будет равен 10010100 (двоичное). Два последних бита заполнились нулями, флаг переноса установлен, потому, что последний выдвинутый слева бит был равен 1
Здесь есть еще два других опкода: (сдвиг арифметический операнда влево/вправо)
SAL операнд, количество_сдвигов
SAR операнд, количество_сдвигов
Команда SAL такая же, как SHL, а вот SAR не совсем такая, как SHR. Команда SAR также, как и SHR сдвигает все биты операнда вправо на один разряд, при этом выдвигаемый справа бит становится значением флага переноса cf. Обратите внимание: одновременно слева в операнд вдвигается не нулевой бит, как в SHR, а значение старшего бита операнда. Пример:
al = 10100110
sar al, 3
al = 11110100
sar al, 2
al = 11111101
bl = 00100110
sar bl, 3
bl = 00000010
Циклический сдвиг
rol операнд, количество_сдвигов ; циклический сдвиг операнда влево
ror операнд, количество_сдвигов ; циклический сдвиг операнда вправо
rcl операнд, количество_сдвигов ; циклический сдвиг операнда влево через флаг переноса
rcr операнд, количество_сдвигов ; циклический сдвиг операнда вправо через флаг переноса
Циклический сдвиг напоминает смещение, выдвигаемые биты, снова вдвигаются с другой стороны:
Пример: команды ror (циклический сдвиг вправо)
бит
|
бит
|
бит
|
бит
|
бит
|
бит
|
бит
|
бит
|
выдвигается |
||
Операнд |
1 |
0 |
0 |
1 |
1 |
0 |
1 |
1 |
||
ror операнд,3 |
1 |
0 |
0 |
1 |
1 |
011 |
||||
Результат |
0 |
1 |
1 |
1 |
0 |
0 |
1 |
1 |
Как видно из рисунка выше, биты вращаются, то есть каждый бит, который выталкивается снова вставляется с другой стороны. Флаг переноса cf содержит значение последнего выдвинутого бита.
RCL и RCR сдвигают все биты операнда влево (для RCL) или вправо (для RCR) на один разряд, при этом старший(для RCL) или младший(для RCR) бит становится значением флага переноса cf; одновременно старое значение флага переноса cf вдвигается в операнд справа(для RCL) или слева(для RCR) и становится значением младшего(для RCL) или старшего(для RCR) бита операнда. Указанные действия повторяются количество раз, равное значению второго операнда.
ROL и ROR сдвигают все биты операнда влево(для ROL) или вправо(для ROR) на один разряд, при этом старший(для ROL) или младший(для ROR) бит операнда вдвигается в операнд справа(для ROL) или слева(для ROR) и становится значением младшего(для ROL) или старшего(для ROR) бита операнда; одновременно выдвигаемый бит становится значением флага переноса cf. Указанные действия повторяются количество раз, равное значению второго операнда.
Стековые операции.
Иногда при вызове некоторых подпрограмм нужно сохранить все регистры для корректной работы программы в дальнейшем. Для этого вы будете последовательно сохранять каждый регистр в стеке и извлекать точно также:
Push eax
Push ebx
Push ecx
[также все остальные регистры]
……
[вытаскиваем оттуда остальные регистры]
Pop ecx
Pop ebx
Pop eax
Такой подход очень громоздок именно для этого и создана команда pushad. Она сохраняет все расширенные регистры в стеке. Соответственно команда popad нужна для извлечения из стека всех регистров.
Pushad
……..
Popad
Также есть команды для сохранения младших регистров pushaw и popaw. Они равносильны командам PUSH AX, CX, DX, BX, SP, BP, SI, DI и POP DI,SI,BP,BX,DX,CX,AX.
Иногда надо сохранять значения флагов после выполнения некоторой операции. Для этого нужны команды pushf и popf. Эти команды сохраняют в стеке значение регистра флагов или восстанавливают его оттуда.
Изменение флагов процессора.
CLC установка CF=0
CLD установка DF=0
CLI установка IF=0
LAHF загрузка регистра AH из регистра флагов: устанавливает биты 7, 6, 4, 2 и 0 по значениям флагов SF ZF AF PF CF.
SAHF запись регистра AH в регистр флагов: устанавливает флаги SF ZF AF PF CF по битам 7, 6, 4, 2 и 0 регистра AH.
STC установка CF=1
STD установка DF=1
STI установка IF=1
На этом уроке мы узнали больше о командах ассемблера. На следующем уроке я вам расскажу об операциях с блоками данных. Не расслабляемся, читаем следующий урок.