<?xml version='1.0' encoding="utf-8"?>
      <rss version='2.0'>
      <channel>
      <title>Форум на Исходниках.RU</title>
      <link>https://forum.sources.ru</link>
      <description>Форум на Исходниках.RU</description>
      <generator>Форум на Исходниках.RU</generator>
  	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=215557&amp;view=findpost&amp;p=3805690</guid>
        <pubDate>Thu, 01 Aug 2019 20:15:19 +0000</pubDate>
        <title>Арифметика с длинными числами</title>
        <link>https://forum.sources.ru/index.php?showtopic=215557&amp;view=findpost&amp;p=3805690</link>
        <description><![CDATA[Tamilla: правила простой математики- <a class='tag-url' href='https://nauka.club/matematika/poryadok-dejstvij-pravila-ocherednosti.html' target='_blank'>порядок дейсвия</a> в умножении<br>
<br>
<br>
Базовыми формами вычисления являются: <br>
Сложение + <br>
Умножение х или ∗ <br>
Вычитание - <br>
Деление ÷ или / <br>
<br>
К ним также можно отнести возведение в степень, однако с ним действуют те же законы, что и при умножении. <br>
Итак, последовательность расчетов регулируется следующими правилами. <br>
<br>
По умолчанию, при отсутствии дополнительных элементов, они выполняются в порядке написания. 15 - 3 + 7 = 19 <br>
При наличии скобок сначала выполняется действие, в них заключенное. 15 - (3 + 7) = 5 <br>
При появлении знаков или первыми выполняются они, лишь затем сложение или вычитание. 2 + 2 х 2 = 2 + 4 = 6 2 + 2 ÷ 2 = 2 + 1 = 3 <br>
Скобки могут частично ослабить эти правила, так как действие в них заключенное всегда выполняется в первую очередь. (2 + 2) х 2 = 4 х 2 = 8 (2 + 2) ÷ 2 = 4 ÷ 2 = 2 <br>
Если в скобки заключено сложное выражение, внутри них работают стандартные правила. (4 + 7 - 1) + 5 = (11 - 1) + 5 = 15 (5 + 3 х 2) - 4 = (5 + 6) - 4 = 11 - 4 = 7 <br>
При появлении двух и более знаков или нужно учитывать их очередность. 5 х 2 - 8 ÷ 4 = 10 - 2 = 8]]></description>
        <author>Tamilla</author>
        <category>Assembler FAQ</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=215557&amp;view=findpost&amp;p=1804704</guid>
        <pubDate>Sat, 15 Dec 2007 22:28:09 +0000</pubDate>
        <title>Арифметика с длинными числами</title>
        <link>https://forum.sources.ru/index.php?showtopic=215557&amp;view=findpost&amp;p=1804704</link>
        <description><![CDATA[AndNot: <div class='tag-align-center'><br>
<span class='tag-size' data-value='13' style='font-size:13pt;'><span class="tag-color tag-color-named" data-value="blue" style="color: blue"><strong class='tag-b'>Арифметика с длинными числами</strong></span></span></div><br>
<div class='tag-align-center'><span class='tag-size' data-value='11' style='font-size:11pt;'><span class="tag-color tag-color-named" data-value="green" style="color: green"><strong class='tag-b'>Небольшое предисловие</strong></span></span></div><br>
Сразу оговорюсь, что я не ставил своей целью работу с числами любого размера, для простоты взял так называемые long числа, т.е. для 16-ти разрядного кода - это 32-х битные числа, а для 32-х разрядного кода - 64-х битные. Все примеры даны для 16-ти битного кода, но при желании легко переводятся под 32-х битные системы. И если понять теорию, то несложно применить данные алгоритмы для работы с числами любой разрядности, по крайней мере, я старался не просто предоставить код, а пояснить саму суть алгоритмов, дать теоретическое обоснование, да еще и на простом и всем понятном русском языке :) Что нам понадобится? Естественно знание ассемблера, хотя бы на уровне синтаксиса, ну и три класса образования :)<br>
В примерах будут использоваться числа, определенные в сегменте данных.<br>
Для удобства и экономии места объявим их заранее:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">ideal</div><div class="code_line">P386</div><div class="code_line">model tiny</div><div class="code_line">locals __</div><div class="code_line">&nbsp;</div><div class="code_line">dataseg</div><div class="code_line">label X word</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;dd &nbsp; &nbsp; &nbsp;0000FFFEh</div><div class="code_line">label Y word</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;dd &nbsp; &nbsp; &nbsp;00010003h</div><div class="code_line">label Z word</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;qword &nbsp; 0</div><div class="code_line">&nbsp;</div><div class="code_line">Shift &nbsp; db 5</div></ol></div></div></div></div><script>preloadCodeButtons('1');</script><br>
<div class='tag-align-center'><span class='tag-size' data-value='11' style='font-size:11pt;'><span class="tag-color tag-color-named" data-value="green" style="color: green"><strong class='tag-b'>Хранение и преобразования</strong></span></span></div><br>
Хранить числа будем так же, как и принято в x86 архитектуре - младший байт по младшему адресу. Таким образом, загрузка числа в регистры выглядит следующим образом:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; AX - младшая часть числа</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; dx, [X+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; DX - старшая часть числа</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DX:AX = X</div></ol></div></div></div></div><br>
Сохранение числа из DX:AX в память:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; [X], ax &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; записываем младшую часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; [X+2], dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; записываем старшую часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; X = DX:AX</div></ol></div></div></div></div><br>
Зачастую может понадобиться получить длинное число из числа меньшей разрядности. Здесь есть два варианта. Для без знаковых чисел достаточно очистить старшую часть:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; AX - исходное число</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xor &nbsp; &nbsp; dx, dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; у беззнакового старшие биты(DX) равны 0</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DX:AX = X</div></ol></div></div></div></div><br>
Расширение чисел со знаком осуществляется немного по-другому, поскольку знак числа определяется его старшим битом, которым и нужно заполнить старшую часть числа. Самый быстрый вариант:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; AX - исходное число</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; dx, ax</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sar &nbsp; &nbsp; dx, 15 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; if (AX &#62;= 0) DX=0 else DX=sign, т.е. -1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DX:AX = X</div></ol></div></div></div></div><br>
Менее быстрый, но самый короткий вариант:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; AX - исходное число</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cwd &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; перенос в DX старшего(знакового) бита AX</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DX:AX = X</div></ol></div></div></div></div><br>
<div class='tag-align-center'><span class='tag-size' data-value='11' style='font-size:11pt;'><span class="tag-color tag-color-named" data-value="green" style="color: green"><strong class='tag-b'>Сравнение чисел</strong></span></span></div><br>
Для начала рассмотрим сравнение чисел без знака. Но здесь понадобится некоторое знание команд сравнения и условных переходов. Сравнение производится по простому принципу, сначала сравниваем старшую часть, а затем, если это еще необходимо, младшую. Проще всего понять это на примере. Допустим, есть некое число в регистрах <em class='tag-i'>DX:AX</em> и если оно больше числа <em class='tag-i'>X</em>, то нужно выполнить какие либо действия:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">; if DX:AX &#62; [X]:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; dx, [X+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; сравниваем старшие части</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jne &nbsp; &nbsp; __islater</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; сравниваем младшие части</div><div class="code_line">&nbsp;&nbsp; &nbsp;__islater:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jbe &nbsp; &nbsp; __later &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; &#60;- переход при DX:AX &#60;= [X]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; сюда попадем при DX:AX &#62; [X]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; соответственно делаем что нам нужно</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;....</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;__later:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; продолжаем программу</div></ol></div></div></div></div><br>
А теперь по порядку. Почему прыгаем на второй переход, после первого сравнения? Да все очень просто. Если <em class='tag-i'>DX</em> меньше <em class='tag-i'>[X+2]</em>, то будет установлен флаг переноса <em class='tag-i'>CF</em>, поэтому второй переход перенаправит программу на метку <em class='tag-i'>__later</em>. Если же <em class='tag-i'>DX</em> больше <em class='tag-i'>[X+2]</em>, то флаг <em class='tag-i'>CF</em> будет нулевым и переход не сработает, мы попадем на код, который выполняется при <em class='tag-i'>DX:AX &gt; [X]</em>. Ну и если старшие части равны, то первый переход не сработает, и все будет зависеть от сравнения младших частей чисел. Далее приведу только примеры, поскольку все они работают по такому же принципу.<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">; if DX:AX &#62;= [X]:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; dx, [X+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; сравниваем старшие части</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jne &nbsp; &nbsp; __islater</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; сравниваем младшие части</div><div class="code_line">&nbsp;&nbsp; &nbsp;__islater:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jb &nbsp; &nbsp; &nbsp;__later &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; &#60;- переход при DX:AX &#60; [X]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; сюда попадем при DX:AX &#62;= [X]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; соответственно делаем что нам нужно</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;....</div><div class="code_line">&nbsp;&nbsp; &nbsp;__later:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; продолжаем программу</div></ol></div></div></div></div><div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">; if DX:AX &#60; [X]:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; dx, [X+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; сравниваем старшие части</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jne &nbsp; &nbsp; __isgreat</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; сравниваем младшие части</div><div class="code_line">&nbsp;&nbsp; &nbsp;__isgreat:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jae &nbsp; &nbsp; __great &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; &#60;- переход при DX:AX &#62;= [X]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; сюда попадем при DX:AX &#60; [X]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; соответственно делаем что нам нужно</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;....</div><div class="code_line">&nbsp;&nbsp; &nbsp;__great:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; продолжаем программу</div></ol></div></div></div></div><div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">; if DX:AX &#60;= [X]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; dx, [X+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; сравниваем старшие части</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jne &nbsp; &nbsp; __isgreat</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; сравниваем младшие части</div><div class="code_line">&nbsp;&nbsp; &nbsp;__isgreat:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;ja &nbsp; &nbsp; &nbsp;__great &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; &#60;- переход при DX:AX &#62; [X]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; сюда попадем при DX:AX &#60;= [X]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; соответственно делаем что нам нужно</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;....</div><div class="code_line">&nbsp;&nbsp; &nbsp;__great:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; продолжаем программу</div></ol></div></div></div></div><div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">; if DX:AX = [X]:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; dx, [X+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; сравниваем старшие части</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jne &nbsp; &nbsp; __isnoteq</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; сравниваем младшие части</div><div class="code_line">&nbsp;&nbsp; &nbsp;__isnoteq:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jne &nbsp; &nbsp; __noteq &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; &#60;- переход при DX:AX &#60;&#62; [X]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; сюда попадем при DX:AX = [X]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; соответственно делаем что нам нужно</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;....</div><div class="code_line">&nbsp;&nbsp; &nbsp;__noteq:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; продолжаем программу</div></ol></div></div></div></div><div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">; if DX:AX &#60;&#62; [X]:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; dx, [X+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; сравниваем старшие части</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jne &nbsp; &nbsp; __isequ</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; сравниваем младшие части</div><div class="code_line">&nbsp;&nbsp; &nbsp;__isequ:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;je &nbsp; &nbsp; &nbsp;__equ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; &#60;- переход при DX:AX = [X]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; сюда попадем при DX:AX &#60;&#62; [X]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; соответственно делаем что нам нужно</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;....</div><div class="code_line">&nbsp;&nbsp; &nbsp;__equ:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; продолжаем программу</div></ol></div></div></div></div><br>
Для сравнения чисел со знаком применяется та же схема, только используются другие флаги, а именно <em class='tag-i'>SF</em> и <em class='tag-i'>OF</em>. Тот же пример:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">; if DX:AX &#62; [X]:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; dx, [X+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; сравниваем старшие части</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jne &nbsp; &nbsp; __islater</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; сравниваем младшие части</div><div class="code_line">&nbsp;&nbsp; &nbsp;__islater:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jle &nbsp; &nbsp; __later &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; &#60;- переход при DX:AX &#60;= [X]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; сюда попадем при DX:AX &#62; [X]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; соответственно делаем что нам нужно</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;....</div><div class="code_line">&nbsp;&nbsp; &nbsp;__later:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; продолжаем программу</div></ol></div></div></div></div><br>
Остальной код приводить не буду, он практически идентичный, только вместо команд условного перехода для чисел без знака используются команды условного перехода для знаковых чисел. Т.е. достаточно выполнить следующую замену:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jb &nbsp;-&#62; &nbsp;jl</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jbe -&#62; &nbsp;jle</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;ja &nbsp;-&#62; &nbsp;jg</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jae -&#62; &nbsp;jge</div></ol></div></div></div></div><br>
<div class='tag-align-center'><span class='tag-size' data-value='11' style='font-size:11pt;'><span class="tag-color tag-color-named" data-value="green" style="color: green"><strong class='tag-b'>Логические и арифметические сдвиги</strong></span></span></div><br>
Логический сдвиг чисел можно реализовать несколькими способами.<br>
<span class='tag-u'>1</span>. совместимый со всеми моделями процессоров.<br>
Сдвиг влево:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; AX - младшая часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; dx, [X+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; DX - старшая часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; cl, [Shift] &nbsp; &nbsp; &nbsp; &nbsp;; CL - величина сдвига</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; cl, 16</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jae &nbsp; &nbsp; __short</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shl &nbsp; &nbsp; dx, cl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; сдвигаем старшую часть числа</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; bx, ax &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; сохраняем младшую часть, для ее сдвига в старшую</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shl &nbsp; &nbsp; ax, cl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; сдвигаем младшую часть числа</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sub &nbsp; &nbsp; cl, 16</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;neg &nbsp; &nbsp; cl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; CL = 16-CL</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shr &nbsp; &nbsp; bx, cl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; выделяем старшие биты младшего слова</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;or &nbsp; &nbsp; &nbsp;dx, bx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; и заносим их в младшие биты старшего слова</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;ret &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; DX:AX = DX:AX shl CL</div><div class="code_line">&nbsp;&nbsp; &nbsp;__short:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;and &nbsp; &nbsp; cl, 0fh &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; CL = CL-16, но можно и убрать, процессор сам обрежет</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; dx, ax &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; SHL DX:AX, 16</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xor &nbsp; &nbsp; ax, ax &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; младшая часть будет нулевой</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shl &nbsp; &nbsp; dx, cl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; сдвигаем старшую часть на CL-16 бит</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;ret &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; DX:AX = DX:AX shl CL</div></ol></div></div></div></div><br>
Сдвиг вправо:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; AX - младшая часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; dx, [X+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; DX - старшая часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; cl, [Shift] &nbsp; &nbsp; &nbsp; &nbsp;; CL - величина сдвига</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; cl, 16</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jae &nbsp; &nbsp; __short</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shr &nbsp; &nbsp; ax, cl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; сдвигаем младшую часть числа</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; bx, dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; сохраняем старшую часть, для ее сдвига в младшую</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shr &nbsp; &nbsp; dx, cl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; сдвигаем старшую часть числа</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sub &nbsp; &nbsp; cl, 16</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;neg &nbsp; &nbsp; cl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; CL = 16-CL</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shl &nbsp; &nbsp; bx, cl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; выделяем младшие биты старшего слова</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;or &nbsp; &nbsp; &nbsp;ax, bx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; и заносим их в старшие биты младшего слова</div><div class="code_line">&nbsp;&nbsp; &nbsp;__short:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;and &nbsp; &nbsp; cl, 0fh &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; CL = CL-16, но можно и убрать, процессор сам обрежет</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; SHR DX:AX, 16</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xor &nbsp; &nbsp; dx, dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; старшее слово будет нулевым</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shr &nbsp; &nbsp; ax, cl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; сдвигаем младшее слово на CL-16 бит</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;ret &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; DX:AX = DX:AX shr CL</div></ol></div></div></div></div><br>
<span class='tag-u'>2</span>. быстрый вариант, для 386+<br>
Сдвиг влево:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; AX - младшая часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; dx, [X+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; DX - старшая часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; cl, [Shift] &nbsp; &nbsp; &nbsp; &nbsp;; CL - величина сдвига</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; cl, 16</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jae &nbsp; &nbsp; __short</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shld &nbsp; &nbsp;dx, ax, cl &nbsp; &nbsp; &nbsp; &nbsp; ; сдвигаем старшее слово с выдвижением в него старших бит младшего</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shl &nbsp; &nbsp; ax, cl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; теперь сдвигаем младшее слово</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;ret &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; DX:AX = DX:AX shl CL</div><div class="code_line">&nbsp;&nbsp; &nbsp;__short:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;and &nbsp; &nbsp; cl, 0fh &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; CL = CL-16, но можно и убрать, процессор сам обрежет</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; dx, ax &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; SHL DX:AX, 16</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xor &nbsp; &nbsp; ax, ax &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; младшая часть будет нулевой</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shl &nbsp; &nbsp; dx, cl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; сдвигаем старшую часть на CL-16 бит</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;ret &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; DX:AX = DX:AX shl CL</div></ol></div></div></div></div><br>
Сдвиг вправо:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; AX - младшая часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; dx, [X+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; DX - старшая часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; cl, [Shift] &nbsp; &nbsp; &nbsp; &nbsp;; CL - величина сдвига</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; cl, 16</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jae &nbsp; &nbsp; __short</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shrd &nbsp; &nbsp;ax, dx, cl &nbsp; &nbsp; &nbsp; &nbsp; ; сдвигаем младшее слово с выдвижением в него младших бит старшего</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shr &nbsp; &nbsp; dx, cl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; теперь сдвигаем старшее слово</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;ret &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; DX:AX = DX:AX shr CL</div><div class="code_line">&nbsp;&nbsp; &nbsp;__short:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;and &nbsp; &nbsp; cl, 0fh &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; CL = CL-16, но можно и убрать, процессор сам обрежет</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; SHR DX:AX, 16</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xor &nbsp; &nbsp; dx, dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; старшее слово будет нулевым</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shr &nbsp; &nbsp; ax, cl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; сдвигаем младшее слово на CL-16 бит</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;ret &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; DX:AX = DX:AX shr CL</div></ol></div></div></div></div><br>
Но при логическом сдвиге вправо мы получаем только положительные числа, поскольку старшие биты обнуляются. Поэтому для сдвига знаковых чисел необходимо учитывать старший бит. Это делается с помощью команды <em class='tag-i'>SAR</em> (<span class='tag-u'>S</span>hift <span class='tag-u'>A</span>rithmetic operand <span class='tag-u'>R</span>ight), которая при сдвиге заполняет освобождаемые биты старшим битом операнда.<br>
Арифметический сдвиг вправо:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; AX - младшая часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; dx, [X+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; DX - старшая часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; cl, [Shift] &nbsp; &nbsp; &nbsp; &nbsp;; CL - величина сдвига</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; cl, 16</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jae &nbsp; &nbsp; __short</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shr &nbsp; &nbsp; ax, cl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; сдвигаем младшую часть числа</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; bx, dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; сохраняем старшую часть, для ее сдвига в младшую</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sar &nbsp; &nbsp; dx, cl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; сдвигаем старшую часть числа</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sub &nbsp; &nbsp; cl, 16</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;neg &nbsp; &nbsp; cl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; CL = 16-CL</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shl &nbsp; &nbsp; bx, cl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; выделяем младшие биты старшего слова</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;or &nbsp; &nbsp; &nbsp;ax, bx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; и заносим их в младшее слово</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;ret &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; DX:AX = DX:AX sar CL</div><div class="code_line">&nbsp;&nbsp; &nbsp;__short:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;and &nbsp; &nbsp; cl, 0fh &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; CL = CL-16, но можно и убрать, процессор сам обрежет</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; SHR DX:AX, 16</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sar &nbsp; &nbsp; dx, 15 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; if (DX &#62;= 0) DX=0 else DX=sign, т.е. -1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sar &nbsp; &nbsp; ax, cl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; сдвигаем младшее слово на CL-16 бит</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;ret &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; DX:AX = DX:AX sar CL</div></ol></div></div></div></div><br>
Или покороче, для 386+:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; AX - младшая часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; dx, [X+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; DX - старшая часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; cl, [Shift] &nbsp; &nbsp; &nbsp; &nbsp;; CL - величина сдвига</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; cl, 16</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jae &nbsp; &nbsp; __short</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shrd &nbsp; &nbsp;ax, dx, cl &nbsp; &nbsp; &nbsp; &nbsp; ; сдвигаем младшее слово с выдвижением в него младших бит старшего</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sar &nbsp; &nbsp; dx, cl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; теперь сдвигаем старшее слово</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;ret &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; DX:AX = DX:AX sar CL</div><div class="code_line">&nbsp;&nbsp; &nbsp;__short:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;and &nbsp; &nbsp; cl, 0fh &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; CL = CL-16, но можно и убрать, процессор сам обрежет</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; SHR DX:AX, 16</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sar &nbsp; &nbsp; dx, 15 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; if (DX &#62;= 0) DX=0 else DX=sign, т.е. -1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sar &nbsp; &nbsp; ax, cl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; сдвигаем младшее слово на CL-16 бит</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;ret &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; DX:AX = DX:AX sar CL</div></ol></div></div></div></div><br>
Думаю здесь все ясно, и объяснять ничего не надо, сдвиг он и в Африке сдвиг :)<br>
<br>
<div class='tag-align-center'><span class='tag-size' data-value='11' style='font-size:11pt;'><span class="tag-color tag-color-named" data-value="green" style="color: green"><strong class='tag-b'>Сложение и вычитание</strong></span></span></div><br>
Сложение реализуется по тому же принципу, по которому производится сложение столбцом в школе. Для тех, кто забыл, как это делается, напомню:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 98</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;+</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 67</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;---</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;165</div></ol></div></div></div></div>т.е. сложение можно выразить как два независимых сложения:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; 8 &nbsp; &nbsp;90</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; + &nbsp; &nbsp; +</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; 7 &nbsp; &nbsp;60</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; --- &nbsp; ---</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;15 &nbsp; 150</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 15</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; +</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;150</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;---</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;165</div></ol></div></div></div></div><br>
Таким образом, сложение можно реализовать достаточно просто - сначала складываем младшие части чисел (единицы), а затем старшие (десятки), но с учетом возможного переноса предыдущего сложения. Допустим, что есть два числа:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">DX:AX - 0000FFFEh</div><div class="code_line">CX:BX - 00010003h</div></ol></div></div></div></div>Складываем младшие части:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0FFFEh &nbsp; &nbsp; &nbsp;; AX</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;+</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 00003h &nbsp; &nbsp; &nbsp;; BX</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ------</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 10001h</div></ol></div></div></div></div><br>
Результат получился 17-ти битный, но поскольку у нас части чисел не могут превышать 16-ти бит, то в качестве результата получим младшие 16-ть бит, а 17-й отправится в регистр флагов, в бит <em class='tag-i'>CF</em> - <span class='tag-u'>C</span>arry <span class='tag-u'>F</span>lags (флаг переноса). Теперь складываем старшие части, но уже с учетом 17-го бита предыдущего сложения, для этого удобнее всего использовать команду <em class='tag-i'>ADC</em> - <span class='tag-u'>AD</span>d with <span class='tag-u'>C</span>arry, которая аналогична простой <em class='tag-i'>ADD</em>, но добавляет к сумме значение флага <em class='tag-i'>CF</em>:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 00000h &nbsp; &nbsp; &nbsp;; DX</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;+</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 00001h &nbsp; &nbsp; &nbsp;; CX</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;+</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1h &nbsp; &nbsp; &nbsp;; флаг CF - перенос от предыдущего сложения</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -----</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 00002h</div></ol></div></div></div></div><br>
Таким образом, получили правильный результат - 20001h. В теории выглядит немного страшно, но реализуется элементарно:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; AX - младшая часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; dx, [X+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; DX - старшая часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add &nbsp; &nbsp; ax, [Y] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; складываем младшие части</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;adc &nbsp; &nbsp; dx, [Y+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; складываем старшие части, с учетом флага переноса CF.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DX:AX = X+Y</div></ol></div></div></div></div><br>
Вычитание чисел производится похожим образом, но с учетом заема, для чего служит команда <em class='tag-i'>SBB</em> - <span class='tag-u'>S</span>u<span class='tag-u'>B</span>tract  with <span class='tag-u'>B</span>orrow:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; AX - младшая часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; dx, [X+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; DX - старшая часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sub &nbsp; &nbsp; ax, [Y] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; вычитаем младшие части</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sbb &nbsp; &nbsp; dx, [Y+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; вычитаем старшие части, с учетом</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; возможного заема предыдущего вычитания.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DX:AX = X-Y</div></ol></div></div></div></div><br>
<div class='tag-align-center'><span class='tag-size' data-value='11' style='font-size:11pt;'><span class="tag-color tag-color-named" data-value="green" style="color: green"><strong class='tag-b'>Изменение знака</strong></span></span></div><br>
Для изменения знака числа на противоположное существует команда <em class='tag-i'>NEG</em>, но она не работает с большими числами, поэтому придется реализовать свой вариант <em class='tag-i'>NEG</em>, реализованный по тому же принципу что и оригинальная команда. Сама команда работает следующим образом:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;not &nbsp; &nbsp; [X] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; инвертируем все биты числа</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add &nbsp; &nbsp; [X], 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; прибавляем еденицу</div></ol></div></div></div></div><br>
Отсюда и получаем несложную реализацию:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; AX - младшая часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; dx, [X+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; DX - старшая часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;not &nbsp; &nbsp; ax &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; инвертируем число</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;not &nbsp; &nbsp; dx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add &nbsp; &nbsp; ax, 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; добавляем еденицу</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;adc &nbsp; &nbsp; dx, 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; учитываем возможный перенос из сложения младшей части</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DX:AX = -DX:AX</div></ol></div></div></div></div><br>
А немного подумав, можно написать и покороче:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; dx, [X+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; DX - старшая часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; AX - младшая часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;not &nbsp; &nbsp; dx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;neg &nbsp; &nbsp; ax</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sbb &nbsp; &nbsp; dx, -1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; DX:AX = -DX:AX</div></ol></div></div></div></div><br>
<div class='tag-align-center'><span class='tag-size' data-value='11' style='font-size:11pt;'><span class="tag-color tag-color-named" data-value="green" style="color: green"><strong class='tag-b'>Умножение и деление</strong></span></span></div><br>
Вот и подошли к самой интересной части. Прежде чем рассматривать умножение вспомним, как мы это делали в школе, столбцом:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 98</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 67</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;---</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;686</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; 5880</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; + ----</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; 6566</div></ol></div></div></div></div>что можно записать как:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;98 &nbsp; &nbsp;98</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; * &nbsp; &nbsp; *</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; 7 &nbsp; &nbsp; 60</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; --- &nbsp; ----</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; 686 &nbsp; 5880</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;686</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;+</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; 5880</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; ----</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; 6566</div></ol></div></div></div></div><br>
То есть принцип простой, разбиваем 67 на два числа - 60 и 7, после чего перемножаем их на первое и результаты складываем. А теперь представим, что каждая цифра может содержать значение не от 0 до 9, а от 0 до 65535, т.е. целый 16-ти битный регистр, после чего умножение больших чисел сводится к традиционному умножению столбиком:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">DX:AX - 00020001h</div><div class="code_line">CX:BX - 00040003h</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;00020001h</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; *</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;00040003h</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;---------</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;00060003h &nbsp; &nbsp; &nbsp;; 00020001h*0003h (DX:AX * BX)</div><div class="code_line">&nbsp;&nbsp; &nbsp;00080004h &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; 00020001h*0004h (DX:AX * CX)</div><div class="code_line">&nbsp;&nbsp;+ -------------</div><div class="code_line">&nbsp;&nbsp; &nbsp;0008000A0003h</div></ol></div></div></div></div><br>
Разумеется, складывать нужно с учетом флага переноса. Ну и, учитывая вышесказанное, реализация будет выглядеть следующим образом:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xor &nbsp; &nbsp; dx, dx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; [Z+4], dx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; [Z+6], dx &nbsp; &nbsp; &nbsp; ; обнуляем старшие части результата</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; ; сначала перемножаем младшую часть X</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mul &nbsp; &nbsp; [Y] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; с обоими частями Y</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; [Z], ax</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; [Z+2], dx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; ; перемножаем младшую часть X</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mul &nbsp; &nbsp; [Y+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; со старшей частью Y</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add &nbsp; &nbsp; [Z+2], ax &nbsp; &nbsp; &nbsp; ; добавляем к результату</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;adc &nbsp; &nbsp; [Z+4], dx &nbsp; &nbsp; &nbsp; ; с учетом возможного переноса из предыдущего сложения</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;adc &nbsp; &nbsp; [Z+6], 0</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, [X+2] &nbsp; &nbsp; &nbsp; ; теперь перемножаем старшую часть X</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mul &nbsp; &nbsp; [Y] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; с обоими частями Y</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add &nbsp; &nbsp; [Z+2], ax &nbsp; &nbsp; &nbsp; ; с учетом возможного переноса из предыдущего сложения</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;adc &nbsp; &nbsp; [Z+4], dx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;adc &nbsp; &nbsp; [Z+6], 0</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, [X+2] &nbsp; &nbsp; &nbsp; ; перемножаем старшую часть X</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mul &nbsp; &nbsp; [Y+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; со старшей частью Y</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add &nbsp; &nbsp; [Z+4], ax</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;adc &nbsp; &nbsp; [Z+6], dx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; Z = X*Y</div></ol></div></div></div></div><br>
Можно немного упростить умножение, если у одного из множителей старшая часть равна нулю:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xor &nbsp; &nbsp; dx, dx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; [Z+4], dx &nbsp; &nbsp; &nbsp; ; обнуляем старшую части результата</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; ; сначала перемножаем младшую часть X</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mul &nbsp; &nbsp; [Y]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; [Z], ax</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; [Z+2], dx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, [X+2] &nbsp; &nbsp; &nbsp; ; теперь перемножаем старшую часть X</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mul &nbsp; &nbsp; [Y]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add &nbsp; &nbsp; [Z+2], ax</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;adc &nbsp; &nbsp; [Z+4], dx &nbsp; &nbsp; &nbsp; ; с учетом возможного переноса из предыдущего сложения</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; Z = X*Y</div></ol></div></div></div></div><br>
Осталось рассмотреть самую сложную часть - деление. В отличие от остальных операций здесь все немного сложнее. Первым, что приходит на ум - деление вычитанием:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, [X] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; AX - младшая часть делимого</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; dx, [X+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; DX - старшая часть делимого</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; bx, [Y] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; BX - младшая часть делителя</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; cx, [Y+2] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; CX - старшая часть делителя</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xor &nbsp; &nbsp; si, si</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xor &nbsp; &nbsp; di, di &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; DI:SI - результат (частное)</div><div class="code_line">&nbsp;&nbsp; &nbsp;__loop:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; dx, cx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; делимое больше делителя?</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jne &nbsp; &nbsp; __hinotequ</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; ax, bx</div><div class="code_line">&nbsp;&nbsp; &nbsp;__hinotequ:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jb &nbsp; &nbsp; &nbsp;__done &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; флаг переноса установится если делимое меньше делителя</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sub &nbsp; &nbsp; ax, bx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; вычитаем из делимого делитель</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sbb &nbsp; &nbsp; dx, cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add &nbsp; &nbsp; si, 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; увеличиваем частное</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;adc &nbsp; &nbsp; di, 0</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jmp &nbsp; &nbsp; __loop &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; повторяем, пока делимое не станет меньше делителя</div><div class="code_line">&nbsp;&nbsp; &nbsp;__done:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DI:SI - частное (результат)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DX:AX - остаток</div></ol></div></div></div></div><br>
Здесь есть один неприятный момент - при большом делимом и маленьком делителе скорость вычисления будет крайне мала, из-за тысячей циклов. Но есть и другой способ, пришедший еще со времен 8-ми битных процессоров, не имевших аппаратной поддержки деления. Он основан на серии сдвигов и вычитаний, неком аналоге деления столбиком, только с двоичной спецификой. Как мы делим столбиком? Допустим:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;2565|4</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;+---</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|</div></ol></div></div></div></div>Сначала подбираем наименьшее делимое. Мы видим, что 2 меньше 4, соответственно берем уже 25, а в частное записываем 0 (но поскольку он первый, то его можно проигнорировать). Но 25 намного больше 4, поэтому мы умножаем 4 на такое число, произведение которого будет как можно ближе к делимому ,но не превышая его, в нашем случае подходит 6:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;2565|4</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;24 &nbsp;+---</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;-- &nbsp;|6</div></ol></div></div></div></div>Теперь вычитаем это произведение из делимого и если оставшееся число все еще больше делителя, то повторяем. В результате получаем следующее:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;2565|4</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;24 &nbsp;+---</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;-- &nbsp;|641 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;- частное</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; 16</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; 16</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; ---</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 5</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;- остаток</div></ol></div></div></div></div><br>
Но это для десятичной системы счисления. Для двоичной все будет точно так же, но нам не придется подбирать множитель, поскольку основание системы позволяет использовать только ноль или единицу. Опять проще всего посмотреть на примере:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;101000000101|100</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;100 &nbsp; &nbsp; &nbsp; &nbsp; +----</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;--- &nbsp; &nbsp; &nbsp; &nbsp; |1010000001 - частное</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;100</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;100</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;---</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;00000101</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 100</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ---</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;- остаток</div></ol></div></div></div></div><br>
Легко заметить, что множитель всегда равен единице, что значительно упрощает нашу задачу, поскольку нам достаточно сравнить очередную часть делимого с делителем и если делимое меньше, то в частное добавляем ноль, иначе единицу и вычитаем делитель. Все это легко реализуется с помощью сдвига и вычитания. Собственно реализация:<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, [X]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; dx, [X+2] &nbsp; &nbsp; &nbsp; ; dx:ax - делимое</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; bx, [Y]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; cx, [Y+2] &nbsp; &nbsp; &nbsp; ; cx:bx - делитель</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;or &nbsp; &nbsp; &nbsp;cx, cx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; делитель меньше (2^16-1) ?</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jnz &nbsp; &nbsp; big_div &nbsp; &nbsp; &nbsp; &nbsp; ; &#60;- нет, переходим к варианту деления больших чисел</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; dx, bx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; если старшая часть делимого меньше делителя,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jb &nbsp; &nbsp; &nbsp;one_div &nbsp; &nbsp; &nbsp; &nbsp; ; то можно обойтись одним делением</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; придется делить старшую и младшую части отдельно, поскольку</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; в противном случае словим переполнение (результат превысит размер слова)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; cx, ax &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; сохраняем младшую часть делимого</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; ax, dx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xor &nbsp; &nbsp; dx, dx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;div &nbsp; &nbsp; bx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; делим старшую часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xchg &nbsp; &nbsp;ax, cx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; ax - младшая часть делимого</div><div class="code_line">one_div:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;div &nbsp; &nbsp; bx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; делим младшую часть</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; si, dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; si - младшая часть остатка</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; dx, cx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; dx - старшая часть результата</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xor &nbsp; &nbsp; di, di &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; di - старшая часть остатка</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;ret</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DX:AX &nbsp; - частное</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DI:SI &nbsp; - остаток</div><div class="code_line">&nbsp;</div><div class="code_line">big_div: &nbsp; &nbsp; &nbsp; &nbsp;; сюда попадаем только при делителе большем 0FFFFh</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov &nbsp; &nbsp; bp, 32 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; 32 цикла, по одному на каждый разряд числа</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xor &nbsp; &nbsp; si, si</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xor &nbsp; &nbsp; di, si &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; di:si - остаток деления</div><div class="code_line">&nbsp;&nbsp; &nbsp;__loop:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shl &nbsp; &nbsp; ax, 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; сдвигаем делимое влево, на один разряд</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;rcl &nbsp; &nbsp; dx, 1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;rcl &nbsp; &nbsp; si, 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; выдвигаемый с делимого бит заносится в остаток</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;rcl &nbsp; &nbsp; di, 1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; di, cx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; остаток больше делителя?</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jne &nbsp; &nbsp; __hinotequ</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp &nbsp; &nbsp; si, bx</div><div class="code_line">&nbsp;&nbsp; &nbsp;__hinotequ:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jc &nbsp; &nbsp; &nbsp;__next &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; флаг переполнения установится если остаток меньше делителя</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sub &nbsp; &nbsp; si, bx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; вычитаем из накопителя делитель</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sbb &nbsp; &nbsp; di, cx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;inc &nbsp; &nbsp; ax &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; и прибавляем еденицу к делимому</div><div class="code_line">&nbsp;&nbsp; &nbsp;__next:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;dec &nbsp; &nbsp; bp &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; повторяем, пока не пройдемся по всему числу</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jne &nbsp; &nbsp; __loop</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DX:AX - частное</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DI:SI - остаток</div></ol></div></div></div></div><br>
В самом начале функции мы проверяем размер делителя и если он умещается в одно слово, то используем аппаратное деление, что намного быстрее программного. Тут есть одна тонкость, связанная с реализацией деления на x86. Допустим, нужно разделить 101111h на 1. Естественно получим 101111h. Но это число не влезет в один 16-ти битный регистр и мы получим липовый результат, да еще и процессор сгенерирует исключение. Поэтому мы отлавливаем такие ситуации, деля число в два приема - сначала старшую часть (в примере - 10h), а затем младшую (1111h), что позволяет получить верный 32-х битный результат.<br>
Остается только добавить, что рассмотренные реализации умножения и деления расчитаны на числа без знака. Можно конечно реализовать и для знаковых чисел, но проще поменять знак на положительный, а после умножения/деления вернуть его обратно.<br>
<br>
<div class='tag-align-center'><span class='tag-size' data-value='11' style='font-size:11pt;'><span class="tag-color tag-color-named" data-value="green" style="color: green"><strong class='tag-b'>Заключение</strong></span></span></div><br>
Существуют более оптимальные алгоритмы деления больших чисел, но поскольку они специализированны на числах определенной длины, то здесь не рассматриваются. На этом закончу. Надеюсь, я достаточно ясно все разъяснил :)]]></description>
        <author>AndNot</author>
        <category>Assembler FAQ</category>
      </item>
	
      </channel>
      </rss>
	