Главная

Популярная публикация

Научная публикация

Случайная публикация

Обратная связь

ТОР 5 статей:

Методические подходы к анализу финансового состояния предприятия

Проблема периодизации русской литературы ХХ века. Краткая характеристика второй половины ХХ века

Ценовые и неценовые факторы

Характеристика шлифовальных кругов и ее маркировка

Служебные части речи. Предлог. Союз. Частицы

КАТЕГОРИИ:






Над двоично-десятичными числами




Определение и формат BCD-чисел были рассмотрены в начале этого урока. У вас справедливо может возникнуть вопрос: а зачем нужны BCD-числа? Ответ может быть следующим: BCD-числа нужны в деловых приложениях, то есть там, где числа должны быть большими и точными. Как мы уже убедились на примере двоичных чисел, операции с такими числами довольно проблематичны для язы­ка ассемблера. К недостаткам использования двоичных чисел можно отнести сле­дующие:

- О значения величин в формате слова и двойного слова имеют ограниченный диапазон. Если программа предназначена для работы в области финансов, то ограничение суммы в рублях величиной 65 536 (для слова) или даже 4 294 9G7 296 (для двойного слова) будет существенно сужать сферу ее при­менения (да еще в наших экономических условиях — тут уж никакая деноми­нация не поможет);

- О наличие ошибок округления, Представляете себе программу, работающую где-нибудь в банке, которая не учитывает величину остатка при действиях с целыми двоичными числами и оперирует при этом миллиардами. Не хоте­лось бы быть автором такой программы. Применение чисел с плавающей точкой не спасет — там существует та же проблема округления;

- О представление большого объема результатов в символьном виде (ASCII-коде). Деловые программы не просто выполняют вычисления; одной из целей их использования является оперативная выдача информации пользователю. Для этого, естественно, информация должна быть представлена в символь­ном виде. Перевод чисел из двоичного кода is ASCII-код, как мы уже видели, требует определенных вычислительных затрат. Число с плавающей точкой • еще труднее перевести в символьный вид, А вот если посмотреть на шШестнад-, цатеричное представление неупакованной десятичной цифры (в начале наше­го урока) и на соответствующий ей символ в таблице ASCII, то видно, что они ' • отличаются на величину 30hЗОН. Таким образом, преобразование в символьный

- вид и обратно получается намного проще и быстрее.

Наверняка вы уа<;е убедились в важности овладения хотя бы основами действий с десятичными числами. Далее рассмотрим особенности выполнения основных арифметических операций с десятичными числами. Для предупреждения возмож­ных вопросов отметим сразу тот факт, что Отдельных команд сложения, вычита-__________________________-1П|

ния, умножения и деления BCD-чисел нет. Сделано это по вполне понятньцц причинам: размерность таких чисел может быть сколь угодно большой. Склады-ивать и вычитать можно двоично-десятичгшные числа как в упакованном формате так и в неупакованном, а вот делить и умножать можно только неупакованные BCD-числа., Почему это так, будет видно из дальнейшего обсуждения.

 

1. Неупакованные BCD-числа |

- т

1.1. Сложение ^v*!.:;;*'>•;V>:'-•;-••!' ^.r^V;.,,.

Рассмотрим два случая сложения. \^ • f;,;,•, '• -ч^-'-- чЧ ->•;(••..?.,;-,";• ^,; •.••

' !i r!»i-.,i * !i;S •, '', i •('",: ',•-"• г\ ';;.•* /'••.'.;

Пример 8.9. Результат сложения не больше 9.

6 = 0000 0110ооооопо -,-...',,:•,•,..,.,•<.!..•''.'"';'.-,.',-'.-.-: ••-.:•,-:- '-/.и.' ' 1

 

+ •,••,,,-. -••• -.. '.'С'.'-;,'';.';,'...;:;........;

3=- 0000 ООН0011;.;,,,.-,...:. -.•,.... •...,,.....

=

9-=0000 1001

100! • "' '; ',',-. ' :..',,;'.'",',-•.- •;'„:;•..; '>;.;.!'•'... Переноса из младшей тетрады в старшую нет. Результат правильный.

Пример 8.10. Результат сложения больше 9 ' ;. '. ' '"''•' ' ' '.

6 = 0000 0110

+

06 = 0000 ОНО. •...л: '. •-•>;„. ••-,.:•-';>.• 'Ч/' • ' •.•'•/''•••. • -

07 = 0000 0111;,,;; •.•.-*•.*....;;..•...V:-^-:-,'''•.-...•• '„ „г,.-..,: '-,.,•#•„•. '•

=

13=0000 1101

кз-оооо hoi;;: V. '' '•''"' ' "" : •' ' ^

То есть мы получили уже не BCD-число. Результат неправильный. Правильный :>|
результат в неупакованном BCD-формате должен быть таким: 0000 0001 0000 1
ООН0011 в двоичном представлении (или 13 в десятичном). Проанализировав данную fi
проблему при сложении BCD-чисел (и подобные проблемы при выполнении дру- j
гих арифметических действий) и возможные пути ее решения, разработчики си- j
стемы команд микропроцессора решили не вводить специальные команды для?
работы с BCD-числами, а свести несколько корректировочных команд. Назпаче-,'.
пие этих команд — в корректировке рез}>лътата работы обычных арифметических;
команд д.тя случаев, когда операнды в них являются BCD-числами. В случае сло­
жения в примере 8.10 видно, что Полученный результат нужно корректировать..;
Для коррекции операции сложения довух однозначных неупакованных BCD-чи­
сел в системе команд микропроцессора существует специальная команда 1

ааа (ASCII Adjust for Addition) — коррекция результата сложения для Щ
представления в символьном виде. Ш

Эта команда не имеет операндов. Она работает неявно только с регистром al и Щ

анализирует значение его младшей тетрады. Если это значение меньше 9, то флаг |

cf сбрасывается в 0, и осуществляется переход к следующей команде. Если это |

значение больше 9, то выполняются следующие действия: 1

- г\ к содержимому младшей тетрады al (но не к содержимому всего регистра!) прибавляется 6, тем самым значение десятичного результата корректируется в правильную сторону;

- О флаг cf устанавливается в 1, тем самым фиксируется перенос в старший раз­ряд для того, чтобы его можно было учесть в последующих действиях.

Так, в примере 8.10, предполагая, что значение суммы 0000 1101 находится в al, после команды ааа в регистре будет 1101 + 0110= 0011, то есть двоичное 0000 ООН0011 или десятичное 3, а флаг cf установится в 1, то есть перенос запомнился в мик­ропроцессоре. Далее программисту нужно будет использовать команду сложения adc, которая учтет перенос из предыдущего разряда. Приведем пример програм­мы сложения двух неупакованных BCD-чисел.

Листинг 8.8. Сложение неупакованных BCD-чисел

<l>;prg_8_8.asm

<2>... •• '-' •'"•'•'" •"•'!:-!'"'"'

<3>.data

<4> Tlen equ 2;разрядность числа, •.;/

<5> b db 1,7;неупакованное число 71 '••-"••.'.;•••••, •-.-.-.•£•

<6> с db 4,5;неупакованное число 54.. • ~

<7> sum db 3 dup (0) •,

<8>.code.,

<9> mmain:;точка входа в программу

<10>...,,_.- -(' '

<11> хогr bx,.bx.. t" '.

<12> mov cx,.len ' '' • ' ''','' ''' '•'- ''' '. '

<п> mi1: ' •'" ""• ••' • • ••::" :; "••;'.'•,'•• '

<14> mov al,b[bx] • • :' •'- ' -'•'*•' • -' ' •.--."'

<15> adc a1.,c[bx] " •• ; '' •': •'/ ''- • / •'• ^ ''-' l^-' ' '--''

<16> aaa. '• • •' •.' '•••' ""• " •••' '••••• • "••', "

<17> mov sum[bx],al •.: - •• •'•i!. • •••.•• • -. - •''" '•

<18> inc bx..'.-.... '.' •:• •• •>••<•;:•.-...

<19> loop ml

<20> adc sum[bx].,0 • • • '.•..•• <;1, :-

<21>... '..-.-..;.',:'.•-
exit:... •

В листинге 8.8 есть несколько интересных моментов, над которыми есть смысл поразмыслить. Начнем с описания BCD-чисел. Из строк 5 и 6 видно, что Поря­док их ввода BCD-чисел обратен нормальному, то есть цифры младших разрядов расположе­ны по меньшему адресу. Но это вполне логично по нескольким причинам: во-пер-вых, такой порядок удовлетворяет общему принципу представления данных для микропроцессоров Intel, во-вторых, это очень удобно для поразрядной обработ­ки неупакованных BCD-чисел, так как каждое из них занимает один байт. Хотя, повторюсь, программист сам волен выбирать способ описания BCD-чисел в сег­менте данных. Строки 14-15 содержат команды, которые складывают цифры в очередных разрядах BCD-чисел, при этом учитывается возможный перенос из младшего разряда. Команда ааа в строке 16 корректирует результат сложения, формируя в al BCD-цифру и, при необходимости, устанавливая в 1 флаг cf. Стро-_________________________________^——;-^г1Ды

ка 20 учитывает возможность переноса при сложении цифр из самых старшихщцх
разрядов чисел. Результат сложения формируется в поле sum.

, описанном в стро­
ке 7...";• i'-';;M-K-;|'

 

Вычитание Ш

па s Ситуация здесь вполне аналогична сложению. Рассмотрим те'же'случаи. ™Ц

' • •.:.. v.,•

Пример 8.11. Результат вычитания не больше 9е 9 •, • •,;}>;• j

6 = 0000 0110 ••• •. ; -.• :.$

–-'••• • "••',-•. ^

 

3 = 0000 0011 - ! ' ' : •"'". j

3 = 0000 0011 ' ••'•••' •,

" •" '•• •'; - '•!

Как видим, Ззаема из старшей тетрады нет. Результат верный и корректировки не \
требует.;:- J

"i
Пример 8.12. Результат вычитания больше 9../....,,, ~ •,,•.*

6 = 0000 0110

– ••-."...••,• ' •?•> • Ш'\

7 -= 0000 0111 • *Ь. "Я j

 

=

-1 = 1111 1П111 1

 

Вычитание проводится по правилам двоичной арифметики. Поэтому результат не
является BCD-числом. Правильный результат в неупакованном BCD-формате
должен быть 9 (0000 1001 в двоичной системе счисления). При этом предполага­
ется заем из старшего разряда, как при обычной команде вычитания, то есть в
случае с BCD-числами фактически должно быть выполнено вычитание 16 - 7.

Таким образом, видно, что, как и в случае сложения, результат вычитания нужно
корректировать. Для этого существует специальная команда

aas (ASCII Adjust for Substraction) — коррекция результата вычитания для представления в символьном виде.

Команда aas также не имеет операндов и работает с регистром al, анализируя его младшую тетраду следующим образом: если ее значение меньше 9, то флаг cf сбрасывается в 0, и управление передается следующей команде. Если значение тетрады в al больше 9, то команда aas выполняет следующие действия:

- О из содержимого младшей тетрады регистра аl] (заметьте — не из содержимого всего регистра) вычитает 6;

- О обнуляет старшую тетраду регистра al;

- О устанавливает флаг cf в 1, тем самым фиксируя воображаемый заем из стар­шего разряда.

Понятно, что команда aas применяется вместе с основными командами вычита­ния sub и sbb. При этом команду sub есть смысл использовать только один раз при вычитании самых младших цифр операндов, далее должна применяться команда sbb

hb которая будет учитывать возможный заем из старшего разряда.

В листинге 8.9
' обходимся одной командой sbb, которая в цикле производит поразрядное
вычитание двух BCD-чисел. - -..........

Листинг 8.9. Вычитание неупакованных BCD-чисел

<\>;prg_8_9.asm ", •..:.- •'..?it

<ф, masm

.ф, model small

ф. stack 256 -Jк •-,*..^;С".

^.data;сегмент данных t..,,,.

<6> ьb db 1,7;неупакованное число 71 ',. ''

<-}> с db 4,5;неупакованное число 54 ' ••"-."•'"•

<8> subs db 2 dup (0) - " ' ;"fi-

<9>. code : '•' ' " ' ""' ;:

<10> main:;точка входа в программу Vl •-..-<• •:,'.„

<ц> rmnov ax,@.^data связываем регистр dx с сегнентйн-•'"• i! •''

<12> mov ds,.ax;данных через регистр ах

<13> хогr ах,ах..;очищаем ах.., •.

<14> len equ 2;2.' -.разрядность чисел ' ',:•;,;.,'.'

<15> хогr bx.,bx,.., |,,,,.., (

<16> mov ecx,len;загрузка в сх счетчика цикла../.'.".,

<17> ml: '' ; '; '"' : '•

<18> mov al,b[bx]. •, '•' "V

<19> sbb al.,c[bx].,... ii.jK. ',

<20> aas ' ' • ••.'"• •'' " •;41 '-'

<21> mov subs[bx],al - "-'• '• • •;..••• • s'"'1 v т; s...

<22> •.. Iinc bx..., (|,. ;,:.... '.':-

<23> ' loop ml....-- - •. •.

<:24> jc m2; анализ флага эзаенма

<25> jmp exit = - - '." • ^'-iv:.;:•(-. r~. v •

m^26> ni2:.... ".. • •-

•=27> exit:

<28> mov ax,4c00OOh;стандартный выход

^29> innt 21h.- -.I..',.W- '.

":30> end main;конец программы,; • -,,.,v •

Данная программа не требует особых пояснений, когда уменьшаемое больше вы­читаемого. Поэтому обратите внимание на строку 24. С ее помощью Мы предусмат­риваем случай, когда после вычитания старших цифр чисел был зафиксирован факт заема. Это говорит о том, что вычитаемое было больше уменьшаемого, в результа­те чего разность будет неправильной. Эту ситуацию нужно как-то обработать. С этой целью в строке 24 командой jc анализируется флаг cf. По результату этого анализа мы уходим на ветку программы, обозначенную меткой т2, где и будут вы­полняться некоторые действия. Набор этих действий сильно зависит от конкрет­ного алгоритма обработки, поэтому поясним только суть действий, которые может Выполнять соответствующий фрагмент программы. Для этого посмотрим в отлад-ике, как наша программа выполнит вычитание 50 - 74 (правильный ответ -24). о, что вы увидите в окне Dump отладчика, в поле, соответствующем адресу subs, УДет далеко от истинного ответа. Что делает в этом случае человек? Он просто ыполняет вычитание 74 - 50 = 24 и рассматривает результат как имеющий знакминус. Так как у микропроцессора нет средств обработки подобной ситуации, то фрагмент программы, обозначенный меткой т2, может поменять уменьшаемое ц вычитаемое местами, выполнить вычитание и где-то отметить тот факт, что раз-ность, на самом деле, нужно рассматривать как отрицательное число. Но ключевой момент здесь все-таки тот, что микропроцессор с помощью флага cf сигнализирует нам об этой особой ситуации.

 

Умножение I

На примере сложения и вычитания неупакованных чисел стаао понятно, что стан­дартных алгоритмов для выполнения этих действий над BCD-числами нет, и про­граммист должен сам, исходя из требований к своей программе, реализовать эти операции. Реализация двух оставшихся операций — умножения и деления — еще более сложна. В системе команд микропроцессора присутствуют только средства для производства умножения и деления одноразрядных неупакованных BCD-чи­сел.

Для того чтобы умножать числа произвольной размерности, нужно реализовать процесс умножения самостоятельно, взяв за основу некоторый алгоритм умноже­ния, например «в столбик*. Позже мы рассмотрим пример программы, выполня­ющей умножение десятичных чисел произвольной размерности.

Для того чтобы перемножить два одноразрядных BCD-числа, необходимо:

- О поместить один из сомножителей в регистр аl (как того требует команда mul);

- О поместить второй операнд в регистр или память, отведя байт;

- О перемножить сомножители командой mul (результат, как и положено, будет в ах);

- О результат, конечно, получится в двоичном коде, поэтому его нужно скоррек­тировать.

Для коррекции результата после умножения применяется специальная команда

aam (ASCII Adjust for Multiplication) — коррекция результата умножения для представления в символьном виде.

Она не имеет операндов и работает с регистром ах следующим образом:

- О делит al на 10;

- О результат деления записывается так; частное — в al, остаток — в ah.

В результате после выполнения команды aam в регистрах al и ah находятся

правильные двоично-десятичные цифры произведения двух цифр.

В листинге 8.10 приведен пример умножения BCD-числа произвольной раз­мерности на однозначное BCD-число.

Листинг 8.10. Умножений неупакованных BCD-чисел

;prg8_10.asm

masm

model small

stack 256

.data

b db 6,7;неупакованное число 76

c db 4;неупакованное число 4

proizv db 4 dup (0)

.code

main:;точка входа в программу

mov ax,@data

mov ds,ax

xor ax,ax

len equ 2;размерность сомножителя 1

xor bx,bx

xor si,si

xor di,di

mov cx,len;в cx длина наибольшего сомножителя 1

m1:

mov al,b[si]

mul c

aam;коррекция умножения

adc al,dl;учли предыдущий перенос

aaa;скорректировали результат сложения с переносом

mov dl,ah; запомнили перенос

mov proizv[bx],al

inc si

inc bx

loop m1

mov proizv[bx],dl;учли последний перенос

exit:

mov ax,4c00h

int 21h

end main

 

Данную программу можно легко модифицировать для умножения BCD-чисел произвольной длины. Для этого достаточно представить алгоритм умножения в «столбик». Листинг 8.10 можно использовать для получения частичных произве­дений в этом алгоритме. После их сложения со сдвигом получится искомый ре­зультат. Попробуйте выполнить разработку этой программы самостоятельно. Перед окончанием обсуждения Командуы aam необходимо отметить еще один ва­риант ее применения. Эту команду можно применять для преобразования двоич­ного числа в регистре al в неупакованное BCD-число, которое будет размещено в регистре ах: старшая цифра результата — в ah, младшая — в al. Понятно, что Двоичное число должно быть в диапазоне 0...99.

 

1.4. Делениее:

Процесс выполнения операции деления двух неупакованных BCD-чисел не­сколько отличается от других, рассмотренных ранее, операций с ними. Здесь также требуются действия по коррекции, но они должны выполняться до основ­ной операции, выполняющей непосредственно деление одного BCD-числа на другое BCD-число. Предварительно в регистре ах нужно получить две неупако­ванные BCD-цифры делимого. Это делает программист удобным для него способом. Далее нужно выдать команду aad:

aad (ASCII Adjust, for Division) — коррекция деления для представления в символьном виде.

 

Команда не имеет операндов и преобразует двузначное неупакованное BCD-число в регистре ах в двоичное число. Это двоичное число впоследствии будет играть роль делимого в операции деления. Кроме преобразования, команда aad помеща­ет полученное двоичное число в регистр al. Делимое, естественно, будет двоич­ным числом из диапазона 0...99. Алгоритм, по которому команда aad осуществля­ет это преобразование, состоит в следующем:

- О умножить старшую цифру исходного BCD-числа в ах (содержимое ah) на 10;

- О выполнить сложение ah + al, результат которого (двоичное число) занести в al;

- О обнулить содержимое ah.

Далее программисту нужно выдать обычную команду деления div для выполне­ния деления содержимого ах на одну BCD-цифру, находящуюся и байтовом ре­гистре или байтовой ячейке памяти.

Деление неупакованных BCD-чисел иллю­стрируется листингом 8.11.

Листинг 8.11. Деление неупакованных BCD-чисел

;prg8_11.asm

masm

model small

stack 256

.data;сегмент данных

b db 1,7;неупакованное BCD-число 71

c db 4;

ch db 2 dup (0)

.code;сегмент кода

main:;точка входа в программу

mov ax,@data

mov ds,ax

xor ax,ax

mov al,b

aad;коррекция перед делением

div c;в al BCD-частное, в ah BCD-остаток

;...

exit:

mov ax,4c00h

int 21h

end main

Аналогично ааmт, команде aad можно найти и другое применение — использовать ее для перевода неупакованных BCD-чисел из диапазона 0...99 в их двоичный эквивалент.

 

Для деления чисел большей разрядности, так же, как и в случае умножения, нужно реализовывать свой алгоритм, например в «столбик», либо найти более оптимальный путь. Любопытный и настойчивый читатель, возможно, самосто­ятельно разработает эти программы. Но это делать совсем необязательно. На дискете, прилагаемой к книге, в каталоге данного урока приведены тексты мак­рокоманд, которые выполняют четыре основных арифметических действия с BCD-числами любой разрядности.

 






Не нашли, что искали? Воспользуйтесь поиском:

vikidalka.ru - 2015-2024 год. Все права принадлежат их авторам! Нарушение авторских прав | Нарушение персональных данных