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 - это наиболее эффектив- ные инструкции, с помощью которых можно увеличивать и уменьшать значения переменных в памяти и регистров. Их следует использовать там, где это возможно.