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:...

Задания

а). Вычислить значение выражения (значения переменных задаются в тексте программы):

  1. (170-16)/2+12*5
  2. 45+((23-2)*2)/7
  3. 80+(45-5)*3+45/9
  4. 34*2-(15+9)/3
  5. (21+7)/14-4*5
  6. (81-60)/7+3*7
  7. (17+16)/3+12*5
  8. (7+(23-2)*2)/7
  9. 8+(14-5)*3+45/5
  10. 24*3-(45+18)/3
  11. (41-20)/3-4+3*5
  12. (46+10)/2-10*5
  13. (87-16+7)/3-16*5
  14. (83-20)/3+4-3*5
  15. 30+(45-5+2)/3+2*3
  16. 90-(41-5)*3/6

 

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

 

рассказать друзьям и получить подарок

Оставить комментарий

Ваш email не будет опубликован. Обязательные поля отмечены *

Вы можете использовать это HTMLтеги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Translate Переводчик

Подписка на новости

SmartResponder.ru
Ваш e-mail: *
Ваше имя: *

Хостинг для Wordpress сайтов