Сравнение процедур и макроопределений.
Как мы уже говорили, на Ассемблере один и тот же алгоритм программист, как правило, может реализовать как в виде процедуры, так и в виде макроопределения. Процедура будет вызываться командой call с передачей параметров по стандартным или нестандартным соглашениям о связях, а макроопределение – макрокомандой, также с заданием соответствующих параметров. Сравним эти два метода разработки программного обеспечения между собой, оценим достоинства и недостатки каждого из них.
Для изучения этого вопроса рассмотрим пример какого-нибудь простого алгоритма и реализуем его двумя указанными выше способами. Пусть, например, надо реализовать оператор присваивания ax:=max(X,Y), где X и Y – знаковые целые значения размером в слово. Сначала реализуем этот оператор в виде функции со стандартными соглашениями о связях, например, так:
Max proc near
pushbp
mov bp,sp
mov ax,[bp+6]
cmp ax,[bp+4]
jge L
mov ax,[bp+4]
L: pop bp
ret 4
Max endp
Тело нашей функции состоит из 8 команд, а каждый вызов этой функции занимает не менее 3-х команд, например:
; ax:=Max(A,B) ; ax:=Max(Z,-13)
push A push Z
push B mov ax,-13
call Max push ax
call Max
Реализуем теперь нашу функцию в виде макроопределения, например, так (не будем принимать во внимание, что это макроопределение будет неправильно работать для вызовов вида Max Z,ax ):
Max macro X,Y
local L
mov ax,X
cmp ax,Y
jge L
mov ax,Y
L:
Endm
Как видим, каждый вызов нашего макроопределения будет порождать макрорасширение в четыре команды, а каждый вызов процедуры занимает 3-4 команды, да ещё сама процедура имеет длину 8 команд. Таким образом, для коротких алгоритмов выгоднее реализовывать их в виде макроопределений.[72] Всё, конечно, меняется, если длина макрорасширения будет хотя бы 10 команд. В этом случае, если, например, в нашей программе содержится 20 макрокоманд, то в сумме во всех макрорасширениях будет 20*10=200 команд. В случае же реализации алгоритма в виде процедуры (пусть её длина тоже 10 команд) и 20-ти вызовов этой процедуры нам потребуется всего 20*4+10=90 команд. Получается, что для достаточно сложных алгоритмов реализация в виде процедуры более выгодна, что легко понять, если учесть, что процедура присутствует в памяти только в одном экземпляре, а каждая макрокоманда требует своего экземпляра макрорасширения, которое будет располагаться в программе на месте этой макрокоманды.
С другой стороны, однако, макроопределения предоставляют программисту такие уникальные возможности, как настройка алгоритма на типы передаваемых параметров, лёгкую реализацию переменного числа параметров, хорошую выдачу диагностик об ошибочных параметрах. Такие возможности весьма трудно и неэффективно реализовываются с помощью процедур.
Исходя из вышеизложенного, наиболее перспективным является гибридный метод: реализовать алгоритм в виде макроопределения, в котором производится настройка на типы параметров и выдачу диагностики, а потом, если нужно, вызывается процедура для реализации основной части алгоритма. Именно так устроены достаточно сложные макроопределения inint и outint, которыми Вы часто пользуетесь.
На этом мы закончим наше по необходимости краткое изучение макросредств языка Ассемблера, ещё раз напомним, что необходимо тщательно изучить эту тему в учебнике по языку Ассемблера.
Дата добавления: 2015-10-05; просмотров: 741;