Ответ 1
Этот вопрос является вариацией на другие неудачи, связанные с делением. В x86
теге wiki есть дополнительные ссылки:
idiv
/div
проблемы: Нульedx
сначала, или sign-extendeax
в него.. 32bitdiv
, если коэффициент 64b/32b = > 32b фактически не соответствует 32b.
По-видимому, случайный код, к которому, по-видимому, переключается ваш отладчик, - это обработчик арифметических исключений (также тот же, что и Divide by Zero). Случается, что ваш код испытывает Division Overflow
. Вы делаете 16-битный/8-битный IDIV. Из документации:
Подписанное разделение AX на r/m8, с результатом, хранящимся в: AL ← Quotient, AH ← Remainder.
Вы заметите, что для деления с 8-битным делителем (в вашем случае BL) диапазон для частного составляет от -128 до +127. 044c0h IDIV 85 - 207 (десятичный). 207 не вписывается в подписанный 8-разрядный регистр, поэтому вы получаете переполнение деления и причину своей неожиданной проблемы.
Чтобы решить эту проблему, вы можете перейти к 16-разрядному делителю. Таким образом, вы можете поместить свой делитель в BX (16-разрядный регистр). Это будет mov bx, 85
. К сожалению, это не так просто. При использовании 16-разрядного делителя процессор предполагает, что дивиденд составляет 32 бита с высокими 16-бит в DX и младшими 16-разрядными в AX.
Подписанное разделение DX: AX на r/m16, с результатом, хранящимся в AX ← Quotient, DX ← Remainder.
Чтобы решить эту проблему, вы должны подписать расширение 16-битного значения в AX. Это просто, поскольку вам нужно использовать команду CWD после размещения значения в AX. Из ссылки на набор инструкций
DX: AX ← sign-extend от AX.
Эффективно, если самый значительный бит (MSB) AX равен 0 DX, станет 0. Если MSB равен 1, то DX станет 0ffffh (все биты установлены на единицу). Битом знака числа является MSB.
Учитывая это, ваш код разделения можно настроить так, чтобы он принял 16-разрядный делитель:
mov ax, 044c0h
cwd ; Sign extend AX into DX (DX:AX = 32-bit dividend)
mov bx, 85 ; Divisor is 85
idiv bx ; Signed divide of DX:AX by BX