Ассемблер
Как работает DIV в ассемблере
DIV в x86-ассемблере выполняет беззнаковое деление. У инструкции есть важная особенность: делимое берется не из одного регистра, а из пары регистров. Частное попадает в аккумулятор, а остаток — в старший регистр. Поэтому перед div нужно подготовить не только eax или rax, но и edx или rdx
Пример для 32 бит
mov eax, 100
xor edx, edx
mov ebx, 7
div ebx
Что произойдет:
EDX:EAXобразуют делимое;EBXсодержит делитель;- после
div ebxчастное будет вEAX; - остаток будет в
EDX.
Для примера 100 / 7:
EAX = 14
EDX = 2
Потому что 100 = 14 * 7 + 2
Почему нужно очищать EDX
Для 32-битного деления процессор делит не просто EAX, а пару EDX:EAX. Если в EDX остался мусор, делимое станет огромным и результат будет неправильным. Поэтому перед обычным делением положительного 32-битного числа часто пишут:
xor edx, edx
Это обнуляет старшую часть делимого
Таблица размеров
| Размер делителя | Делимое | Частное | Остаток |
|---|---|---|---|
| 8 бит | AX |
AL |
AH |
| 16 бит | DX:AX |
AX |
DX |
| 32 бит | EDX:EAX |
EAX |
EDX |
| 64 бит | RDX:RAX |
RAX |
RDX |
Эта таблица — главный ключ к div. Если смотреть только на eax, можно пропустить остаток или не понять, почему возникает ошибка деления
DIV и IDIV
DIV работает с беззнаковыми числами. Для знакового деления используют IDIV. Перед idiv старшую часть делимого готовят иначе: например, через cdq для 32-битного деления или cqo для 64-битного
Если число может быть отрицательным, div не подходит
Что вызывает ошибку
Ошибка деления может возникнуть в двух случаях:
- делитель равен нулю;
- частное не помещается в регистр назначения.
Например, если результат слишком большой для eax, процессор не «молча обрежет» его, а выдаст исключение деления
Как проверить код
Для учебного примера используйте маленькие числа:
mov eax, 25
xor edx, edx
mov ecx, 4
div ecx
Ожидаемый результат:
EAX = 6
EDX = 1
Смотрите оба регистра в отладчике. Если результат не совпадает с ожиданием, сначала проверьте значение делителя и содержимое EDX перед самой инструкцией div
Частые ошибки
Не очищают EDX
Самая частая ошибка новичка. Для div ecx делимое — EDX:EAX, а не только EAX
Делят на ноль
Перед div проверяйте делитель
Используют DIV для отрицательных чисел
Для signed-деления нужен idiv
Теряют остаток
Остаток после 32-битного деления лежит в EDX
Что почитать дальше по ассемблеру
Если нужен общий маршрут по теме, откройте рубрику ассемблеру. Для соседних задач пригодятся эти разборы:
- CMP в ассемблере: как работает сравнение
- JP в ассемблере: как работает переход
- Как работает CMP в ассемблере
- Как работает MUL в ассемблере
Как проверить результат на практике
Для ассемблера важно сначала понять, под какую среду написан пример: DOSBox/TASM, Linux x64/NASM, Visual Studio/MASM или микроконтроллер. Один и тот же смысл может записываться разным синтаксисом, поэтому не переносите команды между средами вслепую. Создайте отдельную папку для примера, сохраните файл с расширением .asm, выполните сборку именно тем инструментом, который указан в уроке, и сравните вывод или состояние регистров с ожидаемым результатом
Если пример не собирается, читайте первую ошибку ассемблера: обычно она указывает на строку, неизвестную инструкцию, неверную метку, неправильную секцию или конфликт синтаксиса. Исправляйте одну ошибку за раз. В ассемблере это особенно важно, потому что маленькая опечатка в метке, регистре или размере операнда может полностью изменить поведение программы