Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции СП.doc
Скачиваний:
9
Добавлен:
01.03.2025
Размер:
1.98 Mб
Скачать

Передача параметров в потоке кода

В этом необычном методе передаваемые процедуре данные размещаются прямо в коде программы, сразу после команды CALL (как реализована процедура print в одной из стандартных библиотек процедур для ассемблера UCRLIB):

call print

db "This ASCIZ-line will be printed",0

(следующая команда)

Чтобы прочитать параметр, процедура должна использовать его адрес, который автоматически передается в стеке как адрес возврата из процедуры. Разумеется, функция должна будет изменить адрес возврата на первый байт после конца переданных параметров перед выполнением команды RET. Например, процедуру print можно реализовать следующим образом:

print proc near

push bp

mov bp,sp

push ax

push si

mov si,[bp+2] ; прочитать адрес

; возврата/начала данных

cld ; установить флаг направления

; для команды lodsb

print_readchar:

lodsb ; прочитать байт из строки,

test al,al ; если это 0 (конец строки),

jz print_done ; вывод строки закончен

int 29h ; вывести символ в AL на экран

jmp short print_readchar

print_done:

mov [bp+2],si ; поместить новый адрес возврата в стек

pop si

pop ax

pop bp

ret

print endp

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

Передача параметров в блоке параметров

Блок параметров — это участок памяти, содержащий параметры, так же как и в предыдущем примере, но располагающийся обычно в сегменте данных. Процедура получает адрес начала этого блока при помощи любого метода передачи параметров (в регистре, в переменной, в стеке, в коде или даже в другом блоке параметров). В качестве примеров использования этого метода можно назвать многие функции DOS и BIOS, например поиск файла, использующий блок параметров DTA, или загрузка (и исполнение) программы, использующая блок параметров ЕРВ.

Лекция 2.5. Макросредства языка Ассемблер

 

Макросредства - инструменты (средства) модификации текста программы во время ее трансляции.

Макросредства предназначены для облегчения написания программ на языке Ассемблер и для улучшения понимания исходного текста программы.

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

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

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

 

Макроопределение

Это описание макроса. Синтаксис макроопределения:

<имя макрокоманды> MACRO [формальные параметры]

тело макроопределения

ENDM

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

Формальные параметры позволяют копировать макрос не в неизменном виде, а с изменениями. Те величины, которые необходимо будет изменить описываются формальными параметрами.

Замечание. Имена формальных параметров локальны по отношению к макросу, т.е. они могут совпадать с именами в основной программе, макрогенератор понимает их как параметры.

Завершает макроопределение директива ENDM. !!! Не надо повторять имя макроса.

Пример 1 ; настройка сегмента данных

initds macro

mov ax, @data

mov ds, ax

endm

Размещаться макроопределения могут :

1.   В любом месте программы.

!!! Обязательно до первой ссылки на него.

2.   В отдельном файле.

Чтобы сделать доступными макроопределения в программе, необходимо в начале программы использовать директиву INCLUDE <имя файла>. При этом на этапе работы макрогенератора текст указанного файла будет вставлен полностью на место директивы.

Пример.

model small

include Mymacro.inc

. . .

Можно универсальные макрокоманды записать в один файл, в так называемую макробиблиотеку. Подключать ее с помощью директивы include.

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

PURGE <список через запятую имен макроопределений>

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

Пример. . . .

include mymacro.inc

purge outstr, initds

. . .

Макрокоманды

Макрокоманда - обращение к макроопределению. Или указание макрогенератору на то, что на указанном месте необходимо подставить тело макроопределения. Итак, одна макрокоманда заменяется на группу команд, поэтому она и наз. макро (большая).

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

<имя макроса> [<фактические параметры>]

Замечание. Фактические параметры можно разделять запятыми или пробелами.

Формальные параметры макроопределения заменяются соответствующими фактическими параметрами макрокоманды.

  • !!! i-тый фактичнский параметр соответствует i-тому формальному параметру

  • !!! Число фактических параметров должно быть равно числу формальных параметров,

  • если фактических параметров больше, то лишние игнорируются

  • если формальных больше, считается что в качестве недостающих фактических указаны пустые тексты

Процесс замещения формальных параметров фактическими называется макроподстановкой. Результат макроподстановки (т.е. полученный в результате текст называется макрорасширением.

Действия макрогенератора:

1) макрогенератор находит макроопределение с указанным именем

2) в его теле заменяет все формальные параметры фактическими

3) полученное макрорасширение подставляет в программу вместо макрокоманды

 

Сравнительный анализ процедур и макросредств

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

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

Вывод 1. Применение процедур делает код более компактным, т.е. экономим память

Но при обращении к процедуре

а) выполняется засылка параметров в регистры или стек,

б) запоминается адрес возврата

в) осуществляется переход,

г) по окончании работы процедуры восстанавливается адрес возврата,

д) очищаются регистры или стек и т.п.

Итак, при работе процедуры тратится время на переходы и передачу параметров во время выполнения программы.

!!! При замене макрокоманд на макрорасширения тоже тратится время, но это происходит на этапе трансляции, а не во время выполнения программы.

Вывод 2. Применение макросредств экономит время выполнения программы.

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

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

Вывод 3. Большие участки кода рекомендуется описывать как процедуры, а маленькие - как макроопределения.

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

Макрокоманды

Осмысленное рассмотрение данного механизма предполагает понимание смысла терминов макрокоманда и макроопределение. Макрокоманда представляет собой строку, одним из компонентов которой является символическое имя макрокоманды. Имя макрокоманды может сопровождаться параметрами. Если данная строка встречается в теле исходного текста программы, то транслятор замещает ее одной или несколькими другими строками. Какими именно строками — определяется макроопределением, которое представляет собой шаблон (описание) макрокоманды.

Таким образом, для использования макрокоманды в программе первым делом задают ее макроопределение.

Синтаксис макроопределения следующий:

имя_макрокоманды macro список_формальных_аргументов

тело макроопределения

endm

Макроопределение обрабатывается компилятором особым образом. Для того чтобы использовать описанное макроопределение, его нужно «активизировать» с помощью макрокоманды. Для этого в нужном месте исходного кода программы на основе текста заголовка макроопределения указывается следующая синтаксическая конструкция:

имя_макрокоманды список_фактических_аргументов

Макродирективы

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

Директивы повторения WHILE, REPT, IRP и IRPC предназначены для создания макросов, содержащих несколько идущих подряд одинаковых последовательностей строк. При этом возможна частичная модификация этих строк.

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

Директивы WHILE и REPT

Директивы WHILE и REPT применяются для повторения определенное количество раз некоторой последовательности строк. Эти директивы имеют следующий синтаксис:

WHILE константное_выражение

последовательность строк

ENDM

REPT константное_выражение

последовательность строк

ENDM

Пример:

N =  0

               REPT 5

               N =  N + 1

               DB   N

               ENDM

Директива IRP

Директива IRP имеет следующий синтаксис:

IRP формальный_аргумент,<строка_символов_1 строка_символов_n>

последовательность строк

ENDM

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

Пример:

               IRP  N,<3, 9, 17, 25, 28>

               DB   N

               ENDM

Директива IRPC

Директива IRPC имеет следующий синтаксис:

IRPC формальный_аргумент, строка_символов

последовательность строк

ENDM

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

Пример:

               IRPC N,345678

               DW   N

               ENDM