Advertisement
Guest User

Untitled

a guest
Nov 11th, 2019
147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.07 KB | None | 0 0
  1. #include <algorithm>
  2. #include <iostream>
  3. #include <memory>
  4. #include <sstream>
  5. #include <string>
  6. #include <vector>
  7.  
  8. #include "Utility.h"
  9.  
  10. using namespace std;
  11.  
  12. int main(int argc, char** argv)
  13. {
  14.     int16_t* data1d;
  15.     uint32_t len1d;
  16.     uint32_t count1d;
  17.     uint32_t positions1d[5];
  18.  
  19.     {
  20.         vector<int16_t> dataVec;
  21.  
  22.         cout << "Enter the elements of the array (16-bit numbers): ";
  23.  
  24.         cin >> dataVec;
  25.  
  26.         // Указатель на данные
  27.         data1d = dataVec.data();
  28.         len1d = dataVec.size();
  29.  
  30.         int16_t maximum;
  31.  
  32.         __asm
  33.         {
  34. call calc_1d //процедура без параметра
  35. jmp end_1
  36.  
  37. calc_1d:
  38.  
  39. // Сохраняем регистры в стеке, чтобы не испортить
  40. push ebx
  41. push ecx
  42. push edx
  43. push esi
  44. push edi
  45.  
  46. mov ecx, len1d      // Длина массива
  47. mov edx, 08000h     // Здесь хранится текущий максимум - инициализируем минимальным значением
  48.  
  49. // Выходим, если массив пустой,
  50. // однако возвращается минимальное число для 16 бит
  51. jcxz exit_1d
  52.  
  53. // Назначаем всему начальные значения
  54. xor eax, eax        // В EAX будем грузить элементы данных
  55. lea ebx, [positions1d]  // Сюда будем выводить позиции максимумов (адрес начала)
  56. mov esi, data1d     // Исходные данные (data1d - указатель)
  57. mov edi, ebx        // Сюда будем выводить позиции максимумов (будет меняться)
  58. cld                 // Обнуление флага направления
  59.  
  60. process:
  61.     // Загружаем 16 бит по адресу [ESI] в AX, увеличиваем ESI на 2
  62.     // AX <- [ESI]// ESI += 2
  63.     lodsw
  64.    
  65.     // Сравниваем текущее значение с текущим максимумом
  66.     cmp ax, dx
  67.     jg above
  68.     je equal1d
  69.    
  70. continue:
  71.     // Продолжаем...
  72.     loop process //еще и уменьшает ECX
  73.     jmp over
  74.    
  75. above:
  76.     // Если оказалось, что значение больше, чем текущий максимум,
  77.     // то обновляем указатель на массив с позициями (начинаем заново заполнять позиции)
  78.     mov edi, ebx
  79.    
  80. equal1d:
  81.     // Обновляем максимум
  82.     mov dx, ax
  83.    
  84.     // Выйти, если элементов уже больше 5
  85.     mov eax, edi // в еах текущий адрес
  86.     sub eax, ebx //из текущего смещения вычесть начало массива
  87.     cmp eax, 5 * 4 // (SIZEOF DWORD)
  88.     jae continue //пропускаем обновление максимума
  89.    
  90.     // Запишем новую позицию - адрес предыдущего элемента
  91.     // (так как ESI увеличивается сразу же после команды LODSW)
  92.     lea eax, [esi - 2]
  93.     mov [edi], eax
  94.     xor eax, eax
  95.     add edi, 4 //в edi указатель на массив адресов, переходим к след. эл.
  96.    
  97.     // Продолжаем...
  98.     jmp continue
  99.  
  100. over:
  101.     // Вычисляем количество элементов, записанных в positions (там сейчас адреса)
  102.     // Для этого из текущего смещения EDI вычитаем начало массива positions,
  103.     // далее делим на 4 (размер адреса x86), сохраняем в выходной переменной count
  104.     mov ecx, edi //текущее значение edi, указывающее на элемент в positions
  105.     sub ecx, ebx //в ebx было начало массива
  106.     shr ecx, 2 //деление на 4 (сдвиг на 2 бита)
  107.     mov count1d, ecx
  108.    
  109.     // Готовимся к преобразованию адресов, лежащих в positions,
  110.     // в индексы элементов
  111.     mov esi, ebx //загружаем адреса positions
  112.     mov edi, ebx
  113.    
  114.     // Загружаем начало массива данных
  115.     mov ebx, data1d
  116.  
  117. offset_pos:
  118.     // EAX <- [ESI]// ESI += 4
  119.     // Вычитаем из EAX начало массива и делим на 2 - индекс готов
  120.     lodsd
  121.     sub eax, ebx
  122.     shr eax, 1 // делим на 2, индексы элементов
  123.    
  124.     // [EDI] <- EAX// EDI += 4
  125.     // Сохраняем на то же место
  126.     stosd
  127.    
  128.     // Выполняем для всех индексов
  129.     loop offset_pos
  130.  
  131. exit_1d:
  132.     // в EDX находится максимум по массиву
  133.     mov eax, edx
  134.     mov maximum, dx
  135.    
  136.     // Восстанавливаем регистры из стека в обратном порядке
  137.     pop edi
  138.     pop esi
  139.     pop edx
  140.     pop ecx
  141.     pop ebx
  142.  
  143.     // Возвращаемся в код C++
  144.     ret
  145.  
  146. end_1:
  147.         }
  148.  
  149.         cout << "Max element is: " << maximum << endl;
  150.         cout << "There are " << count1d << " maximum elements" << endl;
  151.         cout << "They are located at positions (starting from 0) ";
  152.  
  153.         auto posVec = vector<int32_t> { positions1d, positions1d + count1d };
  154.  
  155.         cout << posVec << endl;
  156.  
  157.         cout << endl;
  158.     }
  159.  
  160.     cout << "-------------" << endl;
  161.  
  162.     {
  163.         cout << "First enter the number of rows in 2D array: ";
  164.  
  165.         size_t n;
  166.  
  167.         cin >> n;
  168.         cin.ignore();
  169.  
  170.         vector<vector<int16_t>> dataVec(n);
  171.  
  172.         cout << "Now enter the elements of each row line-by-line:" << endl;
  173.  
  174.         string buffer;
  175.  
  176.         for (size_t i = 0; i < n; ++i)
  177.         {
  178.             cout << "\t" << i << ": ";
  179.             cin >> dataVec[i];
  180.         }
  181.  
  182.         vector<uint32_t> sizes;
  183.         sizes.reserve(dataVec.size());
  184.  
  185.         for (const auto& a : dataVec)
  186.         {
  187.             sizes.push_back(a.size());
  188.         }
  189.  
  190.         uint32_t count;
  191.         vector<uint32_t> posXVec(5);
  192.         vector<uint32_t> posYVec(5);
  193.  
  194.         int16_t** data = vecToRaw(dataVec).get();
  195.         uint32_t len = dataVec.size();
  196.         uint32_t* sub_array_sizes = sizes.data(); //размер каждой строчки
  197.         uint32_t* pos_x = posXVec.data();
  198.         uint32_t* pos_y = posYVec.data();
  199.  
  200.    
  201.         uint32_t element_count; // Общее насчитанное количество
  202.  
  203.         int16_t maximum;
  204.  
  205.         __asm
  206.         {
  207. mov ecx, len                // Длина массива, каждая ячейка которого - подмассив
  208. mov edx, 08000h             // Текущий максимум - установлен в абсолютный минимум
  209. jcxz terminate_2d // условный переход
  210. jmp begin_2d
  211.  
  212. terminate_2d:
  213.     jmp exit_2d
  214.  
  215. begin_2d:
  216.     // Изначально элементов 0
  217.     mov element_count, 0
  218.    
  219.     // Инициализируем все
  220.     mov esi, data               // Адрес данных
  221.     mov edi, sub_array_sizes    // Для каждого подмассива есть собственная длина, указатель на массив длин строк
  222.    
  223.     // Очищаем флаг направления - таким образом строковые операции (напр. STOSx, LODSx)
  224.     // будут работать по возрастанию адресов
  225.     cld
  226.  
  227. process_1d:
  228.     // Загружаем адрес подмассива данных и его размер
  229.     mov eax, [esi]  // Подмассив данных, указатель на одномерный массив
  230.     mov ebx, [edi]  // Размер подмассива
  231.    
  232.     // Инкремент на элемент вперед
  233.     add esi, 4
  234.     add edi, 4
  235.    
  236.     // Вызываем процедуру для подмассива
  237.     mov len1d, ebx  // Устанавливаем длину подмассива
  238.     mov data1d, eax // Устанавливаем указатель на данные подмассива
  239.     call calc_1d //процедура поиска максимума в одномерном массиве
  240.    
  241.     // Проверяем ее максимум
  242.     cmp ax, dx
  243.     jg greater_1d
  244.     je equal_1d
  245.    
  246. continue_1d:
  247.     // Продолжаем...
  248.     loop process_1d
  249.     jmp end_1d
  250.    
  251. greater_1d:
  252.     // Новый максимум - обновляем, затираем позиции
  253.     mov dx, ax
  254.     mov element_count, 0
  255.    
  256. equal_1d:
  257.    
  258.     // Сохраняем регистры
  259.     push ecx
  260.     push esi
  261.     push edi
  262.    
  263.     // Обновляем общее количество максимумов
  264.     mov eax, count1d    // Количество максимумов в строке
  265.     mov ecx, element_count //общее количество максимумов
  266.    
  267.     // В случае, если элементов уже больше 5,
  268.     // не заполняем позиции, так как такой элемент не может быть максимумом
  269.     add ecx, eax
  270.     cmp ecx, 5
  271.     ja skip_equal
  272.    
  273.     // Вычисляем смещение, куда нужно будет записать позиции
  274.     mov eax, element_count
  275.     shl eax, 2 //умножаем на 4, потому что адреса 32-битные, в еах смещение
  276.    
  277.     // Сохраняем количество, если оно в пределах 5 элементов
  278.     mov element_count, ecx
  279.    
  280.     // Меняем индексные регистры на адреса:
  281.     lea esi, [positions1d]  // индексы максимумов в строке
  282.     mov edi, pos_y          // Выходной массив с координатами столбца
  283.     add edi, eax            // добавляем смещение
  284.     mov ebx, pos_x          // Выходной массив с координатами строки
  285.     add ebx, eax
  286.    
  287.     // Сохраняем ECX, в ЕСХ кол-во максимумов в строке
  288.     mov eax, ecx
  289.    
  290.     // Копируем позиции максимумов данной строки
  291.     // в выходной массив pos_y
  292.     // {делаем ECX раз} [EDI] <- [ESI]// ESI += 4// EDI += 4
  293.     rep movsd
  294.    
  295.     // Восстанавливаем индексные регистры
  296.     pop edi
  297.     pop esi
  298.    
  299.     // Забиваем pos_x адресом строки - далее они будут преобразованы в индексы
  300.     mov ecx, eax //количество максимумов строки
  301.     mov eax, esi //esi - адрес текущей строки
  302.     xchg edi, ebx //указатель на массив индексов строки
  303.    
  304.     // {делаем ECX раз} [EDI] <- EAX// EDI += 4
  305.     rep stosd
  306.    
  307.     // Возвращаем EDI на место
  308.     xchg edi, ebx
  309.    
  310.     // Восстанавливаем счетчик, после восстановления указывает на кол-во строк
  311.     pop ecx
  312.    
  313.     jmp continue_1d
  314.  
  315. skip_equal:
  316.     pop edi
  317.     pop esi
  318.     pop ecx
  319.  
  320.     jmp continue_1d
  321.    
  322. end_1d:
  323.     // Выводим общее число в переменную count, из памяти в регистр, из регистра в память
  324.     mov eax, element_count
  325.     mov count, eax
  326.    
  327.     // Готовимся к преобразованию адресов в индексы в строках
  328.     mov ebx, data
  329.     mov ecx, eax
  330.     mov esi, pos_x
  331.     mov edi, esi
  332.    
  333. transform_address:
  334.     // Загружаем очередной адрес
  335.     lodsd
  336.    
  337.     // Вычитаем из него начало массива данных, делим на 4, вычитаем 1, чтобы получить индексы
  338.     sub eax, ebx
  339.     shr eax, 2 // /4
  340.     dec eax
  341.    
  342.     // Сохраняем туда же (ESI == EDI)
  343.     stosd
  344.    
  345.     // Делаем ECX раз
  346.     loop transform_address
  347.    
  348. exit_2d:
  349.  
  350.     // Возвращаем общий максимум
  351.     mov eax, edx
  352.     mov maximum, ax
  353.  
  354.         }
  355.  
  356.         cout << "Max element is: " << maximum << endl;
  357.         cout << "There are " << count << " maximum elements" << endl;
  358.         cout << "They are located at positions (row, col) ";
  359.  
  360.         posXVec.resize(count);
  361.         posYVec.resize(count);
  362.  
  363.         for (size_t i = 0; i < posXVec.size(); ++i)
  364.         {
  365.             cout << "(" << posXVec[i] << ", " << posYVec[i] << ")" << "; ";
  366.         }
  367.  
  368.         cout << endl;
  369.     }
  370.  
  371.     cout << "-------------" << endl;
  372.  
  373.     return 0;
  374. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement