<?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=411583&amp;view=findpost&amp;p=3749067</guid>
        <pubDate>Sat, 11 Nov 2017 19:58:46 +0000</pubDate>
        <title>Умная быстрая сортировка</title>
        <link>https://forum.sources.ru/index.php?showtopic=411583&amp;view=findpost&amp;p=3749067</link>
        <description><![CDATA[Jin X: Сделана ещё одна коллекция модулей сортировки. Полная копия описанных выше, но работающая с <span class="tag-color tag-color-named" data-value="blue" style="color: blue"><strong class='tag-b'>32-битными элементами&#33;</strong></span> :victory:<br>
<br>
Теперь вы можете использовать дальние указатели во втором двойном слове, либо 2 ближних указателя, а также 32-битные элементы в первом (опорном) двойном слове (в котором можно расположить, например, дату рождения).<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">+0 &nbsp;BYTE &nbsp;День рождения</div><div class="code_line">+1 &nbsp;BYTE &nbsp;Месяц рождения</div><div class="code_line">+2 &nbsp;WORD &nbsp;Год рождения</div><div class="code_line">+4 &nbsp;WORD &nbsp;Ближний указатель на фамилию</div><div class="code_line">+6 &nbsp;WORD &nbsp;Ближний указатель на имя</div></ol></div></div></div></div><script>preloadCodeButtons('1');</script><br>
Сортировка будет идти по дате рождения, а указатели на строку с фамилией и именем будут переноситься вместе с датой. Правда, здорово? :D<br>
Если 4-х байтов для опорных значений (т.е. значений, которые будут сравниваться и на основе которых будет происходить сортировка) слишком много, можно использовать 2 старших (WORD), а младшие 2 заполнить нулями (если сделать наоборот, то знаковое сравнение работать не будет).<br>
<br>
На этот раз я приведу лишь один исходный код – <em class='tag-i'><span class='tag-u'>универсального</span></em> модуля <strong class='tag-b'>IQSort4.inc</strong>, модуля умной быстрой сортировки расширенных (32-битных) элементов:<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">;##################################################</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &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;[ Asm7x.List ][ IQSort4.inc ] &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;UNIVERSAL UNIT FOR 16 BIT &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; УНИВЕРСАЛЬНЫЙ МОДУЛЬ ДЛЯ 16 БИТ &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;-= Smart Quick Sort =- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp;(for extended elenemt arrays) &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Умная быстрая сортировка &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ##</div><div class="code_line">;## &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [ v1.00 :: 11.11.2017 ] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MASM/TASM (16 bit 386+) &nbsp; &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; (c) 2017 by Jin X (jin.x@sources.ru) &nbsp; &nbsp; ##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; http://xk7.ru/p/a/i &nbsp; &nbsp; &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;##################################################</div><div class="code_line">&nbsp;</div><div class="code_line">IFDEF &nbsp; &nbsp; &nbsp; ??Version &nbsp; ; TASM</div><div class="code_line">&nbsp;&nbsp;LOCALS</div><div class="code_line">ENDIF</div><div class="code_line">&nbsp;</div><div class="code_line">IQSort4_ver = &nbsp; 100h &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; версия данного модуля (word: старший байт - целая часть, младший - дробная)</div><div class="code_line">&nbsp;</div><div class="code_line">; ПЕРЕД ВКЛЮЧЕНИЕМ ДАННОГО ФАЙЛА В ПРОЕКТ *МОЖНО* ОПРЕДЕЛИТЬ СЛЕДУЮЩИЕ СИМВОЛЫ:</div><div class="code_line">&nbsp;</div><div class="code_line">; inclIQSort4 = 1 - включить процедуру IQSort4 (умная быстрая сортировка) в код, 0 - не включать [по умолчанию 1]</div><div class="code_line">&nbsp;</div><div class="code_line">; inclInsSort4 = 1 - включить процедуру InsSort4 (сортировка вставками) в код, 0 - не включать [по умолчанию 0]</div><div class="code_line">; &nbsp; Если процедура InsSort4 используется процедурой IQSort4, в код включается лишь часть этой процедуры, необходимая для работы IQSort4</div><div class="code_line">&nbsp;</div><div class="code_line">; Sort4SignCmp = 1 - знаковое сравнение, 0 - беззнаковое [по умолчанию 1]</div><div class="code_line">&nbsp;</div><div class="code_line">; Sort4Ascending = 1 - сортировка по возрастанию (от меньшего к большему), 0 - по убыванию (от больего к меньшему)</div><div class="code_line">&nbsp;</div><div class="code_line">; Sort4ElemDWords = кол-во двойных слов с данными (допускаются значения: 1 - только опорное слово, 2 - опорное слово и связанные данные; другие значения породят ошибки)</div><div class="code_line">; &nbsp; [*ЭТОТ СИМВОЛ НЕОБХОДИМО ОПРЕДЕЛИТЬ ОБЯЗАТЕЛЬНО*, значения по умолчанию для него нет!!!]</div><div class="code_line">&nbsp;</div><div class="code_line">; IQSort4InsThrs = порог использования сортировки вставками (когда кол-во элементов меньше указанного здесь значения) [0 = отключено; минимум 2; по умолчанию 16]</div><div class="code_line">; &nbsp; Если кол-во элементов (на первой или последюущей итерации) больше или равно значению IQSort4InsThrs, используется быстрая сортировка, иначе</div><div class="code_line">; &nbsp; используется сортировка вставками - это немного ускоряет процесс (при правильном выборе значения IQSort4InsThrs, например, при значении по умолчанию)</div><div class="code_line">; &nbsp; и уменьшает глубину рекурсии, защищая стек от переполнения</div><div class="code_line">&nbsp;</div><div class="code_line">; IQSort4MaxStk = максимальный размер стека в байтах, который допустимо использовать процедуре IQSort4 (включая call из основного кода) [0 = отключено; минимум 12; по умолчанию 128]</div><div class="code_line">; &nbsp; Каждый уровень вложенности использует 4 байта (2 слова) стека (первый уровень - до 4-х слов, последний может использовать на 1-2 слова больше, итого минимум 10-12 байт),</div><div class="code_line">; &nbsp; т.о. 128 байт позволяют организовать до 30 уровней рекурсии, что достаточно даже для очень больших массивов, особенно когда IQSort4InsThrs &#62; 0</div><div class="code_line">&nbsp;</div><div class="code_line">; При установке значений IQSort4InsThrs = IQSort4MaxStk = 0 процедура IQSort4 превращается в процедуру стандартной быстрой сортировки (т.е. некомбинированную)</div><div class="code_line">&nbsp;</div><div class="code_line">;-----------------------------------------------------------------------------------------------------------------------</div><div class="code_line">&nbsp;</div><div class="code_line">_defdef &nbsp; &nbsp; MACRO &nbsp; Const:REQ, DefVal:REQ</div><div class="code_line">&nbsp;&nbsp;IFDEF &nbsp; &nbsp; Const</div><div class="code_line">&nbsp;&nbsp; &nbsp;_&amp;Const = &nbsp; Const</div><div class="code_line">&nbsp;&nbsp;ELSE</div><div class="code_line">&nbsp;&nbsp; &nbsp;_&amp;Const = &nbsp; DefVal</div><div class="code_line">&nbsp;&nbsp;ENDIF</div><div class="code_line">ENDM</div><div class="code_line">&nbsp;</div><div class="code_line">@386 &nbsp; &nbsp; &nbsp; &nbsp;= &nbsp; ((@Cpu and 8) ne 0) or ((@Cpu and 2Fh) eq 0)</div><div class="code_line">&nbsp;</div><div class="code_line">IF &nbsp;not @386</div><div class="code_line">&nbsp;&nbsp;IFDEF &nbsp; &nbsp; ??Version &nbsp; ; TASM</div><div class="code_line">&nbsp;&nbsp; &nbsp;.ERR &nbsp; &nbsp;&quot;This module requires 386+ instructions enabled !!!&quot;</div><div class="code_line">&nbsp;&nbsp;ELSE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; MASM</div><div class="code_line">&nbsp;&nbsp; &nbsp;.ERR &nbsp; &nbsp;&#60;This module requires 386+ instructions enabled !!!&#62;</div><div class="code_line">&nbsp;&nbsp;ENDIF</div><div class="code_line">ENDIF</div><div class="code_line">&nbsp;</div><div class="code_line">_defdef inclIQSort4, 1</div><div class="code_line">_defdef inclInsSort4, 0</div><div class="code_line">&nbsp;</div><div class="code_line">_defdef Sort4SignCmp, 1</div><div class="code_line">_defdef Sort4Ascending, 1</div><div class="code_line">&nbsp;</div><div class="code_line">IF &nbsp;_Sort4SignCmp</div><div class="code_line">&nbsp;&nbsp;IF &nbsp; &nbsp;_Sort4Ascending</div><div class="code_line">&nbsp;&nbsp; &nbsp;srt?jl &nbsp;EQU &#60;jl&#62;</div><div class="code_line">&nbsp;&nbsp; &nbsp;srt?jg &nbsp;EQU &#60;jg&#62;</div><div class="code_line">&nbsp;&nbsp;ELSE</div><div class="code_line">&nbsp;&nbsp; &nbsp;srt?jl &nbsp;EQU &#60;jg&#62;</div><div class="code_line">&nbsp;&nbsp; &nbsp;srt?jg &nbsp;EQU &#60;jl&#62;</div><div class="code_line">&nbsp;&nbsp;ENDIF</div><div class="code_line">ELSE</div><div class="code_line">&nbsp;&nbsp;IF &nbsp; &nbsp;_Sort4Ascending</div><div class="code_line">&nbsp;&nbsp; &nbsp;srt?jl &nbsp;EQU &#60;jb&#62;</div><div class="code_line">&nbsp;&nbsp; &nbsp;srt?jg &nbsp;EQU &#60;ja&#62;</div><div class="code_line">&nbsp;&nbsp;ELSE</div><div class="code_line">&nbsp;&nbsp; &nbsp;srt?jl &nbsp;EQU &#60;ja&#62;</div><div class="code_line">&nbsp;&nbsp; &nbsp;srt?jg &nbsp;EQU &#60;jb&#62;</div><div class="code_line">&nbsp;&nbsp;ENDIF</div><div class="code_line">ENDIF</div><div class="code_line">&nbsp;</div><div class="code_line">_Sort4ElemDWords = &nbsp;Sort4ElemDWords</div><div class="code_line">IF &nbsp;(_Sort4ElemDWords+1)/2 ne 1</div><div class="code_line">&nbsp;&nbsp;IFDEF &nbsp; &nbsp; ??Version &nbsp; ; TASM</div><div class="code_line">&nbsp;&nbsp; &nbsp;.ERR &nbsp; &nbsp;&quot;Wrong value of Sort4ElemDWords, it must be = 1 or 2 !!!&quot;</div><div class="code_line">&nbsp;&nbsp;ELSE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; MASM</div><div class="code_line">&nbsp;&nbsp; &nbsp;.ERR &nbsp; &nbsp;&#60;Wrong value of Sort4ElemDWords, it must be = 1 or 2 !!!&#62;</div><div class="code_line">&nbsp;&nbsp;ENDIF</div><div class="code_line">ENDIF</div><div class="code_line">_Sort4ElemSize &nbsp;= &nbsp; _Sort4ElemDWords*4 &nbsp;; размер одного элемента массива (4 или 8 байт)</div><div class="code_line">&nbsp;</div><div class="code_line">_defdef IQSort4InsThrs, 16</div><div class="code_line">_defdef IQSort4MaxStk, 128</div><div class="code_line">&nbsp;</div><div class="code_line">IF &nbsp;_IQSort4InsThrs and _IQSort4InsThrs lt 2</div><div class="code_line">&nbsp;&nbsp;_IQSort4InsThrs = 0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; если IQSort4InsThrs &#60; 2, принимаем значение 0</div><div class="code_line">ENDIF</div><div class="code_line">&nbsp;</div><div class="code_line">IF &nbsp;_IQSort4MaxStk and _IQSort4MaxStk lt 10+(_Sort4ElemDWords-1)*2</div><div class="code_line">&nbsp;&nbsp;_IQSort4MaxStk = &nbsp;0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; если IQSort4MaxStk &#60; 10 + 2 (если Sort4ElemDWords = 2), принимаем значение 0</div><div class="code_line">ENDIF</div><div class="code_line">&nbsp;</div><div class="code_line">;-- IQSort4: Умная БЫСТРАЯ СОРТИРОВКА массива (комбинированным методом) ------------------------------------------------</div><div class="code_line">; &#62; Входные данные: DS:DX = адрес массива, CX = кол-во элементов массива (знаковое значение)</div><div class="code_line">; &#62; Результат: отсортированный массив (по тому же адресу)</div><div class="code_line">; Если элементы массива содержат по 2 значения, т.е. Sort4ElemDWords = 2 (размер элемента массива = _Sort4ElemSize = 8 байтам), то:</div><div class="code_line">; &nbsp; * первое двойное слово содержит опорное значение (по которому происходит сравнение),</div><div class="code_line">; &nbsp; * второе двойное слово - связанные с элементом данные (обычно это указатель на данные);</div><div class="code_line">; &nbsp; &nbsp; при сортировке связанные данные переносятся вместе с опорными значениями</div><div class="code_line">; Если кол-во элементов (на первой или последующей итерации) больше или равно значению IQSort4InsThrs, используется быстрая сортировка,</div><div class="code_line">; &nbsp; иначе используется сортировка вставками [только если IQSort4InsThrs &#60;&#62; 0]</div><div class="code_line">; Сортировка вставками также используется, если для следующего уровня рекурсии потребуется более IQSort4MaxStk байт стека в общем сложности</div><div class="code_line">; &nbsp; [только если IQSort4MaxStk &#60;&#62; 0]</div><div class="code_line">; Процедура изменяет регистры EAX, EBX, CX, DX, SI, DI, старшее слово EBP; сохраняет BP и сегментные регистры</div><div class="code_line">IF &nbsp;_inclIQSort4</div><div class="code_line">IQSort4 &nbsp; &nbsp; PROC</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;dec cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jle @@exit &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; выходим, если кол-во элементов &#60;= 1</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;bp</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xor bp,bp &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; BP = кол-во рекурсий</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shl cx,_Sort4ElemDWords+1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add cx,dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; CX = адрес последнего элемента</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; Главная процедура быстрой сортировки</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DX = адрес первого элемента, CX = адрес последнего элемента, CX &#62; DX, BP = уровень рекурсии</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@IQSort4Main:</div><div class="code_line">IF &nbsp;_IQSort4InsThrs</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov ax,cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sub ax,dx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shr ax,_Sort4ElemDWords+1 &nbsp; ; AX = кол-во элементов минус 1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp ax,_IQSort4InsThrs-1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jb &nbsp;@@callins &nbsp; &nbsp; &nbsp; ; если кол-во элементов меньше порогового значения, используем сортировку вставками</div><div class="code_line">ENDIF</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov si,dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; I (SI) := L (DX)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@repeat1: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; repeat</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov di,cx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; J (DI) := R (CX)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov bx,cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sub bx,dx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shr bx,1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;and bx,-_Sort4ElemSize</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add bx,dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; P (BX) := (L + R) / 2</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov eax,[bx] &nbsp; &nbsp; &nbsp; &nbsp;;; T (EAX) := [P]</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@repeat2 = @@cmpI &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; repeat</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; SI = I, EAX = T, DI = J, DX = L, CX = R</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jmp @@cmpI</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@addI: add si,_Sort4ElemSize &nbsp; ;; Inc(I)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@cmpI: cmp [si],eax &nbsp; &nbsp; &nbsp; &nbsp;;; while [I] &#60; T</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;srt?jl &nbsp;@@addI</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jmp @@cmpJ</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@subJ: sub di,_Sort4ElemSize &nbsp; ;; Dec(J)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@cmpJ: cmp [di],eax &nbsp; &nbsp; &nbsp; &nbsp;;; while [J] &#62; T</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;srt?jg &nbsp;@@subJ</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp si,di</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jnbe &nbsp; &nbsp;@@noswap &nbsp; &nbsp; &nbsp; &nbsp;;; if I &#60;= J then</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov ebx,[si] &nbsp; &nbsp; &nbsp; &nbsp;;; &nbsp; Swap [I],[J]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xchg &nbsp; &nbsp;[di],ebx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov [si],ebx</div><div class="code_line">IF &nbsp;_Sort4ElemDWords gt 1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov ebx,[si+4]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xchg &nbsp; &nbsp;[di+4],ebx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov [si+4],ebx</div><div class="code_line">ENDIF</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add si,_Sort4ElemSize &nbsp; ;; Inc(I)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sub di,_Sort4ElemSize &nbsp; ;; Dec(J)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@noswap:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp si,di</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jna @@repeat2 &nbsp; &nbsp; &nbsp; ;; until I &#62; J</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp dx,di</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jnb @@norecurs &nbsp; &nbsp; &nbsp;;; if L &#60; J then</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;si &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; сохраняем R и I</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov cx,di</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DX = L, CX = J</div><div class="code_line">IF &nbsp;_IQSort4MaxStk</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp bp,(_IQSort4MaxStk-(10+(_Sort4ElemDWords-1)*2))/4 &nbsp; ; 6 слов - это адрес возврата в вызываемую программу +</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; bp + cx + si + адрес возврата из InsSort4 + bp (если Sort4ElemDWords = 2)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jae @@callins2 &nbsp; &nbsp; &nbsp;; если число рекурсий достигло максимума, идём на вызов сортировки вставками: InsSort4(L, J)</div><div class="code_line">ENDIF</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;inc bp &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; иначе увеличиваем глубину рекурсии и идём на рекурсию</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jmp @@IQSort4Main &nbsp; &nbsp; &nbsp; ;; &nbsp; IQSort4(L, J); вызов делаем через jmp для экономии стека :)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@recursret:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;pop si</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;pop cx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; восстанавливаем I и R</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@norecurs:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov dx,si &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; L := I</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp si,cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jnae &nbsp; &nbsp;@@repeat1 &nbsp; &nbsp; &nbsp; ;; until I &#62;= R</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@finish:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;dec bp &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; уменьшаем глубину рекурсии</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jns @@recursret &nbsp; &nbsp; ; прыгаем, если это не первый (корневой) уровень рекурсии</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;pop bp</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@exit: ret</div><div class="code_line">IF &nbsp;_IQSort4InsThrs</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@callins:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;offset @@finish &nbsp; &nbsp; ; адрес возврата</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jmp @IQInsSort4 &nbsp; &nbsp; ; вместо call + jmp @@finish делаем push + jmp</div><div class="code_line">ENDIF</div><div class="code_line">IF &nbsp;_IQSort4MaxStk</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@callins2:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;offset @@recursret &nbsp;; адрес возврата</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jmp @IQInsSort4 &nbsp; &nbsp; ; вместо call + jmp @@recursret делаем push + jmp</div><div class="code_line">ENDIF</div><div class="code_line">IQSort4 &nbsp; &nbsp; ENDP</div><div class="code_line">ENDIF ; _inclIQSort4</div><div class="code_line">&nbsp;</div><div class="code_line">;-- InsSort4: СОРТИРОВКА массива ВСТАВКАМИ -----------------------------------------------------------------------------</div><div class="code_line">; &#62; Входные данные: DS:DX = адрес массива, CX = кол-во элементов массива (знаковое значение)</div><div class="code_line">; &#62; Результат: отсортированный массив (по тому же адресу)</div><div class="code_line">; Если элементы массива содержат по 2 значения, т.е. Sort4ElemDWords = 2 (размер элемента массива = _Sort4ElemSize = 8 байтам), то:</div><div class="code_line">; &nbsp; * первое двойное слово содержит опорное значение (по которому происходит сравнение),</div><div class="code_line">; &nbsp; * второе двойное слово - связанные с элементом данные (обычно это указатель на данные);</div><div class="code_line">; &nbsp; &nbsp; при сортировке связанные данные переносятся вместе с опорными значениями</div><div class="code_line">; Процедура изменяет регистры EAX, EBX, SI, DI, старшее слово EBP; сохраняет CX, DX, BP и сегментные регистры</div><div class="code_line">IF &nbsp;_inclInsSort4</div><div class="code_line">InsSort4 &nbsp; &nbsp;PROC</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;dec cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jle @@exit &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; выходим, если кол-во элементов &#60;= 1</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shl cx,_Sort4ElemDWords+1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add cx,dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; CX = адрес последнего элемента</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; Главная процедура сортировки вставками</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DX = адрес первого элемента, CX = адрес последнего элемента, CX &#62; DX</div><div class="code_line">IFDEF &nbsp; &nbsp; &nbsp; ??Version &nbsp; ; TASM</div><div class="code_line">&nbsp;&nbsp;@IQInsSort4:</div><div class="code_line">ELSE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; MASM</div><div class="code_line">&nbsp;&nbsp;@IQInsSort4::</div><div class="code_line">ENDIF</div><div class="code_line">ELSEIF &nbsp;_IQSort4InsThrs or _IQSort4MaxStk</div><div class="code_line">@IQInsSort4 PROC</div><div class="code_line">ENDIF</div><div class="code_line">IF &nbsp;_inclInsSort4 or _IQSort4InsThrs or _IQSort4MaxStk</div><div class="code_line">IF &nbsp;_Sort4ElemDWords gt 1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;bp</div><div class="code_line">ENDIF</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov di,dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; J (DI) := L - адрес первого элемента</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@next: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; for J (DI) := L+1 (CX) to R (DX) do</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add di,_Sort4ElemSize &nbsp; ; J++ (DI) - адрес следующего проверяемого элемента (в основном цикле)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov ebx,[di] &nbsp; &nbsp; &nbsp; &nbsp;;; T (EBP:EBX|EBX) := [J]</div><div class="code_line">IF &nbsp;_Sort4ElemDWords gt 1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov ebp,[di+4]</div><div class="code_line">ENDIF</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov si,di &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; I+1 (SI) := DI - адрес элемента, следующего за сравниваемым (во внутреннем цикле)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@loop: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; repeat</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov eax,[si-_Sort4ElemSize]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp eax,ebx &nbsp; &nbsp; &nbsp; &nbsp; ;; if [I] &#62; T then</div><div class="code_line">% &nbsp; &nbsp; &nbsp; srt?jl&amp;e @@break &nbsp; &nbsp; &nbsp; &nbsp;; прыгаем, если [I] &#60;= T</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov [si],eax &nbsp; &nbsp; &nbsp; &nbsp;;; &nbsp;[I+1] := [I] else Break</div><div class="code_line">IF &nbsp;_Sort4ElemDWords gt 1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov eax,[si-_Sort4ElemSize+4]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov [si+4],eax</div><div class="code_line">ENDIF</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sub si,_Sort4ElemSize &nbsp; ;; Dec(I)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp si,dx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jnbe &nbsp; &nbsp;@@loop &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; until I &#60; L (I+1 &#60;= L)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@break:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov [si],ebx &nbsp; &nbsp; &nbsp; &nbsp;;; [I+1] := T</div><div class="code_line">IF &nbsp;_Sort4ElemDWords gt 1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov [si+4],ebp</div><div class="code_line">ENDIF</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp di,cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jnae &nbsp; &nbsp;@@next &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; следующий элемент массива ;; end for</div><div class="code_line">IF &nbsp;_Sort4ElemDWords gt 1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;pop bp</div><div class="code_line">ENDIF</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@exit: ret</div><div class="code_line">ENDIF ; _inclInsSort4 or _IQSort4InsThrs or _IQSort4MaxStk</div><div class="code_line">IF &nbsp;_inclInsSort4</div><div class="code_line">InsSort4 &nbsp; &nbsp;ENDP</div><div class="code_line">ELSEIF &nbsp;_IQSort4InsThrs or _IQSort4MaxStk</div><div class="code_line">@IQInsSort4 ENDP</div><div class="code_line">ENDIF</div></ol></div></div></div></div><br>
Коллекция модулей, работающая с 32-битными элементами, требует включения поддержки инструкций процессора 386+.<br>
<br>
Архив с модулями также прикрепляю к сообщению. В нём множество вариантов модулей на любой вкус и цвет, поэтому не стоит пугаться такому обилию директив условной компиляции – это самый насыщенный такими декорациями модуль.<br>
<br>
В каждом из архивов есть файл <strong class='tag-b'>ReadMe.txt</strong> с информацией о коллекции модулей сортировки.<br>
К тому же, сами исходники снабжены подробным описанием каждой настройки и процедур.<br>
В архивах также имеются папки <strong class='tag-b'>examples</strong> с тестовыми программами, использующими данные модули.<br>
<br>
Пользуйтесь&#33; ;)<br>
<br>
<span class="tag-color" data-value="c0c0c0" style="color: #c0c0c0">asm7x</span><br>
<span class="b-attach" data-size="83010" data-hits="234" data-attach-id="57131" data-attach-post-id="3749067">
			<span class="b-attach__title"></span><a class='b-attach-link' href='https://forum.sources.ru/index.php?act=Attach&amp;type=post&amp;id=3749067&amp;attach_id=57131' title='Скачать файл' target='_blank'>IQSort_16bit_DWORD_1.00.zip</a> (, : 234)
		</span>]]></description>
        <author>Jin X</author>
        <category>Assembler FAQ</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=411583&amp;view=findpost&amp;p=3749026</guid>
        <pubDate>Sat, 11 Nov 2017 11:09:56 +0000</pubDate>
        <title>Умная быстрая сортировка</title>
        <link>https://forum.sources.ru/index.php?showtopic=411583&amp;view=findpost&amp;p=3749026</link>
        <description><![CDATA[Jin X: <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>
Заморочился и сделал не просто быструю сортировку, но ещё и <strong class='tag-b'>умную</strong> :)<br>
<br>
Алгоритм работы <strong class='tag-b'>умной</strong> сортировки заключается в следующем.<br>
По умолчанию используется быстрая сортировка, однако если кол-во элементов массива на первой или последующей итерации меньше некоего порогового значения (по умолчанию 16), либо если для следующего уровня рекурсии в общей сложности потребуется слишком много стека (по умолчанию 128 байт), используется сортировка вставками, в которой рекурсия отсутствует. Это немного ускоряет процесс (мои замеры показывают прирост до 10% для случайных данных) и <strong class='tag-b'>защищает стек от переполнения</strong>.<br>
<br>
Иногда при сортировке массивов необходимо <strong class='tag-b'>упорядочить не только числовые элементы, но и соответствующие им данные</strong>. Например, имеется список людей с указанием года рождения и фамилии для каждого из них. Год рождения записан в виде числового значения, а фамилия – в виде указателя на строку. Таким образом, каждый элемент массива будет содержать 2 записи размером WORD каждая:<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;+0 &nbsp;WORD &nbsp;Год рождения</div><div class="code_line">&nbsp;&nbsp;+2 &nbsp;WORD &nbsp;Адрес (смещение) строки с фамилией</div></ol></div></div></div></div><br>
При сортировке такого массива <em class='tag-i'>по году рождения</em> необходимо сравнивать только первые элементы (опорные значения), однако перемещать (менять местами) и первые, и вторые.<br>
Если массив должен содержать более 2-х элементов, все элементы, кроме опорного (например, фамилию, имя, адрес и телефон) необходимо записать в отдельную область памяти, а во втором поле указать ссылку на эту структуру (которая не ограничена в размере и может также содержать ссылки на каждый из элементов).<br>
<br>
Мои процедуры позволяют выполнить как сортировку одиночных (числовых) элементов, так и двойных (числовых элементов с привязанными данными).<br>
Некоторые файлы прикреплённого архива содержат универсальные процедуры (размер данных, знаковость числовых значений и направление сортировки, а также другие параметры задаются в исходнике программы <em class='tag-i'>перед</em> подключением файла), другие – с заданными параметрами, некоторые из которых можно менять, изменяя сам исходник.<br>
<br>
Процедура быстрой сортировки оптимизирована таким образом, что каждый последующий уровень рекурсии не требует записи в стек адреса возврата (поскольку рекурсивный вызов происходит из одной и той же точки в процедуре), в стек записываются лишь локальные данные, минимально необходимые для последующей работы (2 слово = 4 байта).<br>
Это довольно весомый плюс в сравнении со многими реализациями быстрой сортировки, в которых каждая рекурсия съедает до 3-6 слов (6-12 байт) для каждого уровня рекурсии&#33;<br>
<br>
Модуль <span class="tag-color tag-color-named" data-value="red" style="color: red"><strong class='tag-b'>умной быстрой сортировки</strong></span> для массивов с <em class='tag-i'><span class='tag-u'>одиночными</span></em> элементами <strong class='tag-b'>IQSortS1.inc</strong>:<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">;##################################################</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &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;[ Asm7x.List ][ IQSortS1.inc ] &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;-= Smart Quick Sort =- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; (for single element arrays) &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Умная быстрая сортировка &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ##</div><div class="code_line">;## &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [ v1.00 :: 11.11.2017 ] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MASM/TASM (16 bit) &nbsp; &nbsp; &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; (c) 2017 by Jin X (jin.x@sources.ru) &nbsp; &nbsp; ##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; http://xk7.ru/p/a/i &nbsp; &nbsp; &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;##################################################</div><div class="code_line">&nbsp;</div><div class="code_line">IFDEF &nbsp; &nbsp; &nbsp; ??Version &nbsp; ; TASM</div><div class="code_line">&nbsp;&nbsp;LOCALS</div><div class="code_line">ENDIF</div><div class="code_line">&nbsp;</div><div class="code_line">IQSortS1_ver &nbsp; &nbsp;= &nbsp; 100h &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; версия данного модуля (word: старший байт - целая часть, младший - дробная)</div><div class="code_line">&nbsp;</div><div class="code_line">; !!! В данном модуле используется ЗНАКОВОЕ сравнение значений и сортировка по ВОЗРАСТАНИЮ (от меньшего к большему)</div><div class="code_line">; !!! Для замены на БЕЗзнаковое сравнение или сортировку по УБЫВАНИЮ необходимо изменить соответствующие инструкции, помеченные в комментариях символами ***</div><div class="code_line">&nbsp;</div><div class="code_line">; IQSortInsThrs = порог использования сортировки вставками (когда кол-во элементов меньше указанного здесь значения) [минимум 2; по умолчанию 16]</div><div class="code_line">; &nbsp; Если кол-во элементов (на первой или последующей итерации) больше или равно значению IQSortInsThrs, используется быстрая сортировка, иначе</div><div class="code_line">; &nbsp; используется сортировка вставками - это немного ускоряет процесс (при правильном выборе значения IQSortInsThrs, например, при значении по умолчанию)</div><div class="code_line">; &nbsp; и уменьшает глубину рекурсии, защищая стек от переполнения</div><div class="code_line">IQSortInsThrs &nbsp; = &nbsp; 16</div><div class="code_line">&nbsp;</div><div class="code_line">; IQSortMaxStk = максимальный размер стека в байтах, который допустимо использовать процедуре IQSort (включая call из основного кода) [минимум 10; по умолчанию 128]</div><div class="code_line">; &nbsp; Каждый уровень вложенности использует 4 байта (2 слова) стека (первый уровень - до 4-х слов, последний может использовать на 1 слово больше, итого минимум 10 байт),</div><div class="code_line">; &nbsp; т.о. 128 байт позволяют организовать до 30 уровней рекурсии, что достаточно даже для очень больших массивов</div><div class="code_line">IQSortMaxStk &nbsp; &nbsp;= &nbsp; 128</div><div class="code_line">&nbsp;</div><div class="code_line">;-----------------------------------------------------------------------------------------------------------------------</div><div class="code_line">&nbsp;</div><div class="code_line">;-- IQSort: Умная БЫСТРАЯ СОРТИРОВКА массива (комбинированным методом) -------------------------------------------------</div><div class="code_line">; &#62; Входные данные: DS:DX = адрес массива, CX = кол-во элементов массива (знаковое значение)</div><div class="code_line">; &#62; Результат: отсортированный массив (по тому же адресу)</div><div class="code_line">; Элементы массива содержат по 1 значению типа WORD, по которому происходит сравнение и сортировка</div><div class="code_line">; Если кол-во элементов (на первой или последующей итерации) больше или равно значению IQSortInsThrs, используется быстрая сортировка,</div><div class="code_line">; &nbsp; иначе используется сортировка вставками</div><div class="code_line">; Сортировка вставками также используется, если для следующего уровня рекурсии потребуется более IQSortMaxStk байт стека в общем сложности</div><div class="code_line">; Процедура изменяет регистры AX, BX, CX, DX, SI, DI, сохраняет BP и сегментные регистры</div><div class="code_line">IQSort &nbsp; &nbsp; &nbsp;PROC</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;dec cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jle @@exit &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; выходим, если кол-во элементов &#60;= 1</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;bp</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xor bp,bp &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; BP = кол-во рекурсий</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shl cx,1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add cx,dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; CX = адрес последнего элемента</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; Главная процедура быстрой сортировки</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DX = адрес первого элемента, CX = адрес последнего элемента, CX &#62; DX, BP = уровень рекурсии</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@IQSortMain:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov ax,cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sub ax,dx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shr ax,1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; AX = кол-во элементов минус 1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp ax,IQSortInsThrs-1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jb &nbsp;@@callins &nbsp; &nbsp; &nbsp; ; если кол-во элементов меньше порогового значения, используем сортировку вставками</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov si,dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; I (SI) := L (DX)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@repeat1: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; repeat</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov di,cx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; J (DI) := R (CX)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov bx,cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sub bx,dx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shr bx,1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;and bx,-2</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add bx,dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; P (BX) := (L + R) / 2</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov ax,[bx] &nbsp; &nbsp; &nbsp; &nbsp; ;; T (AX) := [P]</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@repeat2 = @@cmpI &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; repeat</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; SI = I, AX = T, DI = J, DX = L, CX = R</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jmp @@cmpI</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@addI: add si,2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; Inc(I)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@cmpI: cmp [si],ax &nbsp; &nbsp; &nbsp; &nbsp; ;; while [I] &#60; T</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jl &nbsp;@@addI &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; {*** сортировка по возрастанию: jl - знаковое сравнение, jb - беззнаковое; по убыванию: jg - знаковое, ja - беззнаковое}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jmp @@cmpJ</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@subJ: sub di,2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; Dec(J)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@cmpJ: cmp [di],ax &nbsp; &nbsp; &nbsp; &nbsp; ;; while [J] &#62; T</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jg &nbsp;@@subJ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; {*** сортировка по возрастанию: jg - знаковое сравнение, ja - беззнаковое; по убыванию: jl - знаковое, jb - беззнаковое}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp si,di</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jnbe &nbsp; &nbsp;@@noswap &nbsp; &nbsp; &nbsp; &nbsp;;; if I &#60;= J then</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov bx,[si] &nbsp; &nbsp; &nbsp; &nbsp; ;; &nbsp; Swap [I],[J]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xchg &nbsp; &nbsp;[di],bx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov [si],bx</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add si,2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; Inc(I)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sub di,2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; Dec(J)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@noswap:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp si,di</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jna @@repeat2 &nbsp; &nbsp; &nbsp; ;; until I &#62; J</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp dx,di</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jnb @@norecurs &nbsp; &nbsp; &nbsp;;; if L &#60; J then</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;si &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; сохраняем R и I</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov cx,di</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DX = L, CX = J</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp bp,(IQSortMaxStk-10)/4 &nbsp;; 5 слов - это адрес возврата в вызываемую программу + bp + cx + si + адрес возврата из InsSort</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jae @@callins2 &nbsp; &nbsp; &nbsp;; если число рекурсий достигло максимума, идём на вызов сортировки вставками: InsSort(L, J)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;inc bp &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; иначе увеличиваем глубину рекурсии и идём на рекурсию</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jmp @@IQSortMain &nbsp; &nbsp; &nbsp; &nbsp;;; &nbsp; IQSort(L, J); вызов делаем через jmp для экономии стека :)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@recursret:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;pop si</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;pop cx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; восстанавливаем I и R</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@norecurs:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov dx,si &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; L := I</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp si,cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jnae &nbsp; &nbsp;@@repeat1 &nbsp; &nbsp; &nbsp; ;; until I &#62;= R</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@finish:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;dec bp &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; уменьшаем глубину рекурсии</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jns @@recursret &nbsp; &nbsp; ; прыгаем, если это не первый (корневой) уровень рекурсии</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;pop bp</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@exit: ret</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@callins:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;offset @@finish &nbsp; &nbsp; ; адрес возврата</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jmp @IQInsSort &nbsp; &nbsp; &nbsp;; вместо call + jmp @@finish делаем push + jmp</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@callins2:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;offset @@recursret &nbsp;; адрес возврата</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jmp @IQInsSort &nbsp; &nbsp; &nbsp;; вместо call + jmp @@recursret делаем push + jmp</div><div class="code_line">IQSort &nbsp; &nbsp; &nbsp;ENDP</div><div class="code_line">&nbsp;</div><div class="code_line">;-- InsSort: СОРТИРОВКА массива ВСТАВКАМИ ------------------------------------------------------------------------------</div><div class="code_line">; &#62; Входные данные: DS:DX = адрес массива, CX = кол-во элементов массива (знаковое значение)</div><div class="code_line">; &#62; Результат: отсортированный массив (по тому же адресу)</div><div class="code_line">; Элементы массива содержат по 1 значению типа WORD, по которому происходит сравнение и сортировка</div><div class="code_line">; Процедура изменяет регистры AX, BX, SI, DI, сохраняет CX, DX, BP и сегментные регистры</div><div class="code_line">InsSort &nbsp; &nbsp; PROC</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;dec cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jle @@exit &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; выходим, если кол-во элементов &#60;= 1</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shl cx,1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add cx,dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; CX = адрес последнего элемента</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; Главная процедура сортировки вставками</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DX = адрес первого элемента, CX = адрес последнего элемента, CX &#62; DX</div><div class="code_line">IFDEF &nbsp; &nbsp; &nbsp; ??Version &nbsp; ; TASM</div><div class="code_line">&nbsp;&nbsp;@IQInsSort:</div><div class="code_line">ELSE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; MASM</div><div class="code_line">&nbsp;&nbsp;@IQInsSort::</div><div class="code_line">ENDIF</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov di,dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; J (DI) := L - адрес первого элемента</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@next: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; for J (DI) := L+1 (CX) to R (DX) do</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add di,2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; J++ (DI) - адрес следующего проверяемого элемента (в основном цикле)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov bx,[di] &nbsp; &nbsp; &nbsp; &nbsp; ;; T (BX) := [J]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov si,di &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; I+1 (SI) := DI - адрес элемента, следующего за сравниваемым (во внутреннем цикле)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@loop: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; repeat</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov ax,[si-2]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp ax,bx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; if [I] &#62; T then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jle @@break &nbsp; &nbsp; &nbsp; &nbsp; ; прыгаем, если [I] &#60;= T {*** сортировка по возрастанию: jle - знаковое сравнение, jbe - беззнаковое; по убыванию: jge - знаковое, jae - беззнаковое}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov [si],ax &nbsp; &nbsp; &nbsp; &nbsp; ;; &nbsp;[I+1] := [I] else Break</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sub si,2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; Dec(I)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp si,dx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jnbe &nbsp; &nbsp;@@loop &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; until I &#60; L (I+1 &#60;= L)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@break:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov [si],bx &nbsp; &nbsp; &nbsp; &nbsp; ;; [I+1] := T</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp di,cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jnae &nbsp; &nbsp;@@next &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; следующий элемент массива ;; end for</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@exit: ret</div><div class="code_line">InsSort &nbsp; &nbsp; ENDP</div></ol></div></div></div></div><br>
Модуль <span class="tag-color tag-color-named" data-value="red" style="color: red"><strong class='tag-b'>умной быстрой сортировки</strong></span> для массивов с <em class='tag-i'><span class='tag-u'>двойными</span></em> элементами <strong class='tag-b'>IQSortS2.inc</strong>:<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">;##################################################</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &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;[ Asm7x.List ][ IQSortS2.inc ] &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;-= Smart Quick Sort =- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; (for double element arrays) &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Умная быстрая сортировка &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ##</div><div class="code_line">;## &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [ v1.00 :: 11.11.2017 ] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MASM/TASM (16 bit) &nbsp; &nbsp; &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; (c) 2017 by Jin X (jin.x@sources.ru) &nbsp; &nbsp; ##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; http://xk7.ru/p/a/i &nbsp; &nbsp; &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;##################################################</div><div class="code_line">&nbsp;</div><div class="code_line">IFDEF &nbsp; &nbsp; &nbsp; ??Version &nbsp; ; TASM</div><div class="code_line">&nbsp;&nbsp;LOCALS</div><div class="code_line">ENDIF</div><div class="code_line">&nbsp;</div><div class="code_line">IQSortS2_ver &nbsp; &nbsp;= &nbsp; 100h &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; версия данного модуля (word: старший байт - целая часть, младший - дробная)</div><div class="code_line">&nbsp;</div><div class="code_line">; !!! В данном модуле используется ЗНАКОВОЕ сравнение значений и сортировка по ВОЗРАСТАНИЮ (от меньшего к большему)</div><div class="code_line">; !!! Для замены на БЕЗзнаковое сравнение или сортировку по УБЫВАНИЮ необходимо изменить соответствующие инструкции, помеченные в комментариях символами ***</div><div class="code_line">&nbsp;</div><div class="code_line">; IQSortInsThrs = порог использования сортировки вставками (когда кол-во элементов меньше указанного здесь значения) [минимум 2; по умолчанию 16]</div><div class="code_line">; &nbsp; Если кол-во элементов (на первой или последующей итерации) больше или равно значению IQSortInsThrs, используется быстрая сортировка, иначе</div><div class="code_line">; &nbsp; используется сортировка вставками - это немного ускоряет процесс (при правильном выборе значения IQSortInsThrs, например, при значении по умолчанию)</div><div class="code_line">; &nbsp; и уменьшает глубину рекурсии, защищая стек от переполнения</div><div class="code_line">IQSortInsThrs &nbsp; = &nbsp; 16</div><div class="code_line">&nbsp;</div><div class="code_line">; IQSortMaxStk = максимальный размер стека в байтах, который допустимо использовать процедуре IQSortDE (включая call из основного кода) [минимум 12; по умолчанию 128]</div><div class="code_line">; &nbsp; Каждый уровень вложенности использует 4 байта (2 слова) стека (первый уровень - до 4-х слов, последний может использовать на 2 слова больше, итого минимум 12 байт),</div><div class="code_line">; &nbsp; т.о. 128 байт позволяют организовать до 30 уровней рекурсии, что достаточно даже для очень больших массивов</div><div class="code_line">IQSortMaxStk &nbsp; &nbsp;= &nbsp; 128</div><div class="code_line">&nbsp;</div><div class="code_line">;-----------------------------------------------------------------------------------------------------------------------</div><div class="code_line">&nbsp;</div><div class="code_line">;-- IQSortDE: Умная БЫСТРАЯ СОРТИРОВКА массива (комбинированным методом) -----------------------------------------------</div><div class="code_line">; &#62; Входные данные: DS:DX = адрес массива, CX = кол-во элементов массива (знаковое значение)</div><div class="code_line">; &#62; Результат: отсортированный массив (по тому же адресу)</div><div class="code_line">; Элементы массива содержат по 2 значения типа WORD:</div><div class="code_line">; &nbsp; * первое слово содержит опорное значение (по которому происходит сравнение),</div><div class="code_line">; &nbsp; * второе слово - связанные с элементом данные (обычно это указатель на данные);</div><div class="code_line">; &nbsp; &nbsp; при сортировке связанные данные переносятся вместе с опорными значениями</div><div class="code_line">; Если кол-во элементов (на первой или последующей итерации) больше или равно значению IQSortInsThrs, используется быстрая сортировка,</div><div class="code_line">; &nbsp; иначе используется сортировка вставками</div><div class="code_line">; Сортировка вставками также используется, если для следующего уровня рекурсии потребуется более IQSortMaxStk байт стека в общем сложности</div><div class="code_line">; Процедура изменяет регистры AX, BX, CX, DX, SI, DI, сохраняет BP и сегментные регистры</div><div class="code_line">IQSortDE &nbsp; &nbsp;PROC</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;dec cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jle @@exit &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; выходим, если кол-во элементов &#60;= 1</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;bp</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xor bp,bp &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; BP = кол-во рекурсий</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shl cx,2</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add cx,dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; CX = адрес последнего элемента</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; Главная процедура быстрой сортировки</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DX = адрес первого элемента, CX = адрес последнего элемента, CX &#62; DX, BP = уровень рекурсии</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@IQSortDEMain:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov ax,cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sub ax,dx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shr ax,2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; AX = кол-во элементов минус 1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp ax,IQSortInsThrs-1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jb &nbsp;@@callins &nbsp; &nbsp; &nbsp; ; если кол-во элементов меньше порогового значения, используем сортировку вставками</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov si,dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; I (SI) := L (DX)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@repeat1: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; repeat</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov di,cx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; J (DI) := R (CX)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov bx,cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sub bx,dx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shr bx,1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;and bx,-4</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add bx,dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; P (BX) := (L + R) / 2</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov ax,[bx] &nbsp; &nbsp; &nbsp; &nbsp; ;; T (AX) := [P]</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@repeat2 = @@cmpI &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; repeat</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; SI = I, AX = T, DI = J, DX = L, CX = R</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jmp @@cmpI</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@addI: add si,4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; Inc(I)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@cmpI: cmp [si],ax &nbsp; &nbsp; &nbsp; &nbsp; ;; while [I] &#60; T</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jl &nbsp;@@addI &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; {*** сортировка по возрастанию: jl - знаковое сравнение, jb - беззнаковое; по убыванию: jg - знаковое, ja - беззнаковое}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jmp @@cmpJ</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@subJ: sub di,4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; Dec(J)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@cmpJ: cmp [di],ax &nbsp; &nbsp; &nbsp; &nbsp; ;; while [J] &#62; T</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jg &nbsp;@@subJ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; {*** сортировка по возрастанию: jg - знаковое сравнение, ja - беззнаковое; по убыванию: jl - знаковое, jb - беззнаковое}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp si,di</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jnbe &nbsp; &nbsp;@@noswap &nbsp; &nbsp; &nbsp; &nbsp;;; if I &#60;= J then</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov bx,[si] &nbsp; &nbsp; &nbsp; &nbsp; ;; &nbsp; Swap [I],[J]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xchg &nbsp; &nbsp;[di],bx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov [si],bx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov bx,[si+2]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xchg &nbsp; &nbsp;[di+2],bx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov [si+2],bx</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add si,4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; Inc(I)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sub di,4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; Dec(J)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@noswap:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp si,di</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jna @@repeat2 &nbsp; &nbsp; &nbsp; ;; until I &#62; J</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp dx,di</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jnb @@norecurs &nbsp; &nbsp; &nbsp;;; if L &#60; J then</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;si &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; сохраняем R и I</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov cx,di</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DX = L, CX = J</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp bp,(IQSortMaxStk-12)/4 &nbsp;; 6 слов - это адрес возврата в вызываемую программу + bp + cx + si + адрес возврата из InsSortDE + bp</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jae @@callins2 &nbsp; &nbsp; &nbsp;; если число рекурсий достигло максимума, идём на вызов сортировки вставками: InsSortDE(L, J)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;inc bp &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; иначе увеличиваем глубину рекурсии и идём на рекурсию</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jmp @@IQSortDEMain &nbsp; &nbsp; &nbsp;;; &nbsp; IQSortDE(L, J); вызов делаем через jmp для экономии стека :)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@recursret:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;pop si</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;pop cx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; восстанавливаем I и R</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@norecurs:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov dx,si &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; L := I</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp si,cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jnae &nbsp; &nbsp;@@repeat1 &nbsp; &nbsp; &nbsp; ;; until I &#62;= R</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@finish:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;dec bp &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; уменьшаем глубину рекурсии</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jns @@recursret &nbsp; &nbsp; ; прыгаем, если это не первый (корневой) уровень рекурсии</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;pop bp</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@exit: ret</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@callins:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;offset @@finish &nbsp; &nbsp; ; адрес возврата</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jmp @IQInsSortDE &nbsp; &nbsp; &nbsp; &nbsp;; вместо call + jmp @@finish делаем push + jmp</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@callins2:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;offset @@recursret &nbsp;; адрес возврата</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jmp @IQInsSortDE &nbsp; &nbsp; &nbsp; &nbsp;; вместо call + jmp @@recursret делаем push + jmp</div><div class="code_line">IQSortDE &nbsp; &nbsp;ENDP</div><div class="code_line">&nbsp;</div><div class="code_line">;-- InsSortDE: СОРТИРОВКА массива ВСТАВКАМИ ----------------------------------------------------------------------------</div><div class="code_line">; &#62; Входные данные: DS:DX = адрес массива, CX = кол-во элементов массива (знаковое значение)</div><div class="code_line">; &#62; Результат: отсортированный массив (по тому же адресу)</div><div class="code_line">; Элементы массива содержат по 2 значения типа WORD:</div><div class="code_line">; &nbsp; * первое слово содержит опорное значение (по которому происходит сравнение),</div><div class="code_line">; &nbsp; * второе слово - связанные с элементом данные (обычно это указатель на данные);</div><div class="code_line">; &nbsp; &nbsp; при сортировке связанные данные переносятся вместе с опорными значениями</div><div class="code_line">; Процедура изменяет регистры AX, BX, SI, DI, сохраняет CX, DX, BP и сегментные регистры</div><div class="code_line">InsSortDE &nbsp; PROC</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;dec cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jle @@exit &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; выходим, если кол-во элементов &#60;= 1</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shl cx,2</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add cx,dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; CX = адрес последнего элемента</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; Главная процедура сортировки вставками</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DX = адрес первого элемента, CX = адрес последнего элемента, CX &#62; DX</div><div class="code_line">IFDEF &nbsp; &nbsp; &nbsp; ??Version &nbsp; ; TASM</div><div class="code_line">&nbsp;&nbsp;@IQInsSortDE:</div><div class="code_line">ELSE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; MASM</div><div class="code_line">&nbsp;&nbsp;@IQInsSortDE::</div><div class="code_line">ENDIF</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;bp</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov di,dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; J (DI) := L - адрес первого элемента</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@next: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; for J (DI) := L+1 (CX) to R (DX) do</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add di,4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; J++ (DI) - адрес следующего проверяемого элемента (в основном цикле)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov bx,[di] &nbsp; &nbsp; &nbsp; &nbsp; ;; T (BP:BX) := [J]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov bp,[di+2]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov si,di &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; I+1 (SI) = DI - адрес элемента, следующего за сравниваемым (во внутреннем цикле)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@loop: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; repeat</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov ax,[si-4]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp ax,bx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; if [I] &#62; T then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jle @@break &nbsp; &nbsp; &nbsp; &nbsp; ; прыгаем, если [I] &#60;= T {*** сортировка по возрастанию: jle - знаковое сравнение, jbe - беззнаковое; по убыванию: jge - знаковое, jae - беззнаковое}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov [si],ax &nbsp; &nbsp; &nbsp; &nbsp; ;; &nbsp;[I+1] := [I] else Break</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov ax,[si-4+2]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov [si+2],ax</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sub si,4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; Dec(I)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp si,dx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jnbe &nbsp; &nbsp;@@loop &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; until I &#60; L (I+1 &#60;= L)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@break:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov [si],bx &nbsp; &nbsp; &nbsp; &nbsp; ;; [I+1] := T</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov [si+2],bp</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp di,cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jnae &nbsp; &nbsp;@@next &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; следующий элемент массива ;; end for</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;pop bp</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@exit: ret</div><div class="code_line">InsSortDE &nbsp; ENDP</div></ol></div></div></div></div><br>
Модуль <span class="tag-color tag-color-named" data-value="red" style="color: red"><strong class='tag-b'>обычной быстрой сортировки</strong></span> для массивов с <em class='tag-i'>одиночными</em> элементами <strong class='tag-b'>QSortS1.inc</strong>:<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">;##################################################</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &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;[ Asm7x.List ][ QSortS1.inc ] &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -= Quick Sort =- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; (for single element arrays) &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Быстрая сортировка &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [ v1.00 :: 11.11.2017 ] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MASM/TASM (16 bit) &nbsp; &nbsp; &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; (c) 2017 by Jin X (jin.x@sources.ru) &nbsp; &nbsp; ##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; http://xk7.ru/p/a/i &nbsp; &nbsp; &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;##################################################</div><div class="code_line">&nbsp;</div><div class="code_line">IFDEF &nbsp; &nbsp; &nbsp; ??Version &nbsp; ; TASM</div><div class="code_line">&nbsp;&nbsp;LOCALS</div><div class="code_line">ENDIF</div><div class="code_line">&nbsp;</div><div class="code_line">QSortS1_ver = &nbsp; 100h &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; версия данного модуля (word: старший байт - целая часть, младший - дробная)</div><div class="code_line">&nbsp;</div><div class="code_line">; !!! В данном модуле используется ЗНАКОВОЕ сравнение значений и сортировка по ВОЗРАСТАНИЮ (от меньшего к большему)</div><div class="code_line">; !!! Для замены на БЕЗзнаковое сравнение или сортировку по УБЫВАНИЮ необходимо изменить соответствующие инструкции, помеченные в комментариях символами ***</div><div class="code_line">&nbsp;</div><div class="code_line">;-----------------------------------------------------------------------------------------------------------------------</div><div class="code_line">&nbsp;</div><div class="code_line">;-- QSort: БЫСТРАЯ СОРТИРОВКА массива ----------------------------------------------------------------------------------</div><div class="code_line">; &#62; Входные данные: DS:DX = адрес массива, CX = кол-во элементов массива (знаковое значение)</div><div class="code_line">; &#62; Результат: отсортированный массив (по тому же адресу)</div><div class="code_line">; Элементы массива содержат по 1 значению типа WORD, по которому происходит сравнение и сортировка</div><div class="code_line">; Процедура изменяет регистры AX, BX, CX, DX, SI, DI, сохраняет BP и сегментные регистры</div><div class="code_line">QSort &nbsp; &nbsp; &nbsp; PROC</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;dec cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jle @@exit &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; выходим, если кол-во элементов &#60;= 1</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;bp</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xor bp,bp &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; BP = кол-во рекурсий</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shl cx,1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add cx,dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; CX = адрес последнего элемента</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; Главная процедура быстрой сортировки</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DX = адрес первого элемента, CX = адрес последнего элемента, CX &#62; DX, BP = уровень рекурсии</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@QSortMain:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov si,dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; I (SI) := L (DX)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@repeat1: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; repeat</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov di,cx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; J (DI) := R (CX)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov bx,cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sub bx,dx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shr bx,1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;and bx,-2</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add bx,dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; P (BX) := (L + R) / 2</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov ax,[bx] &nbsp; &nbsp; &nbsp; &nbsp; ;; T (AX) := [P]</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@repeat2 = @@cmpI &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; repeat</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; SI = I, AX = T, DI = J, DX = L, CX = R</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jmp @@cmpI</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@addI: add si,2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; Inc(I)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@cmpI: cmp [si],ax &nbsp; &nbsp; &nbsp; &nbsp; ;; while [I] &#60; T</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jl &nbsp;@@addI &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; {*** сортировка по возрастанию: jl - знаковое сравнение, jb - беззнаковое; по убыванию: jg - знаковое, ja - беззнаковое}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jmp @@cmpJ</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@subJ: sub di,2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; Dec(J)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@cmpJ: cmp [di],ax &nbsp; &nbsp; &nbsp; &nbsp; ;; while [J] &#62; T</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jg &nbsp;@@subJ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; {*** сортировка по возрастанию: jg - знаковое сравнение, ja - беззнаковое; по убыванию: jl - знаковое, jb - беззнаковое}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp si,di</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jnbe &nbsp; &nbsp;@@noswap &nbsp; &nbsp; &nbsp; &nbsp;;; if I &#60;= J then</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov bx,[si] &nbsp; &nbsp; &nbsp; &nbsp; ;; &nbsp; Swap [I],[J]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;xchg &nbsp; &nbsp;[di],bx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov [si],bx</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add si,2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; Inc(I)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sub di,2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; Dec(J)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@noswap:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp si,di</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jna @@repeat2 &nbsp; &nbsp; &nbsp; ;; until I &#62; J</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp dx,di</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jnb @@norecurs &nbsp; &nbsp; &nbsp;;; if L &#60; J then</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;push &nbsp; &nbsp;si &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; сохраняем R и I</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov cx,di</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DX = L, CX = J</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;inc bp &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; увеличиваем глубину рекурсии и идём на рекурсию</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jmp @@QSortMain &nbsp; &nbsp; ;; &nbsp; QSort(L, J); вызов делаем через jmp для экономии стека :)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@recursret:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;pop si</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;pop cx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; восстанавливаем I и R</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@norecurs:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov dx,si &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; L := I</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp si,cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jnae &nbsp; &nbsp;@@repeat1 &nbsp; &nbsp; &nbsp; ;; until I &#62;= R</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@finish:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;dec bp &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; уменьшаем глубину рекурсии</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jns @@recursret &nbsp; &nbsp; ; прыгаем, если это не первый (корневой) уровень рекурсии</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;pop bp</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@exit: ret</div><div class="code_line">QSort &nbsp; &nbsp; &nbsp; ENDP</div></ol></div></div></div></div><br>
Модуль <span class="tag-color tag-color-named" data-value="red" style="color: red"><strong class='tag-b'>сортировки вставками</strong></span> для массивов с <em class='tag-i'>одиночными</em> элементами <strong class='tag-b'>ISortS1.inc</strong>:<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">;##################################################</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &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;[ Asm7x.List ][ ISortS1.inc ] &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -= Insertion Sort =- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; (for single element arrays) &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Сортировка вставками &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ##</div><div class="code_line">;## &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [ v1.00 :: 11.11.2017 ] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MASM/TASM (16 bit) &nbsp; &nbsp; &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;## &nbsp; &nbsp; (c) 2017 by Jin X (jin.x@sources.ru) &nbsp; &nbsp; ##</div><div class="code_line">;## &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; http://xk7.ru/p/a/i &nbsp; &nbsp; &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;##</div><div class="code_line">;##################################################</div><div class="code_line">&nbsp;</div><div class="code_line">IFDEF &nbsp; &nbsp; &nbsp; ??Version &nbsp; ; TASM</div><div class="code_line">&nbsp;&nbsp;LOCALS</div><div class="code_line">ENDIF</div><div class="code_line">&nbsp;</div><div class="code_line">ISortS1_ver = &nbsp; 100h &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; версия данного модуля (word: старший байт - целая часть, младший - дробная)</div><div class="code_line">&nbsp;</div><div class="code_line">; !!! В данном модуле используется ЗНАКОВОЕ сравнение значений и сортировка по ВОЗРАСТАНИЮ (от меньшего к большему)</div><div class="code_line">; !!! Для замены на БЕЗзнаковое сравнение или сортировку по УБЫВАНИЮ необходимо изменить соответствующие инструкции, помеченные в комментариях символами ***</div><div class="code_line">&nbsp;</div><div class="code_line">;-----------------------------------------------------------------------------------------------------------------------</div><div class="code_line">&nbsp;</div><div class="code_line">;-- InsSort: СОРТИРОВКА массива ВСТАВКАМИ ------------------------------------------------------------------------------</div><div class="code_line">; &#62; Входные данные: DS:DX = адрес массива, CX = кол-во элементов массива (знаковое значение)</div><div class="code_line">; &#62; Результат: отсортированный массив (по тому же адресу)</div><div class="code_line">; Элементы массива содержат по 1 значению типа WORD, по которому происходит сравнение и сортировка</div><div class="code_line">; Процедура изменяет регистры AX, BX, SI, DI, сохраняет CX, DX, BP и сегментные регистры</div><div class="code_line">InsSort &nbsp; &nbsp; PROC</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;dec cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jle @@exit &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; выходим, если кол-во элементов &#60;= 1</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;shl cx,1</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add cx,dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; CX = адрес последнего элемента</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; Главная процедура сортировки вставками</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;; DX = адрес первого элемента, CX = адрес последнего элемента, CX &#62; DX</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov di,dx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; J (DI) := L - адрес первого элемента</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@next: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; for J (DI) := L+1 (CX) to R (DX) do</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;add di,2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; J++ (DI) - адрес следующего проверяемого элемента (в основном цикле)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov bx,[di] &nbsp; &nbsp; &nbsp; &nbsp; ;; T (BX) := [J]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov si,di &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ; I+1 (SI) := DI - адрес элемента, следующего за сравниваемым (во внутреннем цикле)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@loop: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; repeat</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov ax,[si-2]</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp ax,bx &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ;; if [I] &#62; T then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jle @@break &nbsp; &nbsp; &nbsp; &nbsp; ; прыгаем, если [I] &#60;= T {*** сортировка по возрастанию: jle - знаковое сравнение, jbe - беззнаковое; по убыванию: jge - знаковое, jae - беззнаковое}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov [si],ax &nbsp; &nbsp; &nbsp; &nbsp; ;; &nbsp;[I+1] := [I] else Break</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;sub si,2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; Dec(I)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp si,dx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jnbe &nbsp; &nbsp;@@loop &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;;; until I &#60; L (I+1 &#60;= L)</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@break:</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov [si],bx &nbsp; &nbsp; &nbsp; &nbsp; ;; [I+1] := T</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;cmp di,cx</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;jnae &nbsp; &nbsp;@@next &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;; следующий элемент массива ;; end for</div><div class="code_line">&nbsp;&nbsp; &nbsp;@@exit: ret</div><div class="code_line">InsSort &nbsp; &nbsp; ENDP</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;lea dx,Array &nbsp; &nbsp; &nbsp; &nbsp;; DS:DX = адрес массива</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;mov cx,Count &nbsp; &nbsp; &nbsp; &nbsp;; CX = кол-во элементов массива</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;call &nbsp; &nbsp;IQSort &nbsp; &nbsp; &nbsp;; вызов процедуры умной быстрой сортировки</div></ol></div></div></div></div><br>
Настройка и добавление модуля <strong class='tag-b'>IQSort.inc</strong>:<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;inclInsSort = 1 &nbsp; ; включить в код полную процедуру сортировки вставками для использования её отдельно от процедуры умной быстрой сортировки (по умолчанию включается только используемая процедурой IQSort часть)</div><div class="code_line">&nbsp;&nbsp;SortSignCmp = 0 &nbsp; ; беззнаковое сравнение</div><div class="code_line">&nbsp;&nbsp;SortAscending = 0 ; сортировка значений по убыванию</div><div class="code_line">&nbsp;&nbsp;SortElemWords = 2 ; элементы массива имеют 2 слова в каждом элементе (допускается использовать только значение 1 или 2)</div><div class="code_line">&nbsp;&nbsp;IQSortInsThrs = 16 &nbsp; &nbsp;; использовать сортировку вставками для массивов, в которых меньше 16 элементов [это значение установлено по умолчанию]</div><div class="code_line">&nbsp;&nbsp;IQSortMaxStk = 128 &nbsp; &nbsp;; максимальный размер стека в байтах, который допустимо использовать процедуре IQSort (включая call из основного кода) [это значение установлено по умолчанию]</div><div class="code_line">&nbsp;&nbsp;INCLUDE IQSort.inc &nbsp; &nbsp;; включить модуль в проект</div></ol></div></div></div></div><br>
Хочу заметить, что единственной требуемой настройкой из этого списка является <strong class='tag-b'>SortElemWords</strong>, остальные могут быть опущены – в этом случае используются значения по умолчанию. Подробное описание каждой настройки смотрите в исходниках :)<br>
<br>
Всё остальное (универсальные модули, все отдельные процедуры обычной быстрой сортировки и сортировки вставками, в т.ч. с двойными элементами) – см. в архиве ;)<br>
<br>
p.s. Почему я использую именно сортировку вставками, а не пузырьковую или сортировку Шелла? Дело в том, что сортировка вставками на случайных данных работает раза в 2 быстрее пузырьковой (несмотря на её популярность), при этом в реализации она ничуть не сложнее, а где-то даже и проще. Сортировка Шелла не даст прироста скорости для небольших массивов (здесь же сортировка вставками используется по умолчанию для массивов, содержащих менее 16 элементами – это число взято в результате эмпирических экспериментов с разными значениями – 8, 12, 16, 24, 32). Прочие сортировки (вроде пирамидальной – тогда бы получился метод Introsort) слишком громоздки, поэтому я не стал их применять. Что касается быстрой сортировки, то я использую вариант реализации, схожий с используемым в Delphi – в сравнении с &quot;классическим&quot; вариантом (где рекурсивный вызов происходит дважды) данный метод во многих случаях более быстрый и использует меньше уровней рекурсии (правда, замеры я проводил именно в Delphi, но думаю, что и для ассемблера этот вариант оптимален, тем более он позволяет не записывать в стек адрес возврата при рекурсии) :)<br>
<br>
<span class="tag-color" data-value="c0c0c0" style="color: #c0c0c0">asm7x</span>[/COLOR]<br>
<span class="b-attach" data-size="81554" data-hits="226" data-attach-id="57130" data-attach-post-id="3749026">
			<span class="b-attach__title"></span><a class='b-attach-link' href='https://forum.sources.ru/index.php?act=Attach&amp;type=post&amp;id=3749026&amp;attach_id=57130' title='Скачать файл' target='_blank'>IQSort_16bit_1.00.zip</a> (, : 226)
		</span>]]></description>
        <author>Jin X</author>
        <category>Assembler FAQ</category>
      </item>
	
      </channel>
      </rss>
	