переполнение в делении в сборке (8086) - PullRequest
0 голосов
/ 24 декабря 2018

Я не знаю, каково точное определение переполнения в подразделении.Можете ли вы сначала объяснить это, а затем проинструктировать его приведенным ниже примером?

Например, моя книга написала, что этот фрагмент кода приводит к переполнению.Я не знаю, почему ??

mov dx,0087h
mov ax,6002h
mov bx,10h
div bx

, но этот фрагмент кода правильный и не приводит к переполнению:

mov dx,0087h
mov ax,6000h
mov bx,100h
div bx

, так почему первый результат в переполнение, а второйне в чем разница?

Ответы [ 2 ]

0 голосов
/ 24 декабря 2018

0x00876002 / 0x10 = 0x87600, поэтому частное DX:AX / BX не вписывается в AX, поэтому вы получаете исключение #DE.Справочное руководство по инструкциям Intel (x86 SDM vol. 2) содержит подробные описания каждой инструкции, и запись для div объясняет это.Здесь есть HTML-фрагмент записи div .См. вики-тег x86 для ссылок на документы Intel и другие материалы.

Деление на 10h - это сдвиг вправо на 1 шестнадцатеричное число, но верхняя половина ввода, DX,имеет 2 значащих шестнадцатеричных числа.

x86 Сборка: деление Исключение с плавающей запятой, деление на 11 в основном дублирует это, и в ответе @ rcgldr есть код для деления с повышенной точностью (например, 32-бит / 16 бит, производящий 32-битный коэффициент и 16-битный остаток) с использованием div, который работает для произвольного 16-битного делителя.


В вашем конкретном случае вы делитесь настепень 2. Это очень неэффективно с div.

Для этих делений степени 2 следует использовать

; input in DX:AX

shrd ax, dx, 4      ; right shift AX, shifting in bits from DX
shr  dx, 4          ; separately right shift DX

; DX:AX = 0008:7600 = 0x87600 = 32-bit quotient

Если вы хотите остаток, это 4 младших бита оригинального AX, которые вы должны получить с mov cl, al / and cl, 0Fh.

SHRD изменяет только пункт назначения, а не источник, поэтому вам нужночто 2 shr на DX.Это имеет смысл для больших сдвигов с расширенной точностью: вы хотите использовать цепочку команд SHRD для сдвига битов в верхнюю часть каждого элемента по очереди, и не хотите сдвигать нули.

Или если выне может использовать 386 инструкций, таких как shrd, вы можете эмулировать SHRD с левым и правым смещением и OR.В оригинальном 8086 также нет сдвигов немедленного подсчета, поэтому вам понадобится подсчет в CL.

; 8086-compatible version of 32-bit division by 10h, i.e. right shift by 4.
; input in DX:AX

mov  bx, dx
mov  cl, 16-4
shl  bx, cl       ; bx = the bits shifted across the 16-bit boundary into low half

mov  cl, 4
shr  ax, cl
shr  dx, cl       ; discards the bits shifted out

or   ax, bx       ; replace the 4 zeros at the top of AX with the bits from DX

; quotient in DX:AX

Или если вы знаете, что результат не будет переполнен, как при делении на 100h (сдвиг вправо на 8), вы можете использовать только один SHRD.

0 голосов
/ 24 декабря 2018

Дивиденд в регистрах DX и AX на самом деле является 32-битным числом, в вашем примере это 00876002h.
Он будет разделен на делитель BX, и результат (частное) долженвписывается в регистр AX.Остаток после беззнакового деления будет занесен в регистр DX.

. При попытке делить 00876002h на содержимое BX (10h) результат равен 87600h, а остаток равен2. Теперь вы должны понять, почему это вызывает ошибку: частное 87600h слишком велико, чтобы поместиться в 16-битный регистр AX.

Переполнение деления (деление псевдонима на ноль) происходит, когда делитель равенслишком маленький .Ваш пример будет переполнен, когда BX ниже DX.

...