7. Команды целочисленной арифметики
Цель работы: изучение арифметических команд Ассемблера, принципов их действия и применения в программе.
Теоретическая часть
Команды целочисленной двоичной арифметики
Команда ADD
Команда суммирует два операнда, результат сохраняет в операнде назначение.
Синтаксис: ADD <назначение>, <источник>
Примеры:
add ax, [bx] ;элемент, хранящийся по адресу, указанному ;в регистре BX, сложить с содержимым регистра AX, ;результат сохранить в регистре AX. add ax, 10 ;к содержимому регистра AX прибавить 10, ;результат сохранить в регистре AX. add bh, LM ;к содержимому регистра BH прибавить значение ;переменной LM, результат сохранить в регистре BH. |
Команда INC
Команда увеличивает значение операнда на 1.
Синтаксис: INC <назначение>
Примеры:
inc CX ;увеличить значение регистра CX на 1 inc [BX] ;значение, хранящееся по адресу, ;указанному в регистре BX, увеличить на 1 inc LM ;значение переменной LM увеличить на 1. |
Команда SUB
Команда из операнда назначение вычитает операнд источник. Результат сохраняется в операнде назначение.
Синтаксис: SUB <назначение>, <источник>
Примеры:
sub ax, [bx] ;значение, хранящееся по адресу, указанному ;в регистре BX, вычитается из регистра AX и ;результат сохраняется в регистре AX sub ax, 10 ;из содержимого регистра AX вычитается число 10, ;результат сохраняется в регистре AX. sub bh, LM ;содержимое переменной LM вычитается из ;регистра DH, результат сохраняется в регистре BH. |
Команда DEC
Команда уменьшает значение операнда на 1.
Синтаксис: DEC <назначение>
Примеры:
dec cx ;значение регистра CX уменьшается на единицу dec [bx] ;значение, хранящееся по адресу, указанному в ;регистре BX, уменьшается на единицу dec LM ;значение переменной LM уменьшается на 1 |
Команда NEG
Действие команды: операнд назначение вычитается из 0, и результат помещается в назначение.
Синтаксис: NEG <назначение>
Примеры:
neg CX ;изменить знак значения в регистре CX neg [BX] ;изменить знак значения, хранящегося по адресу, ;указанному в регистре BX neg LM ;изменить знак переменной LM |
Команда изменения знака neg не изменит значения операнда, если число находится на границе допустимого диапазона значений. Например, последовательность команд
mov AL, -128
neg AL
оставит без изменения значение регистра AL, так как 128 и -128 имеют одинаковое внутреннее представление (80H).
Команда MUL
Команда предназначена для беззнакового умножения. Операнд–источник умножается на содержимое регистра–накопителя. Если операндом–источником является величина типа BYTE, то источник умножается на содержимое регистра AL и результат сохраняется в регистре AX. Если операндом–источником является величина типа WORD, то источник умножается на содержимое регистра AX и результат помещается в пару регистров DX:AX
Синтаксис: MUL <источник>
Примеры:
mul CL ;CL умножается на AL и результат сохраняется ;в регистре AX mul word ptr [BX] ;значение, хранящееся по адресу, указанному ;в регистре BX, умножается на AX, результат ;помещается в пару регистров DX:AX mul LM ;действие команды зависит от размера памяти, ;адресуемой LM |
Команда IMUL
Команды MUL и IMUL похожи. Разница в том, что команда IMUL при умножении учитывает знаки операндов.
Синтаксис: IMUL <источник>
Рассмотрим команды деления. В командах деления предполагается, что делимое занимает в два раза больше памяти, чем делитель. Результат представляет собой пару значений: частное и остаток, а каждая из полученных величин занимает столько же места, что и делитель.
Команда DIV
Команда осуществляет беззнаковое деление. Регистр–накопитель делится на операнд, и если источником является величина типа BYTE, то содержимое регистра AX делится на операнд–источник, а частное помещается в регистр AL, а остаток от целочисленного деления – в регистр AH. В случае, когда источником является операнд типа WORD, в качестве делимого предполагается пара регистров DX:AX. Результат деления помещается в регистр AX, а остаток – в регистр DX.
Синтаксис: DIV <источник>
Примеры:
div CL ;содержимое регистра AX делится на CL, ;частное – в AL, остаток – в AH div LM ;действие команды зависит от размера памяти, ;адресуемой LM |
Команда IDIV
Команда осуществляет деление со знаком. Действия команд DIV и IDIV схожи. Разница в том, что команда IDIV при делении учитывает знаки операндов.
Синтаксис: IDIV <источник>
Примеры:
idiv DL ;содержимое регистра AX делится на DL, со знаком div MEM_WORD ;разделить DX:AX на слово памяти, со знаком ;частное – в AX, остаток – в DX |
Использование команд деления может привести к неожиданным результатам. В случае, если в результате деления получится величина, превосходящая максимально допустимое значение (8 или 16 бит), или если делитель окажется равным 0, будет сгенерировано программное прерывание Divide Overflow (переполнение при делении).
Например, в последовательности
mov ax, 1000 mov bl, 2 div bl |
результат должен быть 500. Эта величина должна быть сохранена в однобайтовом регистре AL. В этом случае выполнение программы будет прервано и на консоль будет выведено сообщение об ошибке, т.к. число со знаком, помещаемое в один байт, должно находиться в диапазоне [-128, +127].
Команда CBW
Команда преобразует байт в слово, воспроизводя старший 7-й бит регистра AL во всех битах регистра AH. Таким образом, команда CBW позволяет сложить байт и слово, вычесть слово из байта и т.д.
Синтаксис: CBW
Например:
cbw add AX, BX ;сложить байт в AL со словом в BX cbw imul BX ;умножить байт в AL на слово в BX |
Команда CWD
Команда преобразует слово в двойное слово, воспроизводя старший 15-й бит регистра AX во всех битах регистра DX. Таким образом, команда CWD позволяет разделить слово на слово. Например:
cwd idiv BX ;разделить слово в AX на слово в BX |
Синтаксис: CWD
Вычисление значения выражения
Рассмотрим задачу вычисления арифметического выражения. Так как Ассемблер не располагает встроенными средствами ввода и вывода чисел, для работы с числовыми переменными необходимы некоторые преобразования. Так, перед отображением числа его надо преобразовать в последовательность символов. Вводить Ассемблер также позволяет только символы, поэтому для работы с числами введенную строку надо преобразовать в число.
Рассмотрим пример преобразования числа в строку. Пусть numar – число, которое необходимо вывести на экран. Преобразуем его в строку символов s и выведем её на экран.
s db 6 dup(’ ’),’$’ .code ... mov ax, ;число может быть отрицательным ;или положительным push ax ;сохраняем число из ax в стеке mov si, 10 ;делитель для выделения младшего разряда mov di, 5 ;максимально число типа dw может занимать 6 ;позиций. Устанавливаем указатель на последнюю ;позицию в строку результата mov dx, 0 ;dx=0, так как (dx:ax)/si cmp ax, 0 ;проверяем знак числа jge m ;если число положительное, переходим на метку m neg ax ;если число отрицательное, меняем знак m: div si ;значение из (dx:ax) делим на 10, выделяя ;последний разряд числа, который помещается в ;регистр dx. Так как это число не будет больше, ;чем 9, оно помещается в dl add dl, 30h ;преобразуем полученную цифру в символ mov s[di], dl ;вставляем полученный символ в строку результата xor dx, dx ;очищаем dx dec di ;сдвигаем позицию указателя в строке влево cmp ax, 0 ;проверяем, преобразованы ли все символы числа jne m ;если преобразованы не все символы, возвращаемся ;на начало цикла pop ax ;если всё число преобразовано, извлекаем ;первоначальное значение из стека для проверки ;знака cmp ax, 0 ;проверяем знак числа jge m1 ;если число >0, переходим на вывод строки mov s[di], ’-’ ;если число отрицательное, перед числом ;вставляем ”-” m1: mov ah, 9 ;вывод строки, содержащей преобразованное число lea dx, s int 21h |
Пример
Вычислим значение выражения ((120+15)/5-12)*16, значения переменных задаются в тексте программы.
data a db 120 b db 15 c db 5 d db 12 e db 16 .code mov al, a ; al=120 add al, b ; al=120+15 mov ah, 0 div c ; al=(120+15)/5 sub al, d ; al=(120+15)/5-12 mov ah,0 mul e ; ax=((120+15)/5-12)*16 ;Для преобразования введенной строки в число ;со знаком можно использовать следующий алгоритм: .data n dw 0 ;результирующее число mult10 dw 1 ;отвечает за разряд числа i. Будет ;содержать значение 10i. ten dw 10 ;множитель 10 sir db 8 dup (?) ;исходная строка .code ... mov ah, 3fh ;вводим число в виде набора символов mov bx, 0 lea dx, sir int 21h ;регистр ax будет содержать количество введенных ;символов +2 mov di, ax ;сохраняем количество введенных символов в di sub di, 3 ;находим позицию последнего символа cmp di, 0 ;для случая числа из одной цифры je b a: mov al, sir[di] ;копируем символ, на который показывает di, в al sub al, 30h ;преобразуем символ в число (цифру) mov ah, 0 ;ah обнуляется mul mult10 ;умножаем полученное число на mult10 dec di ;сдвигаем позицию индекса на один разряд влево add n, ax ;n=c0*100 +c1*101 +… mov ax, ten ;помещаем в ax 10 mul mult10 ;mult10=mult10*10 получаем 10i mov mult10,ax ;перемещаем новое значение mult10 из ax в mult10 cmp di, 0 ;проверяем, преобразованы ли все символы, кроме ;первого, который может содержать знак числа jne a ;если не первый символ, повторяем цикл cmp sir[di], '-';сравниваем первый символ с символом '-' je m1 ;если '-'‚переход на m1,иначе число положительное b: mov al, sir[di] ;преобразуем старший разряд числа sub al, 30h mov ah, 0 mul mult10 add n, ax ;копируем полученное число из ax в n jmp m2 m1: neg n ;получаем отрицательное число m2:... |
Задания
а). Вычислить значение выражения (значения переменных задаются в тексте программы):
|
b). Вычислить значение выражения (значения переменных вводятся с клавиатуры):
1 | (a+b+c)/a*d | a – define byte,b, c, d – define word |
2 | (a+b/c)*d | a, b, c – define byte, d – define word |
3 | (10*a-2*b)*c-d | a, b – define byte,c, d – define word |
4 | a/b+c*d/(c+b) | b, c, d – define byte, a – define word |
5 | 10*a/(a+b)+10*b/(c+d) | a, b, c – define byte, d – define word |
6 | 60*a+b*d+c*(a–b) | a, b – define byte, c, d – define word |
7 | (a+b)/c+d*a-c | a – define byte, b, c, d – define word |
8 | c-(a+b)/(a–c)+c*d | d – define byte, b, c, a – define word |
9 | a*b+c*d)/d | a, d – define byte, b, c – define word |
10 | (a*c+b*d)*c | a, b, d – define byte, c – define word |
11 | (a*b*c+c*d)/d | b – define byte, a, c, d – define word |
12 | (a*b–c*d)*(a+b) | a, b – define byte, c, d – define word |
13 | a*c*(a+b)-d | a, b, c – define byte, d – define word |
14 | d*b+c*a/(a+b) | c – define byte, b, a, d – define word |
15 | 25*a+13*b-d*c | c, b – define byte, a, d – define word |
16 | a*c-(a+b)/c*d | c, b, d – define byte, a – define word |
Оставить комментарий