Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <algorithm>
- #include <iostream>
- #include <memory>
- #include <sstream>
- #include <string>
- #include <vector>
- #include "Utility.h"
- using namespace std;
- int main(int argc, char** argv)
- {
- int16_t* data1d;
- uint32_t len1d;
- uint32_t count1d;
- uint32_t positions1d[5];
- {
- vector<int16_t> dataVec;
- cout << "Enter the elements of the array (16-bit numbers): ";
- cin >> dataVec;
- // Указатель на данные
- data1d = dataVec.data();
- len1d = dataVec.size();
- int16_t maximum;
- __asm
- {
- call calc_1d //процедура без параметра
- jmp end_1
- calc_1d:
- // Сохраняем регистры в стеке, чтобы не испортить
- push ebx
- push ecx
- push edx
- push esi
- push edi
- mov ecx, len1d // Длина массива
- mov edx, 08000h // Здесь хранится текущий максимум - инициализируем минимальным значением
- // Выходим, если массив пустой,
- // однако возвращается минимальное число для 16 бит
- jcxz exit_1d
- // Назначаем всему начальные значения
- xor eax, eax // В EAX будем грузить элементы данных
- lea ebx, [positions1d] // Сюда будем выводить позиции максимумов (адрес начала)
- mov esi, data1d // Исходные данные (data1d - указатель)
- mov edi, ebx // Сюда будем выводить позиции максимумов (будет меняться)
- cld // Обнуление флага направления
- process:
- // Загружаем 16 бит по адресу [ESI] в AX, увеличиваем ESI на 2
- // AX <- [ESI]// ESI += 2
- lodsw
- // Сравниваем текущее значение с текущим максимумом
- cmp ax, dx
- jg above
- je equal1d
- continue:
- // Продолжаем...
- loop process //еще и уменьшает ECX
- jmp over
- above:
- // Если оказалось, что значение больше, чем текущий максимум,
- // то обновляем указатель на массив с позициями (начинаем заново заполнять позиции)
- mov edi, ebx
- equal1d:
- // Обновляем максимум
- mov dx, ax
- // Выйти, если элементов уже больше 5
- mov eax, edi // в еах текущий адрес
- sub eax, ebx //из текущего смещения вычесть начало массива
- cmp eax, 5 * 4 // (SIZEOF DWORD)
- jae continue //пропускаем обновление максимума
- // Запишем новую позицию - адрес предыдущего элемента
- // (так как ESI увеличивается сразу же после команды LODSW)
- lea eax, [esi - 2]
- mov [edi], eax
- xor eax, eax
- add edi, 4 //в edi указатель на массив адресов, переходим к след. эл.
- // Продолжаем...
- jmp continue
- over:
- // Вычисляем количество элементов, записанных в positions (там сейчас адреса)
- // Для этого из текущего смещения EDI вычитаем начало массива positions,
- // далее делим на 4 (размер адреса x86), сохраняем в выходной переменной count
- mov ecx, edi //текущее значение edi, указывающее на элемент в positions
- sub ecx, ebx //в ebx было начало массива
- shr ecx, 2 //деление на 4 (сдвиг на 2 бита)
- mov count1d, ecx
- // Готовимся к преобразованию адресов, лежащих в positions,
- // в индексы элементов
- mov esi, ebx //загружаем адреса positions
- mov edi, ebx
- // Загружаем начало массива данных
- mov ebx, data1d
- offset_pos:
- // EAX <- [ESI]// ESI += 4
- // Вычитаем из EAX начало массива и делим на 2 - индекс готов
- lodsd
- sub eax, ebx
- shr eax, 1 // делим на 2, индексы элементов
- // [EDI] <- EAX// EDI += 4
- // Сохраняем на то же место
- stosd
- // Выполняем для всех индексов
- loop offset_pos
- exit_1d:
- // в EDX находится максимум по массиву
- mov eax, edx
- mov maximum, dx
- // Восстанавливаем регистры из стека в обратном порядке
- pop edi
- pop esi
- pop edx
- pop ecx
- pop ebx
- // Возвращаемся в код C++
- ret
- end_1:
- }
- cout << "Max element is: " << maximum << endl;
- cout << "There are " << count1d << " maximum elements" << endl;
- cout << "They are located at positions (starting from 0) ";
- auto posVec = vector<int32_t> { positions1d, positions1d + count1d };
- cout << posVec << endl;
- cout << endl;
- }
- cout << "-------------" << endl;
- {
- cout << "First enter the number of rows in 2D array: ";
- size_t n;
- cin >> n;
- cin.ignore();
- vector<vector<int16_t>> dataVec(n);
- cout << "Now enter the elements of each row line-by-line:" << endl;
- string buffer;
- for (size_t i = 0; i < n; ++i)
- {
- cout << "\t" << i << ": ";
- cin >> dataVec[i];
- }
- vector<uint32_t> sizes;
- sizes.reserve(dataVec.size());
- for (const auto& a : dataVec)
- {
- sizes.push_back(a.size());
- }
- uint32_t count;
- vector<uint32_t> posXVec(5);
- vector<uint32_t> posYVec(5);
- int16_t** data = vecToRaw(dataVec).get();
- uint32_t len = dataVec.size();
- uint32_t* sub_array_sizes = sizes.data(); //размер каждой строчки
- uint32_t* pos_x = posXVec.data();
- uint32_t* pos_y = posYVec.data();
- uint32_t element_count; // Общее насчитанное количество
- int16_t maximum;
- __asm
- {
- mov ecx, len // Длина массива, каждая ячейка которого - подмассив
- mov edx, 08000h // Текущий максимум - установлен в абсолютный минимум
- jcxz terminate_2d // условный переход
- jmp begin_2d
- terminate_2d:
- jmp exit_2d
- begin_2d:
- // Изначально элементов 0
- mov element_count, 0
- // Инициализируем все
- mov esi, data // Адрес данных
- mov edi, sub_array_sizes // Для каждого подмассива есть собственная длина, указатель на массив длин строк
- // Очищаем флаг направления - таким образом строковые операции (напр. STOSx, LODSx)
- // будут работать по возрастанию адресов
- cld
- process_1d:
- // Загружаем адрес подмассива данных и его размер
- mov eax, [esi] // Подмассив данных, указатель на одномерный массив
- mov ebx, [edi] // Размер подмассива
- // Инкремент на элемент вперед
- add esi, 4
- add edi, 4
- // Вызываем процедуру для подмассива
- mov len1d, ebx // Устанавливаем длину подмассива
- mov data1d, eax // Устанавливаем указатель на данные подмассива
- call calc_1d //процедура поиска максимума в одномерном массиве
- // Проверяем ее максимум
- cmp ax, dx
- jg greater_1d
- je equal_1d
- continue_1d:
- // Продолжаем...
- loop process_1d
- jmp end_1d
- greater_1d:
- // Новый максимум - обновляем, затираем позиции
- mov dx, ax
- mov element_count, 0
- equal_1d:
- // Сохраняем регистры
- push ecx
- push esi
- push edi
- // Обновляем общее количество максимумов
- mov eax, count1d // Количество максимумов в строке
- mov ecx, element_count //общее количество максимумов
- // В случае, если элементов уже больше 5,
- // не заполняем позиции, так как такой элемент не может быть максимумом
- add ecx, eax
- cmp ecx, 5
- ja skip_equal
- // Вычисляем смещение, куда нужно будет записать позиции
- mov eax, element_count
- shl eax, 2 //умножаем на 4, потому что адреса 32-битные, в еах смещение
- // Сохраняем количество, если оно в пределах 5 элементов
- mov element_count, ecx
- // Меняем индексные регистры на адреса:
- lea esi, [positions1d] // индексы максимумов в строке
- mov edi, pos_y // Выходной массив с координатами столбца
- add edi, eax // добавляем смещение
- mov ebx, pos_x // Выходной массив с координатами строки
- add ebx, eax
- // Сохраняем ECX, в ЕСХ кол-во максимумов в строке
- mov eax, ecx
- // Копируем позиции максимумов данной строки
- // в выходной массив pos_y
- // {делаем ECX раз} [EDI] <- [ESI]// ESI += 4// EDI += 4
- rep movsd
- // Восстанавливаем индексные регистры
- pop edi
- pop esi
- // Забиваем pos_x адресом строки - далее они будут преобразованы в индексы
- mov ecx, eax //количество максимумов строки
- mov eax, esi //esi - адрес текущей строки
- xchg edi, ebx //указатель на массив индексов строки
- // {делаем ECX раз} [EDI] <- EAX// EDI += 4
- rep stosd
- // Возвращаем EDI на место
- xchg edi, ebx
- // Восстанавливаем счетчик, после восстановления указывает на кол-во строк
- pop ecx
- jmp continue_1d
- skip_equal:
- pop edi
- pop esi
- pop ecx
- jmp continue_1d
- end_1d:
- // Выводим общее число в переменную count, из памяти в регистр, из регистра в память
- mov eax, element_count
- mov count, eax
- // Готовимся к преобразованию адресов в индексы в строках
- mov ebx, data
- mov ecx, eax
- mov esi, pos_x
- mov edi, esi
- transform_address:
- // Загружаем очередной адрес
- lodsd
- // Вычитаем из него начало массива данных, делим на 4, вычитаем 1, чтобы получить индексы
- sub eax, ebx
- shr eax, 2 // /4
- dec eax
- // Сохраняем туда же (ESI == EDI)
- stosd
- // Делаем ECX раз
- loop transform_address
- exit_2d:
- // Возвращаем общий максимум
- mov eax, edx
- mov maximum, ax
- }
- cout << "Max element is: " << maximum << endl;
- cout << "There are " << count << " maximum elements" << endl;
- cout << "They are located at positions (row, col) ";
- posXVec.resize(count);
- posYVec.resize(count);
- for (size_t i = 0; i < posXVec.size(); ++i)
- {
- cout << "(" << posXVec[i] << ", " << posYVec[i] << ")" << "; ";
- }
- cout << endl;
- }
- cout << "-------------" << endl;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement