Деление в ассемблере основы и примеры

0
8

Деление в ассемблере

Для обработки целочисленных значений в низкоуровневом коде применяются команды DIV и IDIV. Первая работает с беззнаковыми числами, вторая – со знаковыми. Операнд-делитель указывается явно, а делимое всегда берется из пары регистров: AX (16-бит), DX:AX (32-бит) или EDX:EAX (64-бит).

Перед выполнением операции необходимо обнулить DX (для беззнакового варианта) или расширить знак через CWD/CDQ. Игнорирование этого шага приведет к некорректному результату. Например, перед делением AX на BL требуется выполнить XOR DX, DX для 16-битного формата.

Результат сохраняется в AX (частное) и DX (остаток). Для 32-битных чисел используются EAX и EDX. Ошибка #DE (Divide Error) возникает при переполнении или делении на ноль – обработчик исключений должен быть настроен заранее.

Работа с операциями дробления в низкоуровневом коде

Команды для целочисленного вычисления

В x86 применяются инструкции DIV и IDIV. Первая работает с беззнаковыми значениями, вторая – со знаковыми. Операнд указывает делитель, а делимое всегда берётся из пары регистров:

  • Для 8-битных операций: AX / операнд → результат в AL, остаток в AH.
  • Для 16-битных: DX:AX / операнд → AX (частное), DX (остаток).
  • Для 32-битных: EDX:EAX / операнд → EAX, остаток в EDX.

Пример для 16-битного беззнакового случая:

mov ax, 1000  ; Делимое (младшая часть)
mov dx, 0     ; Старшая часть
mov bx, 30    ; Делитель
div bx        ; AX = 33, DX = 10

Особенности обработки ошибок

При переполнении или попытке дробления на ноль процессор генерирует исключение #DE. Для избежания сбоев проверяйте делитель перед выполнением операции:

test bx, bx
jz division_error  ; Переход, если BX = 0

Для знаковых значений используйте CWD, CDQ или CQO (в зависимости от разрядности), чтобы расширить знак делимого в DX/EDX/RDX перед IDIV.

Работа с целыми числами в x86

Для обработки целых значений используйте команды DIV и IDIV. Первая работает с беззнаковыми числами, вторая – со знаковыми. Операнд указывает делитель, а делимое всегда берётся из пары регистров:

  • 8-битное: AX (результат – AL, остаток – AH)
  • 16-битное: DX:AX (результат – AX, остаток – DX)
  • 32-битное: EDX:EAX (результат – EAX, остаток – EDX)

Особенности обработки ошибок

При нулевом делителе или переполнении возникает исключение #DE. Перед операцией обнулите EDX для беззнаковых значений или используйте CDQ для знаковых.

Код для 32-битного беззнакового случая:

mov eax, 200    ; Делимое
mov ebx, 5      ; Делитель
xor edx, edx    ; Очистка EDX
div ebx         ; EAX = 40, EDX = 0

Для отрицательных чисел:

mov eax, -200
mov ebx, 3
cdq             ; Расширение EAX в EDX:EAX
idiv ebx        ; EAX = -66, EDX = -2

Контроль ошибок и переполнения при работе с операциями

Проверяйте флаг переполнения (OF) после выполнения команды IDIV или DIV. Если он установлен, результат не поместился в регистр назначения.

Типичные сценарии сбоев

  • Деление на ноль – вызывает прерывание #DE (Divide Error).
  • Результат выходит за границы диапазона для AX/DX:AX/EDX:EAX.
  • Остаток превышает размер делителя (например, при DX >= divisor для 16-битных значений).

Практические методы проверки

  1. Перед операцией:
    • Сравните делитель с нулём: CMP divisor, 0 + условный переход.
    • Для знаковых значений: убедитесь, что DX:AX содержит корректное число (например, TEST DX, DX перед IDIV CX).
  2. После операции:
    • Анализируйте флаги процессора: JO label_overflow.
    • Проверяйте остаток (DX/RDX/EDX) на соответствие ожидаемому диапазону.

Пример обработки прерывания #DE:

mov ax, -32768
mov bl, -1
idiv bl ; Вызовет переполнение (результат 32768 > 127)
jo handle_overflow

Как выполнить операцию деления с помощью DIV и IDIV

Для беззнакового вычисления применяйте DIV, для знакового – IDIV. Операнд указывается явно, но делимое всегда берется из пары AX, DX:AX или EDX:EAX в зависимости от размера:

  • 8-битное: делимое в AX, результат – AL (частное), AH (остаток).
  • 16-битное: делимое в DX:AX, результат – AX (частное), DX (остаток).
  • 32-битное: делимое в EDX:EAX, результат – EAX (частное), EDX (остаток).

Перед выполнением IDIV расширьте знак в DX или EDX через CWD, CDQ. Например:

mov ax, -100  ; Делимое
cwd           ; Расширение знака в DX
mov bx, 3     ; Делитель
idiv bx       ; AX = -33, DX = -1

Ошибка (#DE) возникает при переполнении или делении на 0. Проверяйте делитель перед операцией.