Команда DIV
Лучшие книги по Ассемблеру
Сделал подборку не новых, но проверенных книг по программированию на языке ассемблера. Если вы также как и я любите погружаться на низкий уровень, в те закоулки мира программирования, куда не всем путь открыт, то посмотрите. Возможно, что-то вам понравится. Подробнее… |
Инструкция DIV в Ассемблере выполняет деление без знака. Использование этой инструкции похоже на работу команды MUL, хотя, конечно, имеет некоторые особенности, потому что деление — это не умножение )))
Итак, синтаксис команды DIV такой:
DIV ЧИСЛО
ЧИСЛОМ может быть один из следующих:
- Область памяти (MEM)
- Регистр общего назначения (REG)
Эта команда не работает с сегментными регистрами, а также не работает непосредственно с числами. То есть вот так
DIV 200 ; неправильно
делать нельзя.
А теперь алгоритм работы команды DIV:
- Если ЧИСЛО — это БАЙТ, то AL = AX / ЧИСЛО
- Если ЧИСЛО — это СЛОВО, то AX = (DX AX) / ЧИСЛО
Если вы уже изучили инструкцию MUL, то ничего особо нового для вас здесь нет. Ну а если не изучали, то немного напомню.
Обратите внимание, что инструкция DIV работает либо с регистром АХ, либо с парой регистров DX AX. То есть перед выполнением этой команды нам надо записать в регистр АХ или пару регистров DX AX значение, которое требуется разделить. Сделать это можно, например, с помощью уже известной нам команды MOV.
Затем надо в область памяти или в регистр общего назначения записать делитель — то есть число, на которое будем делить.
Далее мы выполняем деление, и получаем результат либо в регистр АL (если ЧИСЛО — это байт), либо в регистр AX (если ЧИСЛО — это слово).
Остаток от деления
Как вы понимаете, инструкция DIV выполняет целочисленное деление. При этом остаток от деления, если таковой имеется, будет записан:
- В регистр АН, если ЧИСЛО — это байт
- В регистр DX, если ЧИСЛО — это слово
Никакие флаги при этом не изменяются. А если и меняются, то об этом ничего не сказано в документации, следовательно, проверять флаги нет необходимости.
Просто если есть сомнения, что деление выполнено без остатка, надо проверить содержимое регистров AL или DX в зависимости от того, какой размер имеет ЧИСЛО.
Пример деления в Ассемблере
Итак, например, нам надо 250 разделить на 150. Тогда мы делаем так:
MOV AX, 250 ; Делимое в регистр AX MOV BL, 150 ; Делитель в регистр BL DIV BL ; Теперь АL = 250 / 150 = 1, AH = 100
Обратите внимание, что нам приходится два раза использовать команду MOV, так как команда DIV не работает непосредственно с числами, а только с регистрами общего назначения или с памятью.
После выполнения этого кода в регистре АL будет результат целочисленного деления числа 250 на число 150, то есть число 1, а в регистре АН будет остаток от деления — число 100 (64 в шестнадцатеричной системе).
Теперь попробуем число 50000000 разделить на 60000.
MOV DX, 762 ; Делимое - в пару регистров DX AX MOV AX, 61568 ; (DX AX) = 50000000 MOV BX, 60000 ; Делитель в регистр BX DIV BX ; Теперь АХ = 50000000 / 60000 = 833 (341h) ; DX = 20000 (4E20h)
Для записи делителя в пару регистров DX и AX используются две команды MOV. В нашем примере в регистр DX будет записано число 762 (02FA — в шестнадцатеричной системе), а в регистр АХ — число 61568 (F080 — в шестнадцатеричной системе). А если рассматривать их как одно число (двойное слово), где в старшем слове 762, а в младшем — 61568, то это и будет 50000000 (2FAF080 — в шестнадцатеричной системе).
Затем в регистр BX мы записываем число 60000 и выполняем команду деления. В результате в регистре АХ будет число 833 (или 341 в шестнадцатеричной системе), в регистре DX — остаток от деления, который в нашем случае будет равен 20000 (или 4E20 в шестнадцатеричной системе).
В конце как обычно расскажу, почему эта команда ассемблера называется DIV. Это сокращение от английского слова DIVIDE, которое можно перевести как “разделить”.
Подписаться на Дзен-канал
Вступить в группу «Основы программирования» Подписаться на рассылки по программированию |
Первые шаги в программирование
Главный вопрос начинающего программиста – с чего начать? Вроде бы есть желание, но иногда «не знаешь, как начать думать, чтобы до такого додуматься». У человека, который никогда не имел дело с информационными технологиями, даже простые вопросы могут вызвать большие трудности и отнять много времени на решение. Подробнее… |
Деление в ассемблере
Используя наш сайт, вы подтверждаете, что прочитали и поняли политику о куки , политику конфиденциальности и пользовательское соглашение. Stack Overflow на русском — это сайт вопросов и ответов для программистов. Регистрация займёт не больше минуты. Присоединиться к сообществу. Лучшие ответы получают голоса и поднимаются наверх.
Поиск данных по Вашему запросу:
Деление в ассемблере
Схемы, справочники, даташиты:
Прайс-листы, цены:
Обсуждения, статьи, мануалы:
Дождитесь окончания поиска во всех базах.
По завершению появится ссылка для доступа к найденным материалам.
Содержание:
- 1. Регистры
- Команда DIV
Основы языка Assembler: Методические указания к лабораторным работам - Деление (DIV, IDIV)
- Команды ассемблера
- Система команд x86
- Деление и умножение в Assembler
ПОСМОТРИТЕ ВИДЕО ПО ТЕМЕ: 0005 Команда DIV
1. Регистры
Здравствуйте, уважаемые друзья! Продолжаем изучать нашу рубрику, на очереди тема умножения и деления в Assembler. Разберемся со всеми тонкостями этих операций, конечно же, на практическом примере. Итак, как мы уже сказали, при умножении и делении в Assembler есть некоторые тонкости, о которых дальше и пойдет речь. Тонкости эти состоят в том, что от того, какой размерности регистр мы делим или умножаем многое зависит.
Вот примеры:. Далее перейдем к примеру: он не должен вызвать у вас каких либо затруднений, если вы читали наши предыдущие статьи, особенно важна статья про вывод на экран , советую вам с ней ознакомиться. Ну а мы начнем:.
Стандартное начало, в котором мы подключаем нужные нам библиотеки и объявляем переменные для вывода чисел на экран. Единственное о чем нужно сказать: новый для нас раздел. Знак вопроса говорит о том, что память будет выделяться на этапе компилирования и не будет выделяться в самом исполняемом файле с расширением. Такое объявление — грамотное с точки зрения программирования. В разделе кода, уже по традиции, считываем дескриптор экрана для вывода и задаем значения для перевода каретки.
Затем помещаем в регистры соответствующие значения и выполняем деление регистра ebx, как оно реализуется описано чуть выше. Думаю, тут понятно, что мы просто делим число 99 на 3, что получилось в итоге выводим на экран консоли. Думаю, что здесь тоже все понятно и без комментариев. Как производиться умножение в Assembler вы тоже можете прочитать чуть выше, ну и результат выводим на экран. Этот код я поместил в файл seventh. Далее открыл консоль, как и всегда, с помощью команды cd перешел в эту папку и прописал amake.
Скомпилировалось, затем запускаю исполняемый файл и в консоли получаются такие числа: Как видите, мы правильно посчитали эти операции.
Скачать исходники. Ваш e-mail не будет опубликован. Уведомить меня о новых комментариях по email. Уведомлять меня о новых записях почтой. Открыть возможности мозга. Деление и умножение в Assembler Опубликовал: Nikiqq Основные команды Для умножения в Assembler используют команду mul Для деления в Assembler используют команду div Правила умножения в Assembler Итак, как мы уже сказали, при умножении и делении в Assembler есть некоторые тонкости, о которых дальше и пойдет речь.
Вот примеры: Если аргументом команды mul является 1-байтовый регистр например mul bl , то значение этого регистра bl умножится на значение регистра al , а результат запишется в регистр ax , и так будет всегда, независимо от того, какой 1-байтовый регистр мы возьмем.
Результат от деления запишется в регистр ax , а остаток запишется в регистр dx. Результат от деления запишется в регистр eax , а остаток запишется в регистр edx. Просмотр консоли Этот код я поместил в файл seventh. На этом сегодня все! Надеюсь вы научились выполнять деление и умножение на Assembler. Опубликовано в Assembler. Предыдущая запись Вывод строковых массивов.
Следующая запись Логические операции в Assembler. Пожалуй, вы правы. Но мы работаем с директивой. Добавить комментарий Отменить ответ Ваш e-mail не будет опубликован. Отправить на электронный адрес Ваше имя Ваш адрес электронной почты Отмена Сообщение не было отправлено — проверьте адреса электронной почты! Проверка по электронной почте не удалась, попробуйте еще раз. К сожалению, ваш блог не может делиться ссылками на записи по электронной почте.
Команда DIV
Здравствуйте, уважаемые друзья! Продолжаем изучать нашу рубрику, на очереди тема умножения и деления в Assembler. Разберемся со всеми тонкостями этих операций, конечно же, на практическом примере. Итак, как мы уже сказали, при умножении и делении в Assembler есть некоторые тонкости, о которых дальше и пойдет речь. Тонкости эти состоят в том, что от того, какой размерности регистр мы делим или умножаем многое зависит. Вот примеры:.
Но не знаю как разделить число на ассемблере, да еще и на Если имеется в виду деление на константу, до делить ВООБЩЕ не надо.
Основы языка Assembler: Методические указания к лабораторным работам
Войдите , пожалуйста. Хабр Geektimes Тостер Мой круг Фрилансим. Войти Регистрация. Целочисленное деление на заранее известную костанту можно заменить на целочисленное умножение на другую константу и обработкой результата напильником. Это будет быстрее, так как умножение занимает где-то в районе пяти тактов процессора, а деление около В гугле меня не забанили, но как найти исходный делитель я сходу не нашел, найдя при этом несколько руководств по оптимизации, где сообщалось как вычислить множитель для такой замены. Впрочем сообщалось в виде готового алгоритма, без пояснения стоящей за этим математикой. При этом целая часть числа будет всегда нулём, а идущие после точки нули выкидываются до первой единицы. Количество выкинутых нулей запоминается, дабы сделать потом соотв.
Деление (DIV, IDIV)
Мне нужен простой способ для деления целых чисел без знака 64b в ассемблере для x Фактор находится в 32b целых. Какой-нибудь код, пожалуйста? Если я правильно интерпретирую ваш вопрос в частности, часть Factor is in 32b integer , вы хотите разделить битное дивиденд на разрядный делитель и получить битный коэффициент.
Местоположение делимого в командах DIV , IDIV не указывается, оно жестко определено и зависит от размерности байт, слово, двойное слово делителя.
Команды ассемблера
Многие опкоды делают вычисления. Вы можете узнать многие из них по их названиям: add addition — добавление , sub substraction — вычитание , mul multiply — умножение , div divide — деление. Эта команда очень проста. Она добавляет значение источника к значение приемника и помещает результат в приемник. Другие математические команды:. Поскольку регистры могут содержать только целочисленные значения то есть числа, не, с плавающей запятой , результат деления разбит на частное и остаток.
Система команд x86
В этом уроке по языку ассемблер мы будем говорит об умножении и делении, обрабатывать числа будем как со знаком так и без него. Хочу заметить то что процессор работает только с целыми числам, и это конечно нужно знать и учитывать. Для работы с вещественными числами числа с плавающей точкой существует сопроцессор, о котором мы еще поговорим в следующих уроках. Это зависит от размера множителя. К примеру мы хотим умножит содержимое AL на BL для этого нам нужно занести в эти младшие части зачернения и выполнить команду mul bl , результат будет в AX. А чтоб умножить слово на слово: mul bx , но в этом случае результат будет находиться в двух регистрах DX:AX. И еще уточним одну деталь перед умножением слов желательно обнулить DX , это можно сделать просто поместив в него ноль. Также умножать можно и на переменные.
Данная группа команд реализует четыре основные арифметические операции – сложение, вычитание, умножение и деление. С точки зрения типов.
Деление и умножение в Assembler
Деление в ассемблере
Деление знаковых чисел с выводом ошибки «Деление на ноль» Собственно поставили передо мной задачу — написать прогу деления двух чисел, причем что бы Можно ли использовать одновременно update, select, и деление? Добрый день, есть таблица с полями width, height, ratio. Можно ли сделать в Ubuntu деление окон как в Windows 7?
Данная группа команд реализует четыре основные арифметические операции — сложение, вычитание, умножение и деление. С точки зрения типов операндов, арифметические команды можно разделить на работающие с целыми и вещественными операндами. Арифметические команды имеют следующий формат Fppp для вещественных операндов или FIppp для целочисленных операндов , где ррр может принимать значения:. Результат заносится в регистр стека сопроцессора ST 0.
Замена деления умножением на Ассемблере
Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда — alarforum yandex. Обязательно пройдите активизацию e-mail. Делитель находится в стеке в виде двух слов. Stilet Посмотреть профиль Найти ещё сообщения от Stilet. Постараюсь объяснить на примере деления слова на слово. Если суть понял, то программу напишешь. Опции темы.
Инструкция DIV в Ассемблере выполняет деление без знака. Использование этой инструкции похоже на работу команды MUL , хотя, конечно, имеет некоторые особенности, потому что деление — это не умножение. Эта команда не работает с сегментными регистрами, а также не работает непосредственно с числами. То есть вот так.
x86 — Язык ассемблера — Как сделать по модулю?
Если ваш модуль/делитель является известной константой, и вы заботитесь о производительности, см. это и это. Мультипликативная инверсия возможна даже для значений, не зависящих от цикла, которые неизвестны до времени выполнения, например. см. https://libdivide.com/ (Но без JIT-кода это менее эффективно, чем жесткое кодирование только шагов, необходимых для одной константы.)
Никогда не используйте div
для известных степеней двойки: это много медленнее, чем и
для остатка или сдвиг вправо для деления. Посмотрите на вывод компилятора C для примеров беззнакового или знакового деления на степени 2, например. в проводнике компилятора Godbolt. Если вы знаете, что ввод времени выполнения является степенью числа 2, используйте lea eax, [esi-1]
; и eax, edi
или что-то в этом роде, чтобы сделать x & (y-1)
. Модуль 256 еще более эффективен: movzx eax, cl
имеет нулевую задержку на последних процессорах Intel (mov-elimination), если два регистра разделены.
Инструкция DIV
(и ее аналог IDIV
для чисел со знаком) дает как частное, так и остаток. Для беззнакового остаток и модуль — одно и то же. Для подписанного idiv
он дает вам остаток (не модуль), который может быть отрицательным:
, например. -5 / 2 = -2 бэр -1
. Семантика деления x86 точно соответствует оператору C99 %
.
DIV r32
делит 64-битное число на EDX:EAX
32-битным операндом (в любом регистре или памяти) и сохраняет частное в EAX
, а остаток в EDX
. Ошибка при переполнении частного.
Беззнаковый 32-битный пример (работает в любом режиме)
mov eax, 1234 ; младшая половина дивиденда мов edx, 0 ; старшая половина дивиденда = 0. предпочитаю xor edx,edx мов ebx, 10 ; делителем может быть любой регистр или память раздел ebx ; Делит 1234 на 10. ; EDX = 4 = 1234 % 10 остаток ; EAX = 123 = 1234 / 10 частное
В 16-битной сборке вы можете сделать div bx
, чтобы разделить 32-битный операнд в DX:AX
на BX
. Дополнительную информацию см. в Руководствах разработчика программного обеспечения для архитектур Intel.
Обычно всегда используйте xor edx,edx
перед unsigned div
для нулевого расширения EAX в EDX:EAX. Вот как вы делаете «обычное» 32-битное / 32-битное => 32-битное деление.
Для разделения со знаком, используйте cdq
до idiv
до знак -расширить EAX в EDX:EAX. См. также Почему EDX должен быть равен 0 перед использованием инструкции DIV?. Для других размеров операндов используйте cbw
(AL->AX), cwd
(AX->DX:AX), cdq
(EAX->EDX:EAX) или cqo
(RAX->RDX :RAX), чтобы установить верхнюю половину на 0
или -1
в соответствии с битом знака младшей половины.
div
/ idiv
доступны с размерами операндов 8, 16, 32 и (в 64-битном режиме) 64-бит. 64-битный размер операнда намного медленнее, чем 32-битный или меньше на текущих процессорах Intel, но процессоры AMD заботятся только о фактической величине чисел, независимо от размера операнда.
Обратите внимание, что 8-битный размер операнда особенный: неявные входы/выходы находятся в AH:AL (он же AX), а не DL:AL. См. сборку 8086 на DOSBox: Баг с инструкцией idiv? для примера.
Пример 64-битного деления со знаком (требуется 64-битный режим)
mov rax, 0x8000000000000000 ; INT64_MIN = -9223372036854775808 мов екх, 10 ; неявное нулевое расширение подходит для положительных чисел cqo ; расширение знака в RDX, в данном случае = -1 = 0xFF...FF идив rcx ; частное = RAX = -922337203685477580 = 0xf333333333333334 ; остаток = RDX = -8 = 0xffffffffffffffff8
Ограничения/распространенные ошибки
div dword 10
не кодируется в машинный код (поэтому ваш ассемблер сообщит об ошибке о недопустимых операндах).
В отличие от mul
/ imul
(где обычно следует использовать более быстрые 2-операндные imul r32, r/m32
или 3-операндные imul r32, r/m32, imm8/32
вместо тех, которые не тратить время на запись результата старшей половины), нет более нового кода операции для деления на непосредственное или 32-битное/32-битное => 32-битное деление или остаток без ввода делимого старшей половины.
Дивизия настолько медленная и (надеюсь) редкая, что они не удосужились добавить способ, позволяющий вам избегать EAX и EDX, или напрямую использовать немедленное.
div и idiv выдадут ошибку, если частное не помещается в один регистр (AL/AX/EAX/RAX, той же ширины, что и делимое). Это включает в себя деление на ноль, но также произойдет с ненулевым EDX и меньшим делителем. Вот почему компиляторы C просто выполняют расширение нулями или расширением знака вместо того, чтобы разбивать 32-битное значение на DX:AX.
А также почему INT_MIN / -1
является неопределенным поведением C: оно переполняет частное со знаком в системах с дополнением до 2, таких как x86. См. Почему целочисленное деление на -1 (отрицательное) приводит к FPE? для примера x86 против ARM. x86 idiv
действительно ошибается в этом случае.
Исключение x86: #DE
— исключение разделения. В системах Unix/Linux ядро посылает сигнал арифметического исключения SIGFPE процессам, вызывающим исключение #DE. (На каких платформах целочисленное деление на ноль вызывает исключение с плавающей запятой?)
Для div
безопасно использовать делимое с high_half < divisor
. например 0x11:23 / 0x12
меньше, чем 0xff
, поэтому он соответствует 8-битному частному.
Деление большого числа с повышенной точностью на малое может быть реализовано путем использования остатка от одного фрагмента в качестве делимого старшей половины (EDX) для следующего фрагмента. Вероятно, поэтому они выбрали остаток=EDX quotient=EAX, а не наоборот.
Как использовать инструкцию div для поиска остатка в сборке x86?
Задавать вопрос
спросил
Изменено 7 лет, 4 месяца назад
Просмотрено 28 тысяч раз
мов акс, 0 мов ебкс, 0 мов эдкс, 0 мов топор, 31 мул сх мов бх, 12 делитель bx добавить бп, топор движение акс, 0 мов ебкс, 0 мов бп, бп Мов аль, 7 раздел аль
может ли кто-нибудь сказать мне, что не так с инструкцией div al в этом блоке кода, так как я отлаживаю каждое вычисленное количество битов, когда я делю на al, это дает мне 1 в качестве остатка, почему это происходит?
остаток следует сохранить обратно в регистр ah
заранее спасибо
отредактированный код:
mov eax, 0 мов ебкс, 0 мов эдкс, 0 мов топор, 31 мул сх мов бх, 12 делитель bx добавить бп, топор движение акс, 0 мов ебкс, 0 мов топор, бп мов бл, 7 раздел бл мов аль, 0
- сборка
- x86
- разделение
2
Вы не можете использовать al
в качестве делителя, потому что команда div
предполагает, что x
будет делимым.