CodeNet / Языки программирования / Ассемблер / СПРАВОЧНИК по системе программирования ТУРБО АССЕМБЛЕР 2.0
СПРАВОЧНИК по системе программирования ТУРБО АССЕМБЛЕР 2.0
32-разрядные операнды
-----------------------------------------------------------------
Операции ADD и SUB работают с 8- или 16-битовыми операндами.
Если вы, к примеру, хотите сложить или вычесть 32-разрядные опе-
ранда, вы должны разбить операцию на ряд операций со значениями
размером в слово и использовать инструкции ADC и SBB.
Когда вы складываете два операнда, процессор 8086 записывает
состояние во флаг переноса (бит С в регистре флагов), которое по-
казывает, был ли выполнен перенос из приемника. Вы знакомы с
принципом переноса в десятичной арифметике: если вы складываете
90 и 10, то получаете перенос в третью цифру (разряд).
90
+ 10
----
100
Рассмотрим теперь сложение двух шестнадцатиричных значений:
FFFF
+ 1
-----
10000
Младшее слово результата равно нулю, перенос равен 1, пос-
кольку результат (10000h) не вмещается в 16 бит.
Инструкция ADC аналогична инструкции ADD, но в ней учитыва-
ется флаг переноса (предварительно установленный предыдущим сло-
жением). Всякий раз когда вы складываете два значения, превышаю-
щие по размеру слово, то младшие (менее значащие) слова нужно
сложить с помощью инструкции ADD, а остальные слова этих значений
- с помощью одной или нескольких инструкций ADC, последними скла-
дывая самые значащие слова. Например, следующие инструкции скла-
дывают значение в регистрах CX:BX, размером в двойное слово, со
значением, записанным в регистрах DX:AX:
.
.
.
add ax,bx
adc dx,cx
.
.
.
а в следующей группе инструкций выполняется сложение четверного
слова в переменной DoubleLong1 с четверным словом в переменной
DoubleLong2:
.
.
.
mov ax,[DoubleLong1]
add [DoubleLong2],ax
mov ax,[DoubleLong1+2]
adc [DoubleLong2+2],ax
mov ax,[DoubleLong1+4]
adc [DoubleLong1+4],ax
mov ax,[DoubleLong1+6]
adc [DoubleLong2+6],ax
.
.
.
Инструкция SBB работает по тому же принципу, что и инструк-
ция ADC. Когда инструкция SBB выполняет вычитание, в ней учитыва-
ется заем, произошедший в предыдущем вычитании. Например, следую-
щие инструкции вычитают значение, записанное в регистрах CX:BX,
из значения размером в двойное слово, записанного в регистрах
DX:AX:
.
.
.
sub ax,bx
sbb dx,cx
.
.
.
При работе с инструкциями ADC и SBB вы должны убедиться, что
флаг переноса не изменился с момента выполнения последнего сложе-
ния или вычитания, иначе состояние заема/переноса, хранящееся во
флаге переноса, будет потеряно. Например, в следующем фрагменте
программы сложение CX:BX с DX:AX выполняется некорректно:
.
.
.
add ax,bx ; сложить младшие слова
sub si,si ; очистить SI (флаг переноса
; сбрасывается в 0)
adc dx,cx ; сложить старшие слова...
; это будет работать некорректно,
; так как с момента последней
; операции сложения содержимое
; флага переноса потеряно
.
.
.
Увеличение и уменьшение
-----------------------------------------------------------------
Иногда в программе не Ассемблере требуется выполнить сложе-
ние, которое состоит просто в прибавлении к операнду значения 1.
Такая операция называется увеличением (инкрементацией). Аналогич-
но, из содержимого регистров и переменных в памяти иногда нужно
вычесть значение 1. Такая операция называется уменьшением (декре-
ментацией). Для таких операций, как изменение содержимого счетчи-
ка или продвижение регистров-указателей по памяти все операции
сложения и вычитания можно выполнять с помощью увеличения и
уменьшения.
Для выполнения таких часто требующихся действий в наборе
инструкций процессора 8086 предусмотрены две инструкции - INC
(увеличить) и DEC (уменьшить). Инструкция INC прибавляет к ре-
гистру или переменной в памяти 1, а инструкция DEC вычитает из
регистра или переменной в памяти 1.
Например, следующая программа заполняет 10-байтовый массив
TempArray числами 0, 1, 2, 3, 4, 5, 6, 7, 8, 9:
.
.
.
.DATA
TempArray DB 10 DUP (?)
FillCount DW ?
.
.
.
.CODE
.
.
.
mov al,0 ; первое значение,
; записываемое в TempArray
mov bx,OFFSET TempArray ; BX указывает на
; TempArray
mov [FillCount],10 ; число элементов,
; которыми нужно
; заполнить массив
FillTempArrayLoop:
mov [bx],al ; установить текущий
; элемент TempArray
inc bx ; ссылка на следующий
; элемент массива
; TempArray
inc al ; следующее записываемое
; значение
dec [FillCount] ; уменьшить счетчик
; числа заполняемых
; элементов
jnz FillTempArray ; обработать следующий
; элементе, если мы еще
; не заполнили все
; элементы
.
.
.
Почему предпочтительнее использовать инструкцию:
inc bx
а не инструкцию:
add bx,1
ведь делают они одно и то же? Это так, но в то время, как инст-
рукция ADD занимает 3 байта, инструкция INC занимает только 1
байт и выполняется быстрее. Фактически, более экономно выполнить
две операции INC, чем прибавить к регистру размером в слово зна-
чение 2 (увеличение и уменьшение регистров и переменных в памяти
размером в байт занимает 2 байта, что так же короче, чем сложение
и вычитание).
Короче говоря, инструкции INC и DEC - это наиболее эффектив-
ные инструкции, с помощью которых можно увеличивать и уменьшать
значения переменных в памяти и регистров. Их следует использовать
там, где это возможно.
