Файл: Поваренкин Н. В. должность, уч степень, звание подпись, дата инициалы, фамилия контрольная работа по дисциплине (Микропроцессоры, устройства и программирование).docx

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 23.11.2023

Просмотров: 33

Скачиваний: 2

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.


Встроенная функция — это функция, которая встроена непосредственно в код языка программирования и доступна для использования без необходимости написания дополнительного кода. В языке ассемблер, встроенные функции определяются в рамках макроопределения.

Необходимость создания собственных функций возникает в тех случаях, когда код программы становится слишком сложным или длинным и требует повторного использования в разных частях программы. В таких случаях, использование функций упрощает код и позволяет избежать дублирования кода. Кроме того, функции могут повышать уровень абстракции, упрощая понимание кода и давая возможность работать на более высоком уровне абстракции.

Л1.8. Функция выделения младшего байта числа. В чем необходимость ее использования в восьмиразрядных микроконтроллерах.

Функция выделения младшего байта числа — это функция, которая извлекает младший байт (младшие 8 бит) из целого числа. Восьмиразрядные микроконтроллеры обрабатывают данные и инструкции с помощью 8-битных операций, поэтому часто возникает необходимость работать с 8-битными данными или с младшими байтами целых чисел.

Использование этой функции в восьмиразрядных микроконтроллерах может быть необходимо для ускорения работы программы, экономии памяти и более эффективного использования ресурсов процессора. Кроме того, восьмиразрядные микроконтроллеры могут иметь ограниченную память, поэтому использование только нужной части целого числа (младшего байта) может сэкономить драгоценную память.

Также, младший байт часто используется в качестве адреса в памяти микроконтроллера, что делает функцию выделения младшего байта необходимой для многих операций в восьмиразрядной микроэлектронике.

Л1.9. Функция выделения старшего байта числа. Какие данных могут быть аргументом функции. Какой тип имеют числа, являющимися результатом выполнения функции.

Функция выделения старшего байта числа — это функция, которая извлекает старший байт (старшие 8 бит) из целого числа. В качестве аргумента функции может выступать любое целое число, представленное в двоичной системе счисления, такое как uint16_t или int16_t. Эти типы данных хранят целые числа в диапазоне от -32,768 до 32,767 (для int16_t) и от 0 до 65,535 (для uint16_t), используя 16 бит.


Результат выполнения функции также будет иметь тип uint8_t или int8_t, в зависимости от того, была ли функция реализована для знаковых или беззнаковых значений. Данные, полученные в результате выполнения этой функции, могут использоваться в ряде приложений, где необходимо работать только со старшей частью целочисленных значений, например, в случае, когда требуется расчет адреса ячейки памяти при работе с устройствами на шине I2C или SPI. Кроме того, функция может быть использована в алгоритмах обработки изображений, где многократно производится извлечение значения цвета красного, зеленого и синего каналов.

Л1.10. Функция выделения второго байта числа. В чем особенность этой функции при использовании в восьмиразрядных микроконтроллерах. Поясните особенности ее функционирования относительно функции выделения старшего байта числа.

Функция выделения второго байта числа — это функция, которая извлекает второй байт (биты с 8 по 15) из целого числа. Восьмиразрядные микроконтроллеры имеют ограниченную внутреннюю память и обрабатывают данные по 8 бит за раз, поэтому извлечение второго байта может быть несколько сложнее, чем извлечение старшего или младшего байта.

Особенности функционирования этой функции относительно функции выделения старшего байта заключаются в том, что второй байт является соседним с первым байтом и, следовательно, его адрес в памяти находится на 1 больше, чем адрес первого байта. Поэтому для получения значения второго байта, нужно осуществить отступ по адресу на 1 байт. Как правило, это делается с помощью операции сдвига или маскирования.

Функция выделения второго байта может использоваться, например, при работе с 16-битными значениями данных, когда нужно разделить число на две половины и произвести над ними отдельные операции. Также, эта функция может быть полезной при работе с устройствами на шине I2C или SPI, где данные передаются в виде последовательности байтов.

Л1.11. Функция вычисления порядка двоичного числа (EXP2). Поясните назначение и область применения функции. Возможно ли применять функцию для установки разрядов (присваивания логической единицы) данных, хранящихся в любых регистрах микроконтроллера?

EXP2 — это функция, которая вычисляет порядок двоичного числа. Назначение этой функции заключается в том, чтобы определить позицию самого старшего бита (номер бита, начиная с нулевого индекса), который установлен в 1 в двоичном представлении числа. Это может быть полезно для манипуляций со значениями битов в регистрах, например, чтения или записи в конкретные биты.



Область применения функции EXP2 может быть очень широкой, потому что она может использоваться во многих областях, где требуется работа с двоичными числами и разрядами. Это может включать в себя программирование микроконтроллеров, обработку данных в компьютерных сетях и различные другие задачи.

Нет, функция EXP2 не может использоваться для установки разрядов (присваивания логической единицы) данных, хранящихся в любых регистрах микроконтроллера. Эта функция предназначена только для вычисления порядка двоичного числа, и ее использование для установки битов может привести к неопределенному поведению программы и ошибкам в работе микроконтроллера. Для установки битов в регистрах микроконтроллера должны использоваться специальные инструкции или функции, которые предоставляются поставщиком микроконтроллера.

Л1.12. Функция вычисления целой части числа эквивалентно его десятичному представлению. Укажите диапазон применения аргумента функции. Опишите правила округления двоичного числа до целого. Запишите примеры написания программного кода, содержащего указанную функцию.

Аргумент функции вычисления целой части числа может быть любым числом с плавающей точкой, включая отрицательные и дробные значения. Однако в некоторых языках программирования (например, в C) функция может возвращать непредсказуемые результаты для отрицательных чисел.

Правила округления двоичного числа до целого следующие:

1. Если дробная часть числа меньше 0,5, то число округляется до меньшего целого.

2. Если дробная часть числа больше или равна 0,5, то число округляется до большего целого.

3. Если дробная часть числа равна 0,5, то число округляется до ближайшего четного целого.

Например, число 3,8 будет округлено до 4, а число 3,5 будет округлено до 4, а число 3,2 будет округлено до 3.

Примеры программного кода:

Python:

def integer_part(num):

return int(num)

print(integer_part(3.8)) # 3

C++:

#include

#include

int main() {

double num = 3.8;

int int_part = floor(num); // округление до меньшего целого

std::cout << int_part << std::endl; // 3

return 0;

}

Л1.13. Функция перевода отрицательного числа в положительное. Поясните применение функции и диапазон аргументов, для которых функция имеет смысл. Поясните представление отрицательного числа в качестве аргумента. Переводится отрицательных аргумент функции до ее выполнения в дополнительных код? Приведите программный код, поясняющий применение указанной функции.

Функция перевода отрицательного числа в положительное применяется в различных алгоритмах, например, для обработки математических операций или при работе с числами в различных системах счисления. Диапазон аргументов функции зависит от типа данных, используемых в программе.

Отрицательное число представляется в компьютере в дополнительном коде, где старший бит является знаковым. Чтобы получить положительное число из отрицательного, необходимо инвертировать все биты числа и добавить единицу.

Пример программного кода на языке C++:

#include

using namespace std;

int abs(int num) { // функция перевода отрицательного числа в положительное

if (num < 0) { // если число отрицательное

num = num + 1; // инвертируем все биты и добавляем единицу

}

return num;

}

int main() {

int num = -5;

cout << "Аргумент функции: " << num << endl;

cout << "Результат работы функции: " << abs(num) << endl;

return 0;

}

В данном примере функция abs принимает аргумент num типа int, проверяет, является ли число отрицательным, и при необходимости переводит его в положительное. Затем возвращается результат работы функции, который выводится на экран. В данном случае, на экране будет выведено:

Аргумент функции: -5

Результат работы функции: 5

Л1.14. Дайте понятие директиве. Поясните механизм их действия директив и их использование в программном коде.

Директива в программировании — это инструкция, которая предписывает компилятору или интерпретатору выполнять определенное действие в процессе компиляции или выполнения программы. Директивы используются в большинстве языков программирования, включая C++, C#, Python и другие.

Директивы влияют на процесс компиляции или выполнения кода путем изменения поведения компилятора или интерпретатора. Например, директива #include в C++ говорит компилятору включить содержимое указанного файла в программный код перед компиляцией.

Другой пример директивы - это директива препроцессора #define в языке C++, которая позволяет определять символические константы, которые заменятся на определенное значение в процессе компиляции.

Директивы могут также использоваться для управления компиляцией, так как они позволяют разработчикам указывать компилятору определенные параметры и опции. Например, директива #pragma в C++ позволяет контролировать поведение компилятора.

В целом, директивы предоставляют разработчикам возможность легко взаимодействовать с компилятором или интерпретатором, контролируя его поведение и параметры.

Л1.15. Директива подключения дополнительного файла к программе. Опишите результат ее применения. Поясните процедуру добавления подключаемого файла к программе, написанной пользователем. Приведите программный код, поясняющий применения директивы. Откройте файл с листингом программы и продемонстрируйте особенность подключения дополнительного файла к файлу основной программы.

Директива подключения дополнительного файла к программе — это инструкция, которая указывает компилятору, какие файлы должны быть включены в процесс компиляции программы. Эти файлы могут содержать дополнительные функции, переменные или другие элементы, необходимые для работы программы.

Процедура добавления подключаемого файла к программе:

1. Написание кода в дополнительном файле. Этот файл должен содержать необходимые функции и/или переменные.

2. В основном файле программы добавить директиву include и имя файла, который нужно включить.

Например, допустим создание файла "myfunctions.h" с функцией "addTwoNumbers":

// myfunctions.h

int addTwoNumbers(int a, int b) {

return a + b;

}

И основной файл программы "main.cpp":

// main.cpp

#include

#include "myfunctions.h"

using namespace std;

int main() {

int num1 = 5;

int num2 = 10;

int sum = addTwoNumbers(num1, num2);

cout << "The sum is " << sum << endl;

return 0;

}

В этом примере, мы включили файл "myfunctions.h" в нашу программу, и использовали функцию "addTwoNumbers" в основном файле.

Особенность подключения дополнительного файла к файлу основной программы заключается в том, что все функции и переменные, определенные в подключаемом файле, будут доступны в основной программе. Также возможно подключение нескольких файлов, если это необходимо.

Результатом применения директивы подключения дополнительного файла к программе будет возможность использования функций и переменных, определенных в этом файле, в основной программе. Компилятор включит код из файла в итоговую программу, за исключением случаев, когда используется функция-заглушка, которая ссылается на код, определенный в отдельном файле.

Л1.16. Директива объявления сегмента программного кода. Опишите назначение директивы. Укажите условия ее использования. Поясните, в каких случаях директива может не применяться. Приведите пример ее использования в программном коде.

Директива объявления сегмента программного кода (например, ".text" в языке ассемблера) предназначена для определения области памяти, в которой будет храниться исполняемый код программы. Она указывает компилятору, что следующий блок кода должен быть расположен в определенном сегменте памяти (например, флэш-памяти).

Директиву нужно использовать в тех случаях, когда необходимо явно задать расположение программного кода в памяти. Это может быть важно, например, при написании программы для встраиваемой системы, где размер доступной памяти может быть ограничен.

В случаях, когда компилятор самостоятельно выбирает место расположения кода в памяти, директива не обязательна и может не применяться.

Пример использования директивы в программном коде на языке ассемблера для микроконтроллера AVR:

```

.text ; объявление сегмента кода

.global main ; объявление глобальной метки

main: ; определение метки

ldi r16, 0x55 ; загрузка значения 0x55 в регистр R16

out DDRB, r16 ; запись значения регистра R16 в регистр DDRB

loop:

; здесь находится основной код программы

jmp loop ; бесконечный цикл

```

В приведенном примере с помощью директивы ".text" определяется сегмент памяти, в котором будет храниться исполняемый код программы. Затем объявляется глобальная метка "main", которая будет использоваться для обращения к определенному блоку кода. Внутри блока кода происходит запись заданного значения в регистр DDRB, а затем запускается бесконечный цикл.

Л1.17. Директива объявления сегмента данных. Опишите назначение директивы. Укажите условия ее использования. Поясните, в каких случаях директива может не применяться. Приведите пример ее использования в программном коде.

Директива объявления сегмента данных используется в языках программирования для определения областей памяти программы, которые будут содержать переменные и массивы данных.

Назначение директивы - определить размер и расположение сегмента данных. Это позволяет компилятору создавать объектный код, который будет знать, какие переменные и массивы данных нужно выделять и где они должны храниться в памяти.

Директиву объявления сегмента данных следует применять в случаях, когда в программе используются переменные и массивы данных, которые должны храниться в памяти, а не на стеке.

Директива может не применяться в случаях, когда в программе не используются переменные или массивы, которые нужно сохранять в памяти.

Пример использования директивы объявления сегмента данных в программном коде на языке ассемблера:

; объявление сегмента данных

data_segment segment

message db 'Hello, World!', 0

number dw 42

data_segment ends

; начало программы

code_segment segment

start:

; вывод сообщения на экран

mov ah, 9

lea dx, message

int 21h

; вывод значения на экран

mov ax, number

add ax, 1

mov cx, ax

mov ah, 2

mov dl, ' '

int 21h

; завершение программы

mov ah, 4Ch

int 21h

code_segment ends

end start

В этом примере директива объявления сегмента данных используется для определения области памяти, содержащей переменные "message" и "number". Переменная "message" является строкой, заканчивающейся нулевым символом, а переменная "number" - 16-битным целым числом. В кодовом сегменте, определенном далее в программе, эти переменные используются для вывода сообщения и значения на экран.

Л1.18. Директива резервирования байтов в памяти данных. Поясните механизм адресации к зарезервированным байтам.

Директива резервирования байтов в памяти данных предназначена для выделения заданного количества байтов в памяти компьютера для последующего использования в программе. Эти зарезервированные байты могут быть использованы для хранения данных, которые будут созданы или получены в процессе выполнения программы.

Механизм адресации к зарезервированным байтам осуществляется с помощью указателя. При объявлении переменной с использованием директивы резервирования памяти, компилятор выделяет блок памяти нужного размера и возвращает указатель на начало этого блока. Указатель затем можно использовать для доступа к каждому байту в зарезервированном блоке памяти.

Например, следующий код на языке C++ иллюстрирует механизм адресации к зарезервированным байтам:

#include

using namespace std;

int main() {

char* buffer;

int bufferSize = 10;

//резервируем 10 байтов памяти

buffer = new char[bufferSize];

//заполняем буфер нулями

for (int i = 0; i < bufferSize; i++) {

buffer[i] = 0;

}

//печатаем содержимое буфера

for (int i = 0; i < bufferSize; i++) {

cout << (int)buffer[i] << " ";

}

//очищаем память

delete[] buffer;

return 0;

}

В этом примере мы создаем указатель buffer на тип char и резервируем 10 байтов памяти, используя оператор new. Затем мы заполняем буфер нулями и печатаем его содержимое. Циклы, используемые для заполнения и печати буфера, проходят по каждому байту в зарезервированном блоке, используя указатель buffer и индексацию.

Наконец, мы освобождаем зарезервированную память с помощью оператора delete[].

Таким образом, механизм адресации к зарезервированным байтам состоит в том, что мы используем указатель на начало зарезервированного блока памяти и индексацию, чтобы получить доступ к каждому байту в этом блоке.

Л1.19. Директива записи констант. Поясните механизм ее использования. Укажите максимальное количество констант, в отношении которых возможно применение директивы.

Директива записи констант — это инструкция, используемая в языках программирования, чтобы указать компилятору, что определенное значение не будет изменяться во время выполнения программы. Это можно сделать с помощью ключевых слов const или final.

Механизм использования директивы const/final довольно простой. При объявлении переменной с ключевым словом const/final она будет доступна только для чтения, то есть ее значение не может быть изменено ни в программе, ни извне в течение выполнения, что гарантирует сохранение неизменности. Это особенно полезно при работе со значениями, которые должны оставаться постоянными, такими как числовые константы или значения для настроек программы.

У каждого языка программирования свои правила для использования директивы const/final. Некоторые языки позволяют использовать их для любой типа данных, а некоторые - только для частных случаев, например, для строк или числовых значений. Максимальное количество констант, которые можно объявить с помощью директивы const/final, зависит от используемого языка программирования и ограничений операционной системы.

Л1.20. Директива определения начального адреса сегмента. Поясните механизм ее использования. Возможно ли увеличение количества тактов выполнения программного кода в зависимости от количества ячеек, на которое он сдвинут в памяти программ. Приведите программный код, поясняющий применения директивы.

Директива определения начального адреса сегмента (аббревиатура SEGMENT в ассемблере) используется для указания начального адреса различных частей программы, например, сегментов кода, данных и стека. Эта директива позволяет компилятору знать, где будут располагаться определенные части программы в памяти, и как обращаться к этим частям.

Механизм использования директивы SEGMENT в ассемблере заключается в том, что она указывает на начальный адрес различных сегментов программы. Например, для сегмента кода может быть указан начальный адрес 0000h, а для сегмента данных – 1000h. Компилятор знает, что код будет находиться в сегменте с адресом 0000h, а данные – в сегменте с адресом 1000h. При выполнении программы процессор обращается к соответствующим адресам, чтобы загрузить необходимые данные и выполнить нужные действия.

Возможно увеличение количества тактов выполнения программного кода в зависимости от количества ячеек, на которое он сдвинут в памяти программ. Это связано с тем, что при сдвиге кода в памяти нужно учитывать изменение адресов, которые будут использоваться для обращений к данным и выполнения других действий. Если адреса не будут изменены соответствующим образом, процессор может обратиться к неправильным ячейкам памяти, что приведет к непредсказуемым результатам.

Пример программного кода с применением директивы SEGMENT:

DATA SEGMENT

NUMBER DW 1000

MESSAGE DB 'Hello, world!'

DATA ENDS

CODE SEGMENT

ASSUME CS:CODE, DS:DATA

START:

MOV AX, DATA

MOV DS, AX

MOV DX, OFFSET MESSAGE

MOV AH, 09H

INT 21H

MOV AX, NUMBER

ADD AX, 100

MOV NUMBER, AX

MOV AH, 4CH

INT 21H

CODE ENDS

END START

В этом примере используются два сегмента: DATA для данных и CODE для кода. В сегменте DATA определены переменная NUMBER и строковая константа MESSAGE. В сегменте CODE содержится код программы, который выводит на экран сообщение и добавляет 100 к переменной NUMBER. Команды MOV AX, DATA и MOV DS, AX устанавливают базовый адрес сегмента DATA, который будет использоваться при обращении к данным. Команда MOV DX, OFFSET MESSAGE загружает в регистр DX адрес строки сообщения. Команда INT 21H вызывает функцию BIOS для вывода сообщения на экран. Затем происходит работа с переменной NUMBER: она загружается в регистр AX, добавляется 100 и сохраняется обратно в переменную NUMBER. В конце программы вызывается функция INT 21H с параметром 4CH, что приводит к завершению работы программы.

Л1.21. Директива присвоения символического имени регистрам. Опишите принцип функционирования процедуры. Поясните ограничения накладываемые на использовании процедуры по отношению регистрам, используемым в микроконтроллере. Приведите программный код, поясняющий применения директивы

Принцип функционирования процедуры присвоения символического имени регистрам заключается в том, что мы можем присвоить определенным регистрам символические имена, которые будут использоваться в программе вместо номеров регистров.

Например, вместо того чтобы использовать номер регистра R0, мы можем присвоить ему символическое имя TEMP. Теперь в программе мы будем использовать имя TEMP вместо номера регистра R0.

Ограничения, накладываемые на использование процедуры по отношению к регистрам, используемым в микроконтроллере, связаны с тем, что некоторые регистры обязательно должны быть зарезервированы для определенных функций, и их нельзя использовать для других целей.

Например, регистры R0-R7 в архитектуре AVR зарезервированы для хранения временных данных и аргументов функций, поэтому не следует использовать их для хранения другой информации.

Пример программного кода с использованием директивы присвоения символического имени регистру R0:

.DEVICE ATmega328P

.EQU TEMP = R0 ; Присваиваем регистру R0 символическое имя TEMP

LDI TEMP, 0x0F ; Загружаем значение 0x0F в регистр TEMP

В этом примере мы присваиваем регистру R0 символическое имя TEMP с помощью директивы .EQU. Затем мы загружаем значение 0x0F в регистр TEMP с помощью команды LDI, используя его символическое имя вместо номера регистра.

Л1.22. Директива задания символьного имени константе. Опишите принцип функционирования процедуры. Укажите формат переменных, используемых в директиве. Поясните синтаксис написания директивы. Приведите программный код, поясняющий применения директивы.

Директива задания символьного имени константе (или директива #define) — это инструкция препроцессору языка программирования C и C++, которая позволяет определять символьные имена для констант и заменять их весьма полезно в программе.

Принцип функционирования процедуры заключается в том, что препроцессор заменяет каждое упоминание символьного имени константы в программе на ее значение, указанное при определении директивы #define. Таким образом, на этапе компиляции программы все имена констант заменяются на их значения, что делает код более читабельным и экономит место в памяти.

Формат переменных, используемых в директиве:

#define имя_константы значение

где имя_константы - символьное имя константы, а значение - ее значение.

Синтаксис написания директивы:

#define PI 3.14159

где PI - имя константы, а 3.14159 - ее значение.

Пример программного кода:

#include

#define PI 3.14159

#define AGE 25

#define NAME "John"

int main()

{

printf("PI = %.2f\n", PI);

printf("Age = %d\n", AGE);

printf("Name = %s\n", NAME);

return 0;

}

Результат выполнения программы:

PI = 3.14

Age = 25

Name = John

В данном примере директивы #define определяют символьные имена для констант PI, AGE и NAME, которые затем используются в функции printf(). Компилятор заменит эти имена на соответствующие значения при компиляции программы.