Сист. прогр. Ч2 (1085771), страница 3
Текст из файла (страница 3)
сложение/вычитание регистр - память;
сложение/вычитание регистр - непосредственное значение;
сложение/вычитание память - непосредственное значение.
page 60, 132
TITLE EXADD (СОM) ;Сложение и вычитание
CODESG SEGMENT PARA ‘Code’
ASSUME CS:CODESG, DS:CODESG, SS:CODESG
ORG 100H
BEGIN: JMP SHORT MAIN
; Элементы данных
BYTEA DB 64H
BYTEB DB 40H
BYTEC DB 16H
WORDA DW 4000H
WORDB DW 2000H
WORDC DW 1000H
;0сновная процедура:
MAIN PROC NEAR
CALL B10ADD ; Вызвать сложение ADD
CALL C10SUB ; Вызвать вычитание SUB
RET
MAIN ENDP
; Пример сложения байт:
B10ADD PROC
MOV AL, BYTEA
MOV BL, BYTEB
ADD AL, BL ;Регистр и регистр
ADD AL, BYTEC ; Память и регистр
ADD BYTEA, BL ;Регистр и память
ADD BL,10H ;Непосредств.и регистр
ADD BYTEA, 25H ;Непосредств.и память
RET
B10ADD ENDP
; Пример вычитания слов:
C10SUB PROC
MOV AX, WORDA
MOV BX, WORDB
SUB AX, BX ;Регистр из регистра
SUB AX, WORDC ;Память из регистра
SUB WORDA, BX ;Регистр из памяти
SUB BX, 1000H ;Непосредств. из per.
SUB WORDA, 256H ;Непосредств. из пам.
RET
C10SUB ENDP
CQDESG ENDS
END BEGIN
Рис.10.1. Примеры команд ADD и SUB
Поскольку прямой операции память-память не существует, то данная операция выполняется через регистр. В следующем примере к содержимому слова WORDB прибавляется содержимое слова WORDА, описанные как DW:
MOV AX, WORDA
ADD AX, WORDB
MOV WORDB, AX
Переполнения
Опасайтесь переполнений в арифметических операциях. Один байт содержит знаковый бит и семь битов данных, т.е. значения от -128 до + 127, Результат арифметической операции может легко превзойти емкость однобайтового регистра. Например, результат сложения в регистре AL, превышающий его емкость, автоматически не переходит в регистр АН. Предположим, что регистр AL содержит 60Н, тогда команда
ADD AL,20H
генерирует в AL сумму - 80Н. Но операция также устанавливает флаг переполнения и знаковый флаг в состояние "отрицательно". Причина заключается в том, что 80Н или двоичное 1000 0000 является отрицательным числом. Таким образом, вместо +128 сумма равна -128. Так как регистр AL слишком мал для такой операции, следует воспользоваться регистром АХ. В следующем примере команда CBW (Convert Byte to Word - преобразовать байт в слово) преобразует 60Н в регистре AL в 0060Н в регистре АХ, передавая при этом знаковый бит (0) через регистр АН. Команда ADD генерирует теперь в регистре АХ правильный результат: 0080Н, или +128:
CBW ;Расширение AL до АХ
ADD AX, 20H ;Прибавить к АХ
Но полное слово имеет также ограничение: один знаковый бит и 15 бит данных, что соответствует значениям от -32768 до + 32767. Рассмотрим далее, как можно обрабатывать числа, превышающие эти пределы.
Многословное сложение
Максимально возможное значение в регистре + 32767 ограничивает возможности компьютера для выполнения арифметических операций. Рассмотрим два способа представления арифметических операций. Первый способ более прост, но специфичен, второй -сложнее, но имеет общий характер.
На рис. 10.2 процедура D10DWD демонстрирует простой способ сложения содержимого одной пары слов (WORD1А и WORD1B) с содержимым второй пары слов (WORD2A и WORD2B) и сохранения суммы в третьей паре слов (WORD3A и WORD3B). Сначала выполняется сложение правых слов:
WORD1B BC62
WORD2B 553A
Сумма: 1119C
page 60,132
TITLE EXDBADD (СОM) ;Пример сложения двойных слов
CODESG SEGMENT PARA ‘Code’
ASSUME CS:CODESG, DS:CODESG, SS:CODESG
ORG 100H
BEGIN: JMP SHORT MAIN
WORD1A DW 0123H
WORD1B DW 0BC62H
WORD2A DW 0012H
WORD2B DW 553AH
WORD3A DW ?
WORD3B DW ?
; Основная процедура:
MAIN PROC NEAR
CALL D1ODWD
CALL E10DWD
RET
MAIN ENDP
; Пример сложения двойных слов:
D1ODWD PROC
MOV АХ, WORD1B ;Сложить правые слова
ADD AX, WORD2B
MOV WORD3B, AX
MOV AX, WORD1A ; Сложить левые слова
ADC AX, WORD2A ; с переносом
MOV WORD3A, AX
RET
DIODWD ENDP
; Сложение чисел любой длины:
E10DWD PROC
CLC ;Очистить флаг переноса
MOV СХ, .2 ;Установить счетчик
LEA SI, WORD1B ; Левое слово DWORD1
LEA DI., WORD2B ; Левое слово DWORD2
LEA BX, WORD3B ; Левое слово суммы
E20: MOV AX,[SI] ; Поместить слово в АХ
ADC АХ, [ DI] ;Сложить с переносом
MOV [ВХ], АХ ; Сохранить слово
DEC SI
DEC SI
DEC DI
DEC DI
DEC BX
DEC BX
LOOP Е20 ;Повторить цикл
RET
E10DWD ENDP
CODESG ENDS
END BEGIN
Рис.10.2. Сложение двойных слов
Сумма 1119СН превышает емкость регистра АХ. Переполнение вызывает установку флага переноса в 1. Затем выполняется сложение левых слов, но в данном случае вместо команды ADD используется команда сложения с переносом ADC (Add with Carry). Эта команда складывает два значения, и если флаг CF уже установлен, к сумме прибавляется 1:
WORDIA 0123
WORD2А 0012
Плюс перенос __ 1
Сумма: 0136
При использовании отладчика DEBUG для трассировки арифметических команд можно увидеть эту сумму 0136 в регистре АХ, и обратные значения 3601 в поле WORD3A и 9С11 в поле WORD3B.
На рис. 10.2 процедура E10DWD демонстрирует подход к сложению значений любой длины. Действие начинается со сложения самых правых слов складываемых полей. В первом цикле складываются правые слова, во втором - слова, расположенные левее. При этом адреса в регистрах SI, DI и ВХ уменьшаются на 2. По две команды DEC выполняют эту операцию для каждого регистра. Применять команду
SUB reg, 02
в данном случае нельзя, так как при этом будет очищен флаг переноса, что приведет к искажению результата сложения.
Ввиду наличия цикла используется только одна команда сложения ADC. Перед циклом команда CLC (CLear Carry -очистить флаг переноса) устанавливает нулевое значение флага переноса. Для работы данного метода необходимо: 1) обеспечить смежность слов, 2) выполнять обработку справа налево и 3) загрузить в регистр СХ число складываемых слов.
Для многословного вычитания используется команда SBB (SuBtract with Borrow - вычитание с заемом), эквивалентная команде ADC. Заменив в процедуре E10DWD (рис. 10.2) команду ADC на SBB, получим процедуру для вычитания.
БЕЗЗНАКОВЫЕ И ЗНАКОВЫЕ ДАННЫЕ
Многие числовые поля являются беззнаковыми, например номер абонента, адрес памяти. Некоторые числовые поля предполагаются всегда положительными, например норма выплаты, день недели, число PI. Другие числовые поля являются знаковыми, так как их содержимое может быть положительным или отрицательным. Например, алгебраическое число или долговой баланс покупателя, который может быть отрицательным при переплатах.
Для беззнаковых данных все биты являются битами данных и вместо ограничения + 32767 регистр может содержать числа до + 65535. Для знаковых данных левый байт является знаковым битом. Команды ADD и SUB не делают разницы между знаковыми и беззнаковыми данными, они просто складывают и вычитают биты. В следующем примере сложения двух двоичных чисел первое число содержит единичный левый бит. Для беззнакового числа биты представляют положительное число 249, для знакового отрицательное число -7:
Беззнаковое Знаковое
11111001 249 -7
00000010 2 +2
11111011 251 -5
Двоичное представление результата сложения одинаково для беззнакового и знакового числа. Однако биты представляют + 251 для беззнакового числа и -5 для знакового. Таким образом, числовое содержимое поля может интерпретироваться по-разному.
Состояние переноса возникает в случае, когда имеется перенос в знаковый разряд. Состояние переполнения возникает в случае, когда перенос в знаковый разряд не создает переноса из разрядной сетки или перенос из разрядной сетки происходит без переноса в знаковый разряд. Если при сложении беззнаковых чисел возникает перенос, то результат получается неправильным:
Беззнаковое Знаковое CF OF
11111100 252 -4
00000101 5 +5
00000001 1 1 1 0
(неправильно)
В случае возникновения переполнения при сложении знаковых чисел результат получается неправильный:
Беззнаковое Знаковое CF OF
01111001 121 +121
00001011 11 +11
10000100 132 -124 0 1
(неправильно)
При операциях сложения и вычитания может одновременно возникнуть и переполнение, и перенос:
Беззнаковое Знаковое CF OF
11110110 246 -10
10001001 137 -119
01111111 127 +127 1 1
(неправильно) (неправильно)
УМНОЖЕНИЕ
Операция умножения для беззнаковых данных выполняется командой MUL, а для знаковых - IMUL (Integer Multiplication -умножение целых чисел). Ответственность за контроль над форматом обрабатываемых чисел и за выбор подходящей команды умножения лежит на самом программисте. Существуют две основные операции умножения.
Умножение байта на байт. Множимое находится в регистре AL, а множитель - в байте памяти или в однобайтовом регистре. После умножения произведение находится в регистре АХ. Операция игнорирует и стирает любые данные, которые находились в регистре АН.
Умножение слова на слово. Множимое находится в регистре АХ, а множитель - в слове памяти или в регистре. После умножения произведение образуется в двойном слове, для которого требуется два регистра: старшая (левая) часть произведения находится в регистре DX, а младшая (правая) часть - в регистре АХ. Операция игнорирует и стирает любые данные, которые были в регистре DX.
В единственном операнде команд MUL и IMUL указывается множитель. Рассмотрим следующую команду:
MUL MULTR
Если поле MULTR определено как байт (DB), то операция предполагает умножение содержимого AL на значение байта из поля MULTR. Если поле MULTR определено как слово (DW), то операция предполагает умножение содержимого АХ на значение слова из поля MULTR. Если множитель находится в регистре, то длина регистра определяет тип операции, как показанно ниже:
MUL CL ;Байт-множитель: множимое в AL, произведение в АХ
MUL ВХ ;Слово-множитель: множимое в АХ, произведение в DX:AX ,
Беззнаковое умножение: команда MUL
Команда MUL (MULtiplication - умножение) перемножает беззнаковые числа. На рис. 10.3 в процедуре C10MUL дано три примера умножения: байт на байт, слово на слово и слово на байт. Первый пример команды MUL перемножает 80Н (128) на 47Н (64). Произведение 2000Н (8192) получается в регистре АХ.
Второй пример команды MUL генерирует 10000000Н в
регистрах DX:AX.
Третий пример команды MUL перемножает слово на байт и требует расширения байта BYTE1 до размеров слова. Так как предполагаются беззнаковые данные, то в примере левый бит регистра АН равен нулю. (При использовании команды CBW значение левого бита регистра AL может быть 0 или 1.) Произведение 00400000Н получается в регистровой nape DX:AX.
Знаковое умножение: команда IMUL Команда IMUL (Integer MULtiplication - умножение целых чисел) перемножает знаковые числа. На рис. 10.3 в процедуре D10IMUL используются те же три примера умножения, что и в процедуре С10MUL, но вместо команд MUL записаны команды IMUL.
page 60,132
TITLE EXMULT (СОM) ;Пример команд умножения
CODESG SEGMENT PARA ‘Code’
ASSUME CS: CODESG, DS: CODESG, SS: CODESG
ORG 100H
BEGIN: JMP SHORT MAIN
BYTE1 DB 80H
BYTE2 DB 40H
WORD1 DW 8000H
WORD2 DW 4000H
;Основная процедура:
MAIN PROC NEAR
CALL С 1 OMUL ; Вызвать умнож. MUL
CALL D10IMUL ; Вызвать умнож. IMUL
RET
MAIN ENDP
; Пример умножения MUL:
C10MUL PROC
MOV AL, BYTE1 ;Байт * байт
MUL BYTE2 ; произведение в АХ
MOV AX, WORD1 ;Слово * слово
MUL WORD2 ; произведение в DХ : АХ