МИНОБРНАУКИ РОССИИ САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ ЭЛЕКТРОТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ «ЛЭТИ» ИМ. В.И. УЛЬЯНОВА (ЛЕНИНА) Кафедра МОЭВМ ОТЧЕТ по лабораторной работе № 6 по дисциплине «Организация ЭВМ и систем» ТЕМА: Организация связи Ассемблера с ЯВУ на примере программы построения частотного распределения попаданий псевдослучайных целых чисел в заданные интервалы Студентка гр. 8381 Звегинцева Е.Н. Преподаватель Кирьянчиков В. А. Санкт-Петербург 2019 Цель работы: Получить практические навыки программирования на языке Ассемблера. Формулировка задания: На языке высокого уровня программируется ввод с клавиатуры и контроль исходных данных (см.ниже), а также генерируется массив псевдослучайных целых чисел, изменяющихся в заданном диапазоне и имеющих равномерное или гауссовское (ограниченное интервалом [Mx-3*S,Mx+3*S]) распределение. Следует привести числа к целому виду с учетом диапазона изменения. Далее должны вызываться 1 или 2 ассемблерных процедуры для формирования распределения количества попаданий псевдослучайных целых чисел в заданные интервалы. Ассемблерные процедуры должны вызываться как независимо скомпилированные модули. Передача параметров в процедуру должна выполняться через кадр стека. Результирующий массив частотного распределения чисел по интервалам, сформированный на ассемблерном уровне, возвращается в программу, реализованную на ЯВУ, и затем сохраняется в файле и выводится на экран средствами ЯВУ. Исходные данные: 1. Длина массива псевдослучайных целыхчисел - NumRanDat (<= 16K) 2. Диапазон изменения массива псевдослучайных целых чисел [Xmin, Xmax] (м.б. биполярный, например, [-100, 100]) 3. Массив псевдослучайных целых чисел. 4. Количество интервалов, на которые разбивается диапазон изменения массива псевдослучайных целых чисел - NInt ( <=24 ) 5. Массив левых границ интервалов разбиения LGrInt (должны принадлежать интервалу [Xmin,Xmax]) В общем случае интервалы разбиения диапазона изменения псевдослучайных чисел могут иметь различную длину. 7 вариант: Для бригад с нечетным номером: программа формирования распределения количества попаданий псевдослучайных целых чисел в заданные интервалы реализуется в виде одного асемблерного модуля (процедуры), сразу получающего требуемое распределение и возвращающего его в головную программу, написанную на ЯВУ; Результаты: 1. Обязательный - текстовая таблица, строка которой содержит: - номер интервала, - левую границу интервала, - количество псевдослучайных чисел, попавших в интервал. Количество строк должно быть равно числу интервалов разбиения. Таблица должна выводиться на экран и сохраняться в файле. Тестирование: Размер массива псевдосл. чисел Диапазон [Xmin,Xmax] 10 [-5;5] 5 [-2;2] Массив псевдослучайных чисел 1) 3 2) 4 3) 4 4) -4 5) 2 6) 0 7) 0 8) 5 9) -4 10) -5 1) -1 2) 0 3) 2 4)-2 5) 2 Массив левых границ Результирующий массив частотного распределения 1) -5 2) -3 3) 3 (-5) 3 (-3) 3 (3) 4 1) -2 2) 0 (-2) 2 (0) 3 15 [-5;10] 1) 4 2) -2 3) 9 4) -1 5) -4 6) 7 7) 1 8) 9 9) -3 10) -5 11) 4 12) -4 13) -4 14) 6 15) 4 1) -5 2) -2 3) 2 4) 7 (-5) (-2) (2) (7) 5 3 4 3 Вывод: В ходе выполнения данной лабораторной работы была написана программа на языке Ассемблера, которая строит частотное распределение попаданий псевдослучайных чисел в заданные интервалы. В результате выполнения лабораторной работы были получены практические навыки программирования на языке Ассемблер. Приложения А. Исходный код LR6_ASM.cpp #include "stdafx.h" #include "iostream" #include <iomanip> using namespace std; extern "C" { //подключение файла с кодом ассемблера void func (int *arr, int Xmin, int *res, int length_); void func2(int *result, int *LGr, int* result_final, int legth_big, int Xmin, int length_); void func2_1(int *result, int *LGr, int *result_final, int length_big, int Xmin, int lehtg_); } void sort(int *arr, int count_) { for (int i = 0; i < count_ - 1; i++) { for (int j = 0; j < count_ - i - 1; j++) { if (arr[j] > arr[j + 1]) { int b = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = b; } } } } void print(int*arr, int count_) { cout << endl << endl; for (int j = 0; j < count_; j++) { cout << j + 1 << ". " << arr[j] << "\n"; } } void print_task(int*arr, int* LGr, int count_) { cout << endl << endl; cout << "Номер интервала\t Левая граница интервала интервал\n"; for (int j = 0; j < count_; j++) { cout << j + 1 << "\t\t ("<<LGr[j]<<")\t\t\t } } Кол-во чисел, попавших в " << arr[j] << "\n"; int main() { setlocale(0, "RUS"); int length_; //длина массива псевдослучайных чисел do { cout << "Введите длину массива псевдослучайных чисел\n"; cin >> length_; } while ( (length_ > 16000) || (length_ <0) ); int Xmin, Xmax; //левая и правая границы диапазона изменения массива do { cout << "Введите минимальное значение отрезка\n"; cin >> Xmin; cout << "Введите максимальное значение отрезка\n"; cin >> Xmax; } while (Xmin > Xmax); int *arr = new int[length_]; //массив псевдослучайных чисел for (int i = 0; i < length_; i++) { arr[i] = Xmin + rand() % (Xmax-Xmin+1); }; cout << "Массив псевдослучайных чисел:\n"; print(arr, length_); int *result = new int[(Xmax - Xmin + 1)]; //массив полученного распределения int *LGr1 = new int[(Xmax - Xmin + 1)]; //массив левых границ для первой функции for (int i = 0; i < (Xmax - Xmin + 1); i++) { result[i] = 0; LGr1[i] = Xmin + i; } func(arr, Xmin, result, length_); print_task(result, LGr1, (Xmax - Xmin + 1)); int count_; //количество интервалов разбиения do { cout << "Введите количество интервалов разбиения\n"; cin >> count_; } while ((count_ > 24) || (count_ < 1) || (count_ >(Xmax - Xmin + 1))); int *LGr2 = new int[count_]; //массив левых границ для второй функции int i = 0; cout << "Введите левые границы интервалов разбиения\n" " 1-я граница - начало отрезка ("<< Xmin <<") \n\n"; LGr2[i] = Xmin; for (int j = 1; j < count_; j++) { do { cout << "Введите " << j + 1 << "-ю границу\n"; cin >> LGr2[j]; } while ((LGr2[j] < Xmin) || (LGr2[j] > Xmax)); } sort(LGr2, count_); print(LGr2, count_); int *result_final = new int[count_]; //массив полученного распределения for (int i = 0; i < count_; i++) { result_final[i] = 0; } // func2(result, LGr2, result_final, (Xmax - Xmin), Xmin, count_); func2_1(result, LGr2, result_final, (Xmax - Xmin), Xmin, count_); print_task(result_final, LGr2, count_); system("pause"); return 0; } lr6.asm .MODEL FLAT, C .CODE PUBLIC C func func PROC C arr:dword, Xmin:dword, res:dword, length_:dword push edi push esi mov eax,arr ;массив псевдослучайных чисел mov ebx,res ;массив результирующего распределения mov edx,00000001h ;счетчик для увеличения количества попаданий mov esi,00000000h ;счетчик цикла CYCLE: mov edi,[eax+4*esi] ;запись i-го элемента из массива псевдослучайных чисел sub edi,Xmin ;вычисление индекса отрезка в массиве распределения, соответствующего данному элементу add [ebx+4*edi], edx ;добавление попадания i-го элемента в отрезок inc esi ;инкрементирование счетчика cmp esi,length_ ;проверка на конец цикла jl CYCLE pop esi pop edi ret func ENDP END lr6_2.asm .MODEL FLAT, C .DATA help dword 0 .CODE PUBLIC C func2_1 func2_1 PROC C arr:dword, LGr:dword, res:dword, length_big:dword, Xmin:dword, length_:dword push edi push esi mov eax,arr ;исходный массив распределения mov ebx,res ;конечный массив распределения mov ecx,LGr ;массив левых границ mov edx,Xmin ;самая первая левая граница mov esi,00000000h ;счетчик цикла mov edi,esi ;счетчик, отвечающий за промежуток, в который нужно записывать jmp STEP CYCLE: add ecx,00000004h ;рассматриваем следующую левую границу inc edi STEP: cmp edi,length_ ;если счетчик равен длине массива левых границ (точка попала в последниий промежуток) je STEP2 cmp edx,[ecx] ;сравнение текущей точки со следующей левой границей jge CYCLE ;если больше или равна, то сравниваем следующую точку STEP2: dec edi mov ecx,[eax+4*esi] ;запись количества попаданий псевдослучайн. чисел в текущую точку во вспомогат. переменную add [ebx+4*edi],ecx ;добавление количества попаданий в промежуток, соответствующий данной точке cmp esi,length_big ;проверка, не достигнут ли конец исходного массива je END_OF_CYCLE ;если достигнут - выход из программы inc esi ;инкрементирование счетчика цикла inc edx ;инкрементирование точки mov edi,00000000h ;обнуление счетчика, отвечающего за промежуток mov ecx,LGr ;перезапись начала массива левых границ jmp STEP END_OF_CYCLE: pop esi pop edi ret func2_1 ENDP END