Advertisement
dmkozyrev

quick_sort_asm.cpp

May 24th, 2016
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.26 KB | None | 0 0
  1. #include <iostream>
  2. #include <cstdlib>
  3. #include <ctime>
  4. using namespace std;
  5.  
  6. void quicksort(int * mas, int first, int last){
  7.     asm(
  8.                 "leave;" //"pop %ebp;" // вернуть стек к его первоначальному состоянию (которое было перед вызовом внешней функции)
  9.         "quick_sort:"  
  10.                 // входим в функцию, сохраняя регистр ebp в стек
  11.                 "push   %ebp;"
  12.                 "mov    %esp,           %ebp;"
  13.                
  14.                 // Смещаем стек влево на 10*sizeof(int) = 40 = 0x28
  15.                 "sub    $0x28,          %esp;"
  16.                
  17.                 // f = first;
  18.                 "mov    0xc(%ebp),      %eax;"
  19.                 "mov    %eax,           -0xc(%ebp);"
  20.                
  21.                 // l = last;
  22.                 "mov    0x10(%ebp),     %eax;"
  23.                 "mov    %eax,           -0x10(%ebp);"
  24.                
  25.                 // l + f;
  26.                 "mov    -0xc(%ebp),     %edx;"
  27.                 "mov    -0x10(%ebp),    %eax;"
  28.                 "add    %edx,           %eax;"
  29.                 "mov    %eax,           %edx;"
  30.                
  31.                 // (l + f)/2;
  32.                 "shr    $0x1f,          %edx;"
  33.                 "add    %edx,           %eax;"
  34.                 "sar    %eax;"
  35.                
  36.                 // mid = mas[(l + f)/2];
  37.                 "lea    (,%eax,4),      %edx;"
  38.                 "mov    0x8(%ebp),      %eax;"
  39.                 "add    %edx,           %eax;"
  40.                 "mov    (%eax),         %eax;"
  41.                 "mov    %eax,           -0x14(%ebp);"
  42.                
  43.             // Цикл do {...} while (f < l);
  44.             "_do:" 
  45.                 "jmp    _condition_while_left;"
  46.                
  47.                 // Цикл while ( mas[f] < mid ) f++;
  48.                 "_step_while_left:"
  49.                     "addl   $0x1,       -0xc(%ebp);" // f++;
  50.                 "_condition_while_left:"   
  51.                     "mov    -0xc(%ebp), %eax;"
  52.                     "lea    (,%eax,4),  %edx;"
  53.                     "mov    0x8(%ebp),  %eax;"
  54.                     "add    %edx,       %eax;"
  55.                     "mov    (%eax),     %eax;"
  56.                     "cmp    -0x14(%ebp),%eax;"
  57.                     "jl     _step_while_left;"
  58.                     "jmp    _condition_while_right;"
  59.                    
  60.                 // Цикл while ( mas[l] > mid ) l--;
  61.                 "_step_while_right:"   
  62.                     "subl   $0x1,       -0x10(%ebp);" // l--;
  63.                 "_condition_while_right:"  
  64.                     "mov    -0x10(%ebp),%eax;"
  65.                     "lea    (,%eax,4),  %edx;"
  66.                     "mov    0x8(%ebp),  %eax;"
  67.                     "add    %edx,       %eax;"
  68.                     "mov    (%eax),     %eax;"
  69.                     "cmp    -0x14(%ebp),%eax;"
  70.                     "jg     _step_while_right;"
  71.                 // if ( f <= l )
  72.                 "mov    -0xc(%ebp),     %eax;"  // Копирование f в регистр eax
  73.                 "cmp    -0x10(%ebp),    %eax;"  // Сравнение f и l
  74.                
  75.                 // Если f > f то пропускаем тело условия
  76.                 "jg     _after_if_in_do_while;"
  77.                
  78.                 // Иначе меняем местами mas[f] и mas[l]
  79.                 // count = mas[f];
  80.                 "mov    -0xc(%ebp),     %eax;"
  81.                 "lea    (,%eax,4),      %edx;"
  82.                 "mov    0x8(%ebp),      %eax;"
  83.                 "add    %edx,           %eax;"
  84.                 "mov    (%eax),         %eax;"
  85.                 "mov    %eax,           -0x18(%ebp);"
  86.                
  87.                 // mas[f] = mas[l];
  88.                 "mov    -0xc(%ebp),     %eax;"
  89.                 "lea    (,%eax,4),      %edx;"
  90.                 "mov    0x8(%ebp),      %eax;"
  91.                 "add    %eax,           %edx;"
  92.                 "mov    -0x10(%ebp),    %eax;"
  93.                 "lea    (,%eax,4),      %ecx;"
  94.                 "mov    0x8(%ebp),      %eax;"
  95.                 "add    %ecx,           %eax;"
  96.                 "mov    (%eax),         %eax;"
  97.                 "mov    %eax,           (%edx);"
  98.                 // mas[l] = count;
  99.                 "mov    -0x10(%ebp),    %eax;"
  100.                 "lea    0x0(,%eax,4),   %edx;"
  101.                 "mov    0x8(%ebp),      %eax;"
  102.                 "add    %eax,           %edx;"
  103.                 "mov    -0x18(%ebp),    %eax;"
  104.                 "mov    %eax,           (%edx);"
  105.                
  106.                 // Увеличиваем f на единицу
  107.                 "addl   $0x1,           -0xc(%ebp);"    // f++
  108.                
  109.                 // Уменьшаем l на единицу
  110.                 "subl   $0x1,           -0x10(%ebp);"   // l--
  111.             "_after_if_in_do_while:"
  112.                 // Сравниваем f и l 
  113.                 "mov    -0xc(%ebp),     %eax;"
  114.                 "cmp    -0x10(%ebp),    %eax;"
  115.                
  116.                 // Если f < l, то возвращаемся к телу цикла do {...} while
  117.                 "jl     _do;"
  118.                
  119.                 // Сравниваем first и l
  120.                 "mov    0xc(%ebp),      %eax;"
  121.                 "cmp    -0x10(%ebp),    %eax;"
  122.                
  123.                 // Если first >= last, то левая рекурсия не нужна, переходим к правой рекурсии
  124.                 "jge    _after_left_recursion;"
  125.                
  126.                 // Иначе мы должны рекурсивно вызвать функцию сортировки на левом отрезке
  127.                 // Кладем l во второй элемент за указателем на стек
  128.                 "mov    -0x10(%ebp),    %eax;"
  129.                 "mov    %eax,           0x8(%esp);"
  130.                
  131.                 // Кладем first в первый элемент за указателем на стек
  132.                 "mov    0xc(%ebp),      %eax;"
  133.                 "mov    %eax,           0x4(%esp);"
  134.                
  135.                 // Кладем mas в элемент, на который непосредственно указывает указатель на стек
  136.                 "mov    0x8(%ebp),      %eax;"
  137.                 "mov    %eax,           (%esp);"
  138.                
  139.                 // Вызываем quicksort(mas, first, l);
  140.                 "call   quick_sort;"
  141.             "_after_left_recursion:"
  142.                 // Сравниваем f и last
  143.                 "mov    -0xc(%ebp),     %eax;"
  144.                 "cmp    0x10(%ebp),     %eax;"
  145.                
  146.                 // Если f >= last, то правая рекурсия не нужна, переходим в конец функции
  147.                 "jge    _end;"
  148.                
  149.                 // Иначе мы должны рекурсивно вызвать функцию сортировки на правом отрезке
  150.                 // Кладем last во второй элемент за указателем на стек
  151.                 "mov    0x10(%ebp),     %eax;"
  152.                 "mov    %eax,           0x8(%esp);"
  153.                
  154.                 // Кладем f в первый элемент за указателем на стек
  155.                 "mov    -0xc(%ebp),     %eax;"
  156.                 "mov    %eax,           0x4(%esp);"
  157.                
  158.                 // Кладем mas в элемент, на который непосредственно указывает указатель на стек
  159.                 "mov    0x8(%ebp),      %eax;"
  160.                 "mov    %eax,           (%esp);"
  161.                
  162.                 // Вызываем quicksort(mas, f, last);
  163.                 "call   quick_sort;"
  164.             "_end:  leave;"  
  165.         "ret;"
  166.     );                     
  167. }
  168.  
  169. int main() {
  170. //  Создаем массив:
  171.     const int n = 500000; int a[n];
  172.     for (int i = 0; i < n; i++)
  173.         a[i] = rand() % n;
  174.        
  175. //  Сортируем в порядке неубывания и засекаем время:
  176.     int t = clock();
  177.     quicksort(a, 0, n-1);
  178.     double time_sec = (clock() - t ) * 1.0 / CLOCKS_PER_SEC;
  179. //  Проверяем на правильность:
  180.     for (int i = 1; i < n; i++)
  181.         if ( a[i-1] > a[i] )
  182.             printf("ERROR: a[%d] > a[%d]\n", i-1, i);
  183.     printf("ok! time: %0.3fs\n", time_sec);
  184.     return 0;
  185. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement