1 of 31

Целочислена аритметика�Аритметични операции с цели двоични числа

ФМИ Компютърни архитектури – практикум

Лекция 7

Изготвила:

Десислава Тодорова

2 of 31

Съдържание

  • Какво е двоично число?
  • Операции с двоични числа
    • Събиране на двоични числа без знак
    • Събиране на двоични числа със знак
    • Изваждане на двоични числа без знак
    • Изваждане на двоични числа със знак
    • Умножение на числа без знак
    • Умножение на числа със знак
    • Деление на числа без знак
    • Деление на числа със знак
    • Спомогателни команди за целочислени операции

3 of 31

Какво е двоично число?

  • Цяло двоично число с фиксирана запетая — е число, закодирано в двоична бройна система.
  • Размерността на цялото двоично число може да бъде :
      • 8 бита;
      • 16 бита;
      • 32 бита.
  • Знакът на двоичното число се определя от това, как се интерпретира старшия бит в представянето на числото. Това са 7-ия, 15-ия или 31-ия бит за числата със съответната размерност.
  • Факт е, че сред аритметичните команди има само две, отчитащи старшия разряд като знаков — това са командите за целочислено умножение и деление (imul и idiv). В осталите случаи отговорността за действията със знакови числа и със знаковия разряд е на програмиста.

4 of 31

Какво е двоично число?

  • Диапазонът от стойности на двоичното число зависи от размера му и от това как се интерпретира старшия бит - като старши значещ бит на числото или като знаков бит на числото .

Размерност на данните

Цяло без знак

Цяло със знак

байт

0...255

–128...+127

дума

0...65 535

–32 768...+32 767

двойна дума

0...4 294 967 295

–2 147 483 648...+2 147 483 647

5 of 31

Операции с двоични числа

  • Всички аритметични операции с двоични числа, като събиране, изваждане, умножение и деление се извършват така както се извършват с десетични числа.

6 of 31

Събиране на двоични числа без знак

  • Микропроцесорът реализира събирането на операндите според правилата на събиране на двоични числа. Проблеми няма докато стойността на резултата не превишава размерността на полето на операнда .

  • Например при събиране на операнди с размер един байт резултатът не бива да превишава числото 255. Иначе резултатът е неверен.

7 of 31

Събиране на двоични числа със знак

    • На практика микропроцесорът не подозира за разликите между числа със знак и без знак. Вместо това той има средства за фиксиране възникването на характерни ситуации в процеса на изчисленията.

    • Друго средство е регистрацията на състоянието на старшия (знаков) разряд на операнда, което става с флага за препълване OF.

    • Как се представят числата в компютъра: положителните — в двоичен код, отрицателните — в допълнителен код.

8 of 31

Събиране на двоични числа�(Команди)

  • В системата от команди на микропроцесора има три команди за двоично събиране:

    • INC операнд — инкремент, стойността на операнда + 1;
    • ADD операнд_1, операнд_2 — операнд_1 = операнд_1 + операнд_2
    • ADC операнд_1, операнд_2 — операнд_1 = операнд_1 + операнд_2 + CF

9 of 31

Изваждане на двоични числа без знак и със знак

  • Без знак:

Ако умаляемото е по-голямо от умалителя — разликата е положително число, резултатът е верен. Ако умаляемото е по-малко от умалителя, възниква проблем: резултатът е отрицателен, а това е вече число със знак. Микропроцесорът заема единица от разряда, следващ след старшия, в разрядната решетка на операнда.

  • Със знак:

Основавайки се на Пример 6 може да твърдим , че микропроцесорът няма нужда от две устройства: за събиране и изваждане, достатъчно е само едно.

10 of 31

Изваждане на двоични числа (Команди)

  • Командите за изваждане са следните:

    • DEC операнд — декремент, стойността на операнда минус 1;
    • SUB операнд_1,операнд_2 — операнд_1 = операнд_1 – операнд_2
    • SBB операнд_1,операнд_2 — операнд_1 = операнд_1 – операнд_2 – CF

11 of 31

Умножение на числа без знак (1)

  • За умножение на числа без знак е предназначена командата:

mul множител_1

  • Вторият операнд — множител_2 се задава неявно. Неговото местоположение е фиксирано и зависи от размера на множителите.
  • Понеже в общия случай резултатът от умножението е по-голям, от колкото всеки от множителите, неговият размер и местоположение следва също да бъдат определени еднозначно. Разположение на операндите и на резултата при умножение са описани в таблицата.

множител_1

множител_2

Резултат

Байт

al

16 бита в ax: �al — младшата част на резултата; �ah — старшата част на резултата

Дума

ax

32 бита в dx:ax: �ax — младшата част на резултата; �dx — старшата част на резултата

Двойна дума

eax

64 бита в edx:eax: �eax — младшата част на резултата; �edx — старшата част на резултата

12 of 31

Умножение на числа без знак (2)

  • Как динамично (по време на изпълнение на програмата) може да се проследи дали резултатът е достатъчно малък и е в един регистър или е превишил размерността на регистъра и старшата му част е в друг регистър? За тази цел се анализират пак флаговете за пренос CF и за препълване OF:

      • Ако старшата част на резултата е равна на нула, тогава след операцията произведение CF=0 и OF = 0;

      • Ако тези флагове са ненулеви, което означава, че резултатът е излязъл от рамките на младшата част на произведението и се състои от две части.

13 of 31

Умножение на числа със знак

  • За умножение на числа със знак е предназначена командата:

imul операнд_1

  • Тя е аналогична на mul. Отличителна особеност е само формирането на знака.

  • Ако резултатът се събира в един регистър (CF = OF = 0), тогава съдържимото на другия регистър (старшата част) представлява разширение на знака — всичките му битове са равни на старшия бит (знаковия разряд) на младшата част на резултата.

  • В противен случай (CF = OF = 1) знакът на резултата е знаковият бит на старшата част на резултата, а знаковият бит на младшата

част е значещ бит на двоичния код на резултата.

14 of 31

Деление на числа без знак (1)

  • За деление на числа без знак е предназначена командата:

div делител

  • Делителят може да се намира в паметта или в регистър и да има размер 8, 16 или 32 бита. Местоположението на делимото е фиксирано и зависи от размера на операндите. Резултат на командата деление са стойностите на частното и остатъка. Разположение на операндите и на резултата при деление са описани в таблицата

15 of 31

Деление на числа без знак (2)

  • Разположение на операндите и на резултата при деление са описани в таблицата

Делимо

Делител

Частно

Остатък

16 бита �в регистър ax

Байт �регистър или клетка от паметта

Байт  �в регистър al

Байт  �в регистър ah

32 бита �dx — старшата част �ax — младшата част 

Дума 16 бита �регистър или клетка от паметта

Дума 16 бита в  �регистър ax

Дума 16 бита в �регистър dx

64 бита �edx — старшата част �eax — младшата част

Двойна дума 32 бита �регистър или клетка от паметта

Двойна дума �32 бита в  �регистър eax

Двойна дума �32 бита в �регистър edx

16 of 31

Деление на числа без знак (3)

  • След изпълнението на командата деление съдържимото на флаговете не е определено. Прекъсване 0 или “деление на нула” възниква поради една от следните причини:
    • Делителят е равен на нула;
    • Частното не се събира в зададената му разрядна решетка, което се случва:
      • при делене за делимо с големина дума на делител с големина байт, при което стойността на делимото е по-голяма 256 пъти от стойността на делителя;
      • при деление за делимо с големина двойна дума на делител с големина дума, при което стойността на делимото е по-голяма 65 536 пъти от стойността на делителя;
      • при деление за делимо с големина четворна дума на делител с големина двойна дума, при което

стойността на делимото е по-голяма 4 294 967 296

пъти от стойността на делителя.

17 of 31

Деление на числа със знак (1)

  • За деление на числа със знак е предназначена командата:

idiv делител

  • Аналогията с div е пълна. “Деление на нула” за числа със знак възниква при изпълнение на командата idiv поради следните причини:

    • делителят е равен на нула;
    • частното не влиза в заделената му разрядна решетка.

18 of 31

Деление на числа със знак (2)

    • Частното да не влиза в заделената му разрядна решетка е възможно в следните случаи:
      • при деление за делимо с големина дума със знак на делител с големина байт със знак, при което стойността на делимото е по-голяма 128 пъти от стойността на делителя (частното трябва да е в диапазона от –128 до +127);
      • при деление за делимо с големина двойна дума със знак на делител с големина дума със знак, при което стойността на делимото е по-голяма 32 768 пъти от стойността на делителя (частното трябва да е в диапазона от –32 768 до +32 768);
      • при деление за делимо с големина четворна дума със знак на делител с големина двойна дума със знак, при което стойността на делимото е по-голяма 2 147 483 648 пъти от стойността на делителя (частното трябва да е в

диапазона от –2 147 483 648 до +2 147 483 647).

19 of 31

Спомогателни команди за целочислени операции (1)

    • Команди за преобразуване на типовете
      • Команди без операнди — те работят с фиксирани регистри:
        • cbw (Convert Byte to Word) — командата преобразува байт (в регистър al) в дума (в регистър ax) като разпространява стойността на старшия бит на al на всички битове на регистър ah;
        • cwd (Convert Word to Double) — командата преобразува дума (в регистър ax) в двойна дума (в регистрите dx:ax) като разпространява стойността на старшия бит на ax на всички битове на регистър dx;
        • cwde (Convert Word to Double) — командата преобразува дума (в регистър ax) в двойна дума (в регистър eax) като разпространява стойността на старшия бит на ax на всички битове на старшата половина на регистър eax;
        • cdq (Convert Double Word to Quarter Word) — командата преобразува двойна дума (в регистър eax) в четворна дума

(в регистрите edx:eax) като разпространява стойността

на старшия бит на eax на всички битове на регистър edx.

20 of 31

Спомогателни команди за целочислени операции (2)

    • Команди за преобразуване на типовете
      • Командите movsx и movzx са за обработка на низ от знаци:
        • movsx операнд_1,операнд_2 — прехвърля с разпространение на знака. Разширява 8 или 16-разрядната стойност на операнд_2, която може да бъде регистър или операнд в паметта, до 16 или 32-разрядна стойност в един от регистрите, използвайки стойността на знаковия бит за запълване на старшите позиции на операнд_1. Дадената команда е удобна за използване за подготовка на операндите със знак за изпълнение на аритметични действия;

        • movzx операнд_1,операнд_2 — да се прехвърли с разширение на нулата. Разширява 8 или 16-разрядна стойност на операнд_2 до 16 или 32-разряда със запълване с нули на старшите позиции на операнд_2. Дадената команда е удобна за използване за подготовка на операндите без знак за изпълнение на

аритметични действия.

21 of 31

Спомогателни команди за целочислени операции (3)

    • Други полезни команди
      • xadd цел, източник — обмен на местата и събиране. Командата изпълнява последователно две действия:
          • обменя стойностите на двата операнда;
          • помества на мястото на операнда цел сумата: цел = цел + източник.
      • neg операнд — отрицание; изчислява двоичното допълнение на операнда. Командата променя знака на операнда. Физически изпълнява едно действие: операнд = 0 – операнд, т.е. изваждане на операнда от нулата. Командата neg операнд може да се прилага в случаите:
          • за смяна на знака;
          • за изпълнение на изваждане от константа.
      • Командите sub и sbb не позволяват да се извади число от константа, понеже константата не може да бъде операнд-приемник в тези операции. Затова дадената операция може да се реализира с

помощта на две команди:

          • neg ax ; смяна на знака (ax)
          • add ax,340 ; изваждането: (ax)=340-(ax)

22 of 31

?

Може да задавате Вашите

въпроси в

Общия форум на курса.

Благодаря за вниманието!

23 of 31

Събиране на двоични числа без знак- Пример 0

254 = 11111110

+

005 = 0000101

=

259 = 1 00000011.

      • Резултатът е преминал границата на осемте бита и верният резултат заема 9 бита, а в 8-битовото поле на операнда е останала стойността 3, което е неверен резултат.
      • В микропроцесора този изход при събирането се прогнозира и са предвидени специални средства за тяхната обработка. В дадения случай се предглежда флага за перенос CF, който фиксира факта за пренос на единица от старшия разряд на операнда. Един лесен вариант е използването на командата за условен переход JC.

24 of 31

Събиране на двоични числа със знак- Пример 1

30566 = 01110111 01100110

+

00687 = 00000010 10101111

=

31253 = 01111010 00010101

      • Следим за наличие на пренос от 14-ия и 15-ия разряд и дали е правилен резултата: перенос няма, резултатът е правилен.

НАПРЕД

25 of 31

Събиране на двоични числа със знак- Пример 2

30566 = 01110111 01100110

+

30566 = 01110111 01100110

=

61132 = 11101110 11001100

      • Наличие на пренос от 14-тия разряд; от 15-ти разряд няма пренос. Резултатът е неправилен, понеже има препълване — полученото число е по-голямо от +32 767 или това, което може да има 16-битово число със знак.

НАПРЕД

26 of 31

Събиране на двоични числа със знак- Пример 3

- 30566 = 10001000 10011010

+

- 04875 = 11101100 11110101

=

- 35441 = 01110101 10001111

      • Наличие на пренос от 15-тия разряд, от 14-тия разряд няма пренос. Резултатът не е правилен, вместо отрицателно число е получено положително (в старшия бит има 0).

НАПРЕД

27 of 31

Събиране на двоични числа със знак- Пример 4

- 4875 = 11101100 11110101

+

- 4875 = 11101100 11110101

=

- 9750 = 11011001 11101010

    • Има пренос от 14 и 15-тия разряд. Резултатът е правилен. Изяснихме, че препълване (OF= 1) има при пренос:

• от 14-тия разряд (за положителни числа със знак);

• от 15-тия разряд (за отрицателни числа).

    • И обратно, препълване няма (OF = 0), ако има пренос едновременно от двата разряда или пренос няма и в двата разряда.

28 of 31

Изваждане на двоични числа - Пример 5

05 = 00000000 00000101

-10 = 00000000 00001010

    • За да извадим вземаме въображаем заем от старшия разряд:

100000000 00000101

-

00000000 00001010

=

11111111 11111011

    • По този начин изпълняваме действието:

(65 536 + 5) — 10 = 65 531, 0 тук е еквивалент на числото 65 536. Резултатът е неверен, но микропроцесорът счита, че проблеми няма и факта на заем на единица той фиксира с установяване на флага за пренос CF. Получихме резултат –5 в допълнителен код.

НАПРЕД

29 of 31

Изваждане на двоични числа - Пример 6

5 = 00000000 00000101

+

(-10)= 11111111 11110110

=

11111111 11111011

      • Примерът е подобен на пример 5 , с разликата че в случая събираме положително с отрицателно число, което всъщност е изваждане.

30 of 31

Изваждане на двоични числа - Пример 7

45 = 0010 1101

-

-127 = 1000 0001

=

-44 = 1010 1100

      • Получи се отрицателен резултат, равен на –44. Правилният е 172. Тук имаме препълване и значещият разряд е променил знаковия на операнда. Проследяване на подобна ситуация може да се реализира с анализ на флага за препълване OF.

НАПРЕД

31 of 31

Изваждане на двоични числа - Пример 8

-45 — 45 = -45 + (-45)= -90.

-45 = 1101 0011

+

-45 = 1101 0011

=

-90 = 1010 0110

      • Тук OF = 0, а 1 в знаковия разряд говори, че резултатът е число в допълнителен код.