Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Тема 7Сравнительная оценка использования макросов и процедур.




 

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

Синтаксис макроса:

 % macro имя_какса число_параметров

< тело макроса>

% endmacro

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

Синтаксис процедуры:

procedure_name:

procedure body

 ….......................

RET

Чтобы вызвать процедуру

 ВЫЗОВ имя_процедуры

После выполнения процедуры управление передается вызывающей процедуре с помощью оператора RET

 

Разница между макросом и процедурой:

S. No. МАКРОС ПРОЦЕДУРА
01. Определение макроса содержит набор инструкций для поддержки модульного программирования. Процедура содержит набор инструкций, которые можно вызывать повторно и которые могут выполнять определенную задачу.
02. Он используется для небольшого набора инструкций, в большинстве случаев менее десяти инструкций. Он используется для большого набора инструкций, в основном более десяти инструкций.
03. В случае необходимости в памяти макросов высоки. В случае процедуры потребность в памяти меньше.
04. Инструкции / операторы CALL и RET не требуются в макросе. В процедуре требуются инструкции / операторы CALL и RET.
05. Директива ассемблера MACRO используется для определения макроса, а директива ассемблера ENDM используется для обозначения завершения тела. Директива ассемблера PROC используется для определения процедуры, а директива ассемблера ENDP используется для обозначения завершения тела.
06. Время выполнения макроса меньше, чем он выполняется быстрее процедуры. Время выполнения процедур велико, так как он выполняется медленнее, чем макрос.
07. Здесь машинный код создается несколько раз, поскольку каждый раз при вызове макроса генерируется машинный код. Здесь машинный код создается только один раз, он генерируется только один раз при определении процедуры.
08. В макросе параметр передается как часть оператора, вызывающего макрос. В процедуре параметры передаются в регистры и ячейки памяти стека.
09. Накладных часов не происходит, так как нет звонков и возвратов. Во время вызова процедуры и возврата управления вызывающей программе возникают накладные расходы.

70.               Интерфейс между ассемблером и языком С++

 

Система программирования VisualDSP++ предусматривает возможность вызывать подпрограммы на ассемблере из программ на C/C++, и наоборот, как из программ на ассемблере вызывать функции C/C++ [1]. Перед тем, как попытаться выполнить любую из этих операций, следует хорошо разобраться с моделью выполнения кода C/C++ (C/C++ run-time model), включая информацию о том, как организован стек, какие используются типы данных, и как обрабатываются аргументы (см. [4]). В конце будут рассмотрены примеры кода, показывающие смешивание в проекте кода C/C++ и ассемблера.

[Вызов подпрограмма ассемблера из программ C/C++]

Перед вызовом подпрограммы на языке ассемблера из программы на языке C/C++ создайте прототип, чтобы определить аргументы для подпрограммы на ассемблере, и интерфейс из программы C/C++ для подпрограммы на ассемблере. Хотя даже допустимо использовать функцию в C/C++ без её прототипа, создание хорошо описанных прототипов настоятельно рекомендуется практикой разработки ПО. Когда прототип опущен, компилятор не может выполнить проверку типов аргументов, а также подразумевает, что возвращаемое значение имеет тип int, и использует правила формирования кода (promotion rules) Кернигана & Ричи (K& R) вместо правил ANSI [6].

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

Модель run-time определяет некоторые регистры в качестве временных (scratch registers), и другие регистры резервируются, или они выделяются для специальных целей (dedicated registers). Scratch-регистры можно использовать в программе на языке ассемблера, не беспокоясь об их предыдущем содержании, т. е. их не надо сохранять на входе в подпрограмму и восстанавливать на выходе из подпрограммы. Если нужно больше места (или используется существующий код), и Вы хотите использовать зарезервированные регистры, то необходимо сохранять и восстанавливать их содержимое соответственно на входе и выходе подпрограммы.

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

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

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

Компилятор всегда выравнивает массивы в памяти по 32-разрядной границе слова, и компилятор нормально использует это знание при оптимизации доступа к содержимому памяти. Поэтому необходимо гарантировать, что массивы, определенные в коде ассемблера, к которым осуществляется доступ из кода C/C++, также выровнены подобным образом. Это обычно достигается вставкой перед определением массива в ассемблере директивы. align 4.

Если аргументы находятся в стеке, то они адресуются через смещение относительно указателя стека (SP) или указателя фрейма (FP) [2]. Хороший способ разобраться, как передавать аргументы через стек между программой C/C++ кодом на ассемблере - написать пустую заглушку подпрограммы на C/C++ и скомпилировать её в язык ассемблера (ниже приведен пример, как это делается). Скомпилировать код C/C++ в код ассемблера можно в среде VisualDSP IDDE, если поставить галочку Save temporary files в свойствах проекта (или использовать дополнительный ключ -save-temps командной строки компилятора [3]).

Ниже показан пример, включающий присваивание глобальной volatile-переменной [5], чтобы показать, где могут быть найдены аргументы на входе в функцию asmfunc на ассемблере.

// Код примера, показывающий интерфейс компилятора с ассемблером.

// В нем глобальным переменным global_a, global_b, global_pglobal

// просто присваиваются значения из аргументов функции. Это сделано

// для демонстрации, как на ассемблере можно получить доступ

// к аргументам функции, находящимся в стеке (тип каждой глобальной

// переменной соответствует типу одного из аргументов):

 

int global_a;

float global_b;

int * global_p;

 

// Пустая демонстрационная функция, код которой компилируется

// в код ассемблера:

int asmfunc(int a, float b, int * p)

{

// Присваивание значений из аргументов, которые будут потом

// найдены в коде ассемблера:

global_a = a;

global_b = b;

global_p = p;

 

// Значение, которое будет загружено в регистр возврата:

return 12345;

}

Когда этот пример кода C/C++ скомпилирован с опциями командной строки -save-temps и -no-annotate -O, получится следующий код на ассемблере:

. section program;

. align 2;

_asmfunc:

P0. L =. epcbss;

P0. H =. epcbss;

[P0+ 0] = R0;

R0 = 0x1234 (X);

[P0+ 4] = R1;

[P0+ 8] = R2;

RTS;

 

. _asmfunc. end:

. global _asmfunc;

. type _asmfunc, STT_FUNC;

  

. section data1;

 

. align 4;

. epcbss:

. byte _global_a[4];

. global _global_a;

. type _global_a, STT_OBJECT;

. byte _global_b[4];

. global _global_b;

. type _global_b, STT_OBJECT;

. byte _global_p[4];

. global _global_p;

. type _global_p, STT_OBJECT;

. epcbss. end:

 

 

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...