logo
Pract / Prakt4

Ділення

Операція ділення для беззнакових даних виконується командою DIV, a для знакових - IDIV. Відповідальність за вибір відповідної команди лежить на програмісті. Існують дві основні операції ділення:

"Слово на байт".

Ділене перебуває в регістрі AX, а дільник - у байті пам'яті або а однобайтовому регістрі. Після ділення остача виходить у регістрі AH, а частка - в AL. Оскільки однобайтова частка дуже мала (максимально +255 (.FFh) для беззнакового ділення і +127 (7Fh) для знакового), то дана операція має обмежене використання.

AX  /  регістр8 = AL(частка) AH(остача)

AX  /  пам’ять8 = AL(частка) AH(остача)

"Подвійне слово на слово". Ділене перебуває в регістровій парі DX:AX, а дільник - у слові пам'яті або в регістрі. Після ділення остача виходить у регістрі DX, а частка в регістрі AX. Частка в одному слові допускає максимальне значення +32767 (FFFFh) для беззнакового ділення і +16383 (7FFFh) для знакового.

DX(старша частина)  AX(молодша частина)  /  регістр16 = DX(остача) AX(частка)

DX(старша частина)  AX(молодша частина)  /  пам’ять16 = DX(остача) AX(частка)

У єдиному операнді команд DIV і IDIV вказується дільник. Розглянемо наступну команду:

DIV DIVISOR

Якщо поле DIVISOR визначене як байт (DB), то операція припускає ділення слова на байт. Якщо поле DIVISOR визначене як слово (DW), те операція припускає ділення подвійного слова на слово. При діленні, наприклад, 13 на 3, виходить результат 4 1/3. Частка є 4, а остача - 1. Зауважимо,

Команда DIV ділить беззнакові числа і відповідно генерує без знаковий результат.

Знаковий ділення: Команда IDIV (Integer DIVide) виконує ділення знакових чисел. Таким чином, якщо ділене й дільник мають однаковий знаковий біт, то команди DIV і IDIV генерують однаковий резуультат . Але, якщо ділене й дільник мають різні знакові біти, то команда DIV генерує додатну частку, а команда IDIV – від’ємну частку.

Зауважимо, що для підвищення продуктивності, при діленні на степінь числа 2 (2, 4, і т.д.) варто використовувати зсув вправо на відповідну кількість війкових розрядів.

Переповнення й переривання

Використовуючи команди DIV і особливо IDIV, дуже легко викликати переповнення Переривання до непередбачених результатів. В операціях ділення передбачається, що дільник значно менший, ніж ділене. Ділення на нуль завжди викликає переривання. Але ділення на 1 генерує частку, що дорівнює діленому, що може також легко викликати переривання. Рекомендується використати наступне правило: якщо дільник - байт, то його значення повинне бути більше, ніж лівий байт (AH) діленого; якщо дільник - слово, то його значення повинне бути більше, ніж ліве слово (DX) діленого.

Проілюструємо дане правило для дільника, рівного 1:

Операція ділення: Ділене Дільник Частка

Слово на байт: 0123 01 (1)23

Подвійне слово на слово: 4026 0001 0001 (1)4026

В обох випадках частка перевищує можливий розмір. Для того щоб уникнути подібних ситуацій, корисно вставляти перед командами DIV і IDIV відповідну перевірку (CMP). Для команди IDIV дана логіка повинна враховувати той факт, що або ділене, або дільник можуть бути від’ємними, а порівнюються абсолютні значення, тому необхідно використати команду NEG для тимчасового перетворення від’ємного значення в додатне

Ділення відніманням

Якщо частка занадто велика, то ділення можна виконати з допомогою циклічного віднімання. Метод полягає в тому, що дільник віднімається з діленого й у цьому ж циклі частка збільшується на 1. Віднімання триває, поки ділене залишається більше ніж дільник. При такому методі, дуже велика частка й малий дільник можуть викликати тисячі циклів.

SUB CX,CX ;Очищення частки

C20: CMP AX,BX ;Якщо ділене < дільника,

JB C30 ; то вийти

SUB AX,BX ;Віднімання дільника від діленого

INC CX ;Інкремент частки

JMP C20 ;Повторити цикл

С30: RET ;Частка в CX, остача в AX

Наприкінці підпрограми регістр CX буде містити частку, а AX – остачу від ділення.

Якщо частка отримується в регістровій парі DX:AX, те необхідно зробити два доповнення:

1. У мітці C20 порівнювати AX і BX тільки при нульовому DX.

2. Після команди SUB вставити команду SBB DX,00.