Федеральное государственное автономное образовательное учреждение высшего образования «СИБИРСКИЙ ФЕДЕРАЛЬНЫЙ УНИВЕРСИТЕТ» ИИФиРЭ институт Радиоэлектронная техника информационных систем кафедра СХЕМОТЕХНИКА ЦИФРОВЫХ УСТРОЙСТВ ОТЧЕТ ПО ЛАБОРАТОРНОЙ РАБОТЕ №2 Изучение функций и процедур В - 15 Руководитель Батурин Т. H. подпись, дата Студент РФ18-32Б код (номер) группы, инициалы, фамилия Поминов Е. И. подпись, дата Красноярск 2022 инициалы, фамилия СОДЕРЖАНИЕ ВВЕДЕНИЕ .............................................................................................................. 2 ЗАКЛЮЧЕНИЕ ....................................................................................................... 3 ПРИЛОЖЕНИЕ А ................................................................................................... 4 ПРИЛОЖЕНИЕ Б .................................................................................................... 5 ПРИЛОЖЕНИЕ В ................................................................................................... 7 ВВЕДЕНИЕ Цель работы: освоение инструкций ассемблера микропроцессора Cortex-M3 и программной среды Keil MDK. Задача работы: Выполнить задание (написать программу расчета среднего арифметического значения отрицательных элементов в одномерном массиве, заменить минимальный элемент в одномерном массиве на среднее арифметическое) на языке Си используя функции и указатели. Переписать программу с помощью процедур языка ассемблера. Вызвать процедуры, написанные на ассемблере в коде на языке Си. Сравнить результат выполнения функций на языке Си и на языке ассемблера. 2 ЗАКЛЮЧЕНИЕ В ходе выполнения работы, был закреплены навыки программирования на языке ассемблер. На основе проделанной работы был сделан вывод, что, язык программирования ассемблер, является языком программирования низкого уровня, вследствие чего, программы, написанные на языке ассемблер, выполняются быстрее чем программы написанные например на языке программирования СИ, но в таких программах легко запутаться, что является нежелательным влиянием, но так же есть и положительный фактор, на языке ассемблера можно осуществить разграничение выполнения действий. В программах на СИ в свою очередь, запутаться труднее, поскольку можно создавать разного рода блоки, а так же для составления разного рода условий и циклов, не обязательно использовать команды переходов. Язык СИ можно связывать с языком Ассемблер, в следствии чего, появляется более большая возможность для выполнения разного рода операций. Результат сравнения приведен на рисунке 1. 1 строка, результат выполнения в ассемблере; 5 строка, выполнение в СИ. Рисунок 1 – Инициализированные и измененные массивы 3 ПРИЛОЖЕНИЕ А Стартовой программный код Stack_Size Stack_Mem __initial_sp EQU 0x400 AREA SPACE STACK, NOINIT, READWRITE, ALIGN=3 Stack_Size ; <h> Heap Configuration ; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> ; </h> Heap_Size __heap_base Heap_Mem __heap_limit EQU 0x200 AREA HEAP, NOINIT, READWRITE, ALIGN=3 SPACE Heap_Size PRESERVE8 THUMB ; Vector Table Mapped to Address 0 at Reset AREA RESET, DATA, READONLY DCD __initial_sp DCD Reset_Handler AREA ; Reset handler Reset_Handler PROC IMPORT __main LDR BX ; ENDP ; Top of Stack ; Reset Handler |.text|, CODE, READONLY R0, =__main R0 B main_asm IMPORT EXPORT __use_two_region_memory __user_initial_stackheap __user_initial_stackheap LDR LDR LDR LDR BX R0, R1, R2, R3, LR = Heap_Mem =(Stack_Mem + Stack_Size) = (Heap_Mem + Heap_Size) = Stack_Mem ALIGN END ;************************ FILE***** (C) COPYRIGHT 4 STMicroelectronics *****END OF ПРИЛОЖЕНИЕ Б Программный код СИ #include <stdint.h> /* Заголовочный файл объявляет несколько целочисленных типов и макросов */ /* ЗАДАНИЕ: 15 Сфомировать массив элементы которогшо будут равны полусумме соседних элементов */ // Инициализируем первичный массив с числами int32_t array_original [] = {0, 2, 7, 8, 4, 9, -3, 6, 4 ,3}; // Инициализируем указатель на новый массив. Начальное значение NULL int32_t* array = NULL; // Объявляем прототип функции, которая будет выполнять задание int32_t* array_do (int32_t* array_ptr, size_t array_size); //Экспортируем функцию из Laba_2.s написанную на ассемблере. extern void Laba_2 (int32_t* array_ptr, int32_t* new_array_ptr, array_size ); size_t // Объявляем мпустой массив для передачи его адреса в функцию Laba_2 int32_t new_array [sizeof(array_original)/sizeof(int32_t)]= {0}; int main (void) { /*Вызываем функцию array_do. Функция возвратит указатель на массив соответствующий заданию. Размерность массива такая же как у оригинального массива.*/ array = sizeof(array_original)/sizeof(int32_t)); array_do(array_original, /*Вызываем функцию Laba_2, тело которой описано в файле Laba_2.s. Так как, в языке ассемблера не функций malloc() и вообще нет механизма выделения данных из кучи, то мы заранее выделяем место в оперативной памяти для обработанного массива, поэтому нам необходимо передать адрес нового массива в функцию. Размерность массива такая же как у оригинального массива.*/ Laba_2(array_original, sizeof(array_original)/sizeof(int32_t)); new_array, while (1) { } return 0; } /**************************************************************************** ****/ /* new_array[], в котором элементы равны полусумме двух соседних элементов элементов массива array_original[] .*/ /**************************************************************************** ****/ /* Функция принимает: int32_t* array_ptr - указатель на исходный массив с элементами типа int32_t 5 array_size - размер массива Функция возвращает: указатель на область памяти в котором лежит новый массив */ int32_t* array_do (int32_t* array_ptr, size_t array_size) { int32_t *new_array = NULL; int32_t k=2; int32_t m=1; int32_t b=10; int32_t j=0; //Выделяем область памяти для нового массива из кучи (heap). new_array = (int32_t*) (malloc(array_size)); for (uint32_t i = 0; i <= array_size;) { if (i==array_size) { m=array_size; j=1;} else *(new_array+i) = (*(array_ptr+(i-m))+*(array_ptr+i))/k; *(new_array+i) = (*(array_ptr+(i-m))+*(array_ptr+(i-j)))/k; i++; } return new_array; 6 ПРИЛОЖЕНИЕ В Программный код ассемблера GET stm32_EQU.s ; Объявляем сегмент кода AREA MAIN, CODE, READONLY THUMB ; Объявляем функцию main к ; R0 adress vhod ; R1 adress vihod ; R2 kolvo element ; R3 ykazatel massiv ; R4 tek element ; R5 next element ; R6 polosumma ; R7 ykazivat na razmer(delitel) Laba_2 PROC EXPORT Laba_2 PUSH {R3,R4,R5,R6,R7,R14} MOV R7,#FOUR MUL R2,R2,R7 SUB R2,#FOUR MOV R3,#NULL MOV R7,#2 while LDR R4,[R0,R3] ADD R3,#FOUR LDR R5,[R0,R3] ADD R6,R4,R5 SDIV R6,R6,R7 SUB R3,#FOUR STR R6,[R1,R3] ADD R3,#FOUR CMP R3,R2 BLT while LDR R4,[R0,R3] LDR R5,[R0,#NULL] ADD R6,R4,R5 SDIV R6,R6,R7 STR R6,[R1,R3] POP {R3,R4,R5,R6,R7,R14} BX LR ENDP ; Конец функции main END ; Конец файла 7