Реферат: Структура и реализация макроязыков - Refy.ru - Сайт рефератов, докладов, сочинений, дипломных и курсовых работ

Структура и реализация макроязыков

Рефераты по информатике » Структура и реализация макроязыков

Московский Государственный Институт Электроники и Математики


кафедра САПР


Ре­фе­рат


Те­ма III


Раз­ра­бот­ка об­ще­го про­грам­мно­го обес­пе­че­ния


За­да­ние 3.2


Вы раз­ра­ба­ты­вае­те мак­ро­язык для сис­те­мы. Обос­нуй­те эф­фек­тив­ность ис­поль­зо­ва­ния мак­ро­средств. Ка­кие ти­пы мак­ро­средств до­пус­ка­ют­ся ва­шим мак­ро­язы­ком? Сфор­му­ли­руй­те ме­то­ды по­строе­ния про­грам­мы, об­ра­ба­ты­ваю­щей мак­ро­язык


Преподаватель:


Зайцева Л. В.


Студент:


Омельченко С. А.


МАК­РО­ЯЗЫК И МАК­РО­ПРО­ЦЕС­СОР


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

Мак­ро­ко­ман­ды (час­то на­зы­вае­мые мак­ро или мак­рос) яв­ля­ют­ся од­но­строч­ны­ми со­кра­ще­ния­ми для груп­пы ко­манд. Ис­поль­зуя мак­ро­ко­ман­ду, про­грам­мист по су­ще­ст­ву оп­ре­де­ля­ет од­ну “ко­ман­ду” для пред­став­ле­ния не­ко­то­рой по­сле­до­ва­тель­но­сти ко­манд.

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


МАК­РО­КО­МАН­ДЫ


В сво­ей про­стей­шей фор­ме мак­ро­ко­ман­да пред­став­ля­ет со­бой со­кра­ще­ние для обо­зна­че­ния по­сле­до­ва­тель­но­сти опе­ра­ций


Рас­смот­рим сле­дую­щий на­бор ко­манд, взя­тый из мак­ро­язы­ка IDE для Borland C++ вер­сии 3.1 (TEMC). Рас­смот­рим сле­дую­щую про­грам­му, на­пи­сан­ную с по­мо­щью этих опе­ра­ций


При­мер 1


.

.

.

SetPrevPos;

FixScreenPos;

PageScreenUp;

FixCursorPos;

.

.

.

SetPrevPos;

FixScreenPos;

PageScreenUp;

FixCursorPos;

.

.

.


В при­ве­ден­ной про­грам­ме по­сле­до­ва­тель­ность ко­манд


SetPrevPos;

FixScreenPos;

PageScreenUp;

FixCursorPos;


встре­ча­ет­ся два­ж­ды.


Ап­па­рат мак­ро­ко­манд по­зво­ля­ет при­сво­ить этой по­сле­до­ва­тель­но­сти имя и ис­поль­зо­вать это имя вме­сто нее. Мож­но так­же оп­ре­де­лить не­ко­то­рый мак­ро­язык, по­зво­ляю­щий рас­смат­ри­вать дан­ную кон­ст­рук­цию, как оп­ре­де­ле­ние и в даль­ней­шем ис­поль­зо­вать это оп­ре­де­ле­ние.


Фак­ти­че­ски, мак­ро­про­цес­сор пред­став­ля­ет со­бой отдельный язы­ко­вой про­цес­сор со сво­им соб­ст­вен­ным язы­ком.


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


MACRO <macro name>

-----------------

-----------------

-----------------

END;


Псев­до­ко­ман­да MACRO - пер­вая стро­ка оп­ре­де­ле­ния - оп­ре­де­ля­ет сле­дую­щий за ней иден­ти­фи­ка­тор, как имя мак­ро­ко­ман­ды. Вслед за этой стро­кой рас­по­ла­га­ет­ся по­сле­до­ва­тель­ность ко­манд, на­зы­вае­мых “те­лом мак­ро­оп­ре­де­ле­ния”. Оп­ре­де­ле­ние за­кан­чи­ва­ет­ся стро­кой с псев­до­ко­ман­дой END.


Ес­ли мак­ро­ко­ман­да оп­ре­де­ле­на, то ис­поль­зо­ва­ние име­ни со­от­вет­ст­вую­щей мак­ро­ко­ман­ды в ка­че­ст­ве мне­мо­ни­ки ко­да в про­грам­ме эк­ви­ва­лент­но ис­поль­зо­ва­нию со­от­вет­ст­вую­щей по­сле­до­ва­тель­но­сти ко­манд. Ес­ли по­вто­ряю­щей­ся по­сле­до­ва­тель­но­сти ко­манд дать имя “MacPageUp”, то наш при­мер мож­но бу­дет пе­ре­пи­сать сле­дую­щим об­ра­зом:


Ис­ход­ный текст


Рас­ши­ре­ние ис­ход­но­го тек­ста

MACRO MacPageUp

SetPrevPos;

FixScreenPos;

PageScreenUp;

FixCursorPos;

END;

.

.

.

MacPageUp

.

.

.

MacPageUp

.

.

.


.

.

.

SetPrevPos;

FixScreenPos;

PageScreenUp;

FixCursorPos;

.

.

.

SetPrevPos;

FixScreenPos;

PageScreenUp;

FixCursorPos;

.

.

.



В дан­ном слу­чае мак­ро­про­цес­сор за­ме­ня­ет ка­ж­дую мак­ро­ко­ман­ду (мак­ро­вы­зов) стро­ка­ми:


SetPrevPos;

FixScreenPos;

PageScreenUp;

FixCursorPos;


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


ОПЕ­РА­ТО­РЫ МАК­РО­КО­МАНД


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


Рас­смот­рим сле­дую­щую про­грам­му:


При­мер 2:


.

.

.

SetPrevPos;

MoveToMark(1);

CenterFixScreenPos;

.

.

.

SetPrevPos;

MoveToMark(2);

CenterFixScreenPos;

.

.

.


В дан­ном слу­чае по­сле­до­ва­тель­но­сти ко­манд очень по­хо­жи, но не аб­со­лют­но иден­тич­ны. В пер­вой по­сле­до­ва­тель­но­сти ис­поль­зу­ет­ся опе­ранд “1”, а во вто­ром - опе­ранд “2”. Мож­но счи­тать, что они вы­пол­ня­ют од­ну и ту же опе­ра­цию с пе­ре­мен­ным па­ра­мет­ром, или опе­ран­дом. Та­кой па­ра­метр на­зы­ва­ют “опе­ран­дом мак­ро­ко­ман­ды” или “фор­маль­ным па­ра­мет­ром”, и он обыч­но объ­яв­ля­ет­ся в той же стро­ке, где и имя мак­ро­са. В слу­чае ра­бо­ты с язы­ком мак­ро­ас­семб­ле­ра, он обыч­но по­ме­ча­ет­ся сим­во­лом &, что от­ли­ча­ет его как сим­вол мак­ро­язы­ка от сим­во­лов ас­семб­ле­ра. В на­шем слу­чае, фир­ма Бор­ланд не пре­ду­смот­ре­ла в сво­ем мак­ро­язы­ке ра­бо­ты с мак­ро­опе­ран­да­ми, од­на­ко мож­но пред­по­ло­жить, что ес­ли бы мак­ро­оп­ре­де­ле­ния в язы­ке TEMC мог­ли бы об­ра­ба­ты­вать по­доб­ную си­туа­цию, то фор­мат мак­ро­оп­ре­де­ле­ния мог бы вы­гля­деть сле­дую­щим об­ра­зом:


MACRO <macro name>(<paramlist>)

-----------------

-----------------

-----------------

END;


где <paramlist> это пе­ре­чис­ле­ние че­рез за­пя­тую всех опе­ран­дов мак­ро­са.


Пре­ды­ду­щая про­грам­ма в та­ком слу­чае мо­жет быть пе­ре­пи­са­на сле­дую­щим об­ра­зом:


Ис­ход­ный текст


Рас­ши­ре­ние ис­ход­но­го тек­ста

MACRO MacGoto(labelno)

SetPrevPos;

MoveToMark(labelno);

CenterFixScreenPos;

END;


.

.

.

MacGoto(1)

.

.

.

MacGoto(2)

.

.

.



.

.

.

SetPrevPos;

MoveToMark(1);

CenterFixScreenPos;

.

.

.

SetPrevPos;

MoveToMark(2);

CenterFixScreenPos;

.

.

.

Сле­ду­ет за­ме­тить, что мак­ро­ко­ман­да мо­жет иметь и бо­лее од­но­го опе­ран­да. Ка­ж­дый опе­ранд дол­жен при этом со­от­вет­ст­во­вать фор­маль­но­му па­ра­мет­ру в стро­ке оп­ре­де­ле­ния име­ни мак­ро­са.


Рас­смот­рим сле­дую­щий при­мер:


При­мер 3:


.

.

.

ScrollScreenDown;

ScrollScreenLeft(0);

FixCursorPos;

.

.

.

ScrollScreenUp;

ScrollScreenLeft(1);

FixCursorPos;

.

.

.


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


Ис­ход­ный текст


Рас­ши­ре­ние ис­ход­но­го тек­ста

MACRO MacMove(cmd,left)

cmd;

ScrollScreenLeft(left);

FixCursorPos;

END;

.

.

.

MacMove(ScrollScreenDown,0)

.

.

.

MacMove(ScrollScreenUp,1)

.

.

ScrollScreenDown;

ScrollScreenLeft(0);

FixCursorPos;

.

.

.

ScrollScreenUp;

ScrollScreenLeft(1);

FixCursorPos;

.

.

.

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


MacMove(cmd=ScrollScreenUp,left=1)


УС­ЛОВ­НОЕ МАК­РО­РАС­ШИ­РЕ­НИЕ


Ино­гда воз­ни­ка­ют по­треб­но­сти из­ме­нять по­ря­док команд мак­ро­рас­ши­ре­ния внут­ри мак­ро­са.


Рас­смот­рим сле­дую­щую про­грам­му:


При­мер 4:


.

.

.

ScrollScreenLeft(1);

LiteralChar('-');

.

.

.

ScrollScreenDown;

ScrollScreenLeft(2);

LiteralChar('*');

.

.

.


В этом при­ме­ре не толь­ко па­ра­мет­ры, но и ко­ли­че­ст­во ко­манд - пе­ре­мен­ная ве­ли­чи­на. Эта про­грам­ма мо­жет быть за­пи­са­на сле­дую­щим об­ра­зом:

.

.

.

MACRO Mac1(p1,left,chr)

IF p1==1 THEN

ScrollScreenDown;

ENDIF

ScrollScreenLeft(2);

LiteralChar('*');

END


.

.

.

Mac1(1,2,’-’)

.

.

.

Mac1(0,1,’*’)

.

.

.

.

.

.

ScrollScreenLeft(1);

LiteralChar('-');

.

.

.

ScrollScreenDown;

ScrollScreenLeft(2);

LiteralChar('*');

.

.

.



Ком­би­на­ция IF...THEN...ELSE яв­ля­ет­ся мак­ро­мет­ка­ми или сим­во­ла­ми сле­до­ва­ния и не по­яв­ля­ют­ся в вы­ход­ном тек­сте мак­ро­про­цес­со­ра. В мак­ро­язы­ке так­же мо­гут быть пре­ду­смот­ре­ны псев­до­ко­ман­ды ус­лов­но­го и без­ус­лов­но­го пе­ре­хо­да на псев­до-мет­ку, с ко­то­рой мак­ро­про­цес­сор про­дол­жит об­ра­бот­ку тек­ста про­грам­мы. Точ­но так же, как и в слу­чае вы­пол­не­ния про­грам­мы, опе­ра­то­ры пе­ре­хо­дов слу­жат для ука­за­ния вы­пол­не­ния опе­ра­то­ров про­грам­мы, опе­ра­то­ры мак­ро-пе­ре­хо­дов слу­жат для ука­за­ния по­ряд­ка компиляции тек­ста про­грам­мы. Это да­ет воз­мож­ность в про­цес­се рас­ши­ре­ния по­лу­чать кон­крет­ные ва­ри­ан­ты по­сле­до­ва­тель­но­стей ко­манд, со­от­вет­ст­вую­щие дан­но­му слу­чаю при­ме­не­ния мак­ро­ко­ман­ды. Вы­пол­не­ние пе­ре­хо­дов и про­ве­рок внут­ри вы­пол­няе­мо­го ко­да уве­ли­чи­ва­ет его раз­мер и вре­мя вы­пол­не­ния, в то вре­мя, как про­вер­ка и пе­ре­хо­ды в мак­ро­сах про­ис­хо­дят на ста­дии ком­пи­ля­ции и по­это­му не тре­бу­ют за­трат вре­ме­ни при вы­пол­не­нии ко­да. Эта воз­мож­ность из­би­ра­тель­ной вы­бор­ки нуж­ных час­тей тек­ста яв­ля­ет­ся од­ним из са­мых мощ­ных средств в сис­тем­ном про­грам­ми­ро­ва­нии.


МАК­РО­ВЫ­ЗО­ВЫ ВНУТ­РИ МАК­РО­ОП­РЕ­ДЕ­ЛЕ­НИЯ


По­сколь­ку мак­ро­оп­ре­де­ле­ния яв­ля­ют­ся, по су­ти, “со­кра­ще­ния­ми” для по­сле­до­ва­тель­но­сти ко­манд, то по­лез­ным свой­ст­вом бы­ла бы воз­мож­ность про­из­во­дить та­кие “со­кра­ще­ния” внут­ри са­мих мак­ро­оп­ре­де­ле­ний.


При­мер 5:


.

.

.

MACRO Mac1

SetPrevPos;

CursorCharRight;

END

.

.

.

MACRO Mac2

Mac1

Mac1

END

.

.

.


Внут­ри мак­ро­оп­ре­де­ле­ния Mac2 два­ж­ды про­ис­хо­дит ссыл­ка на мак­ро­оп­ре­де­ле­ние Mac1. Это по­мог­ло нам умень­шить дли­ну мак­ро­оп­ре­де­ле­ния Mac2 и сде­ла­ло его бо­лее лег­ким для по­ни­ма­ния. Та­кое ис­поль­зо­ва­ние мак­ро­средств при­во­дит к мак­ро­рас­ши­ре­ни­ям на не­сколь­ких уров­нях вло­жен­но­сти, на­при­мер:


Ис­ход­ный текст Рас­ши­ре­ние ис­ход­но­го тек­ста (уро­вень 1) Рас­ши­ре­ние ис­ход­но­го тек­ста (уро­вень 2)

.

.

.

MACRO Mac1

SetPrevPos;

CursorCharRight;

END


MACRO Mac2

Mac1

Mac1

END

.

.

.


Mac2


.

.

.



MACRO Mac2

SetPrevPos;

CursorCharRight;

SetPrevPos;

CursorCharRight;

END


Mac2


.

.

.



SetPrevPos;

CursorCharRight;

SetPrevPos;

CursorCharRight;

.

.

.


Мак­ро­вы­зо­вы, внут­ри мак­ро­оп­ре­де­ле­ний мо­гут вклю­чать не­сколь­ко уров­ней. На­при­мер, ко­ман­да Mac2 мог­ла бы быть вы­пол­не­на внут­ри дру­го­го мак­ро­оп­ре­де­ле­ния. Фак­ти­че­ски, та­кие сред­ст­ва, как мак­ро-пе­ре­хо­ды да­ют воз­мож­ность лю­бое чис­ло раз об­ра­щать­ся к лю­бо­му мак­ро­оп­ре­де­ле­нию, и да­же к са­мо­му се­бе. Та­кие вы­зо­вы на­зы­ва­ют­ся ре­кур­сив­ны­ми.


МАК­РО­ОП­РЕ­ДЕ­ЛЕ­НИЯ В МАК­РО­ОП­РЕ­ДЕ­ЛЕ­НИ­ЯХ


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


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


При­мер 6:


.

.

.

МАСRO DEFINE sub

.......

.......

MACRO sub(param)

......

......

sub(param)

......

......

END

......

......

END


Поль­зо­ва­тель мо­жет об­ра­тить­ся к это­му мак­ро­оп­ре­де­ле­нию сле­дую­щим об­ра­зом:


DEFINE(cos)


оп­ре­де­ляя та­ким об­ра­зом но­вое мак­ро­оп­ре­де­ле­ние с име­нем cos, к ко­то­ро­му впо­след­ст­вии мож­но об­ра­щать­ся сле­дую­щим об­ра­зом:


cos(х)


и мак­ро­про­цес­сор сге­не­ри­ру­ет со­от­вет­ст­вую­щую по­сле­до­ватель­ность вы­зо­ва функ­ции.


РЕА­ЛИ­ЗА­ЦИЯ


Та­ким об­ра­зом, на­ми был опи­сан ва­ри­ант реа­ли­за­ции мак­ро­язы­ка. Рас­смот­рим ме­тод реа­ли­за­ции мак­ро­язы­ка. В ка­че­ст­ве при­ме­ра возь­мем клас­си­че­ский язык мак­ро­ас­семб­ле­ра.


ПО­СТА­НОВ­КА ЗА­ДА­ЧИ


Лю­бой про­цес­сор мак­ро­ко­манд дол­жен ре­шать сле­дую­щие че­ты­ре ос­нов­ные за­да­чи:


Рас­по­зна­вать мак­ро­оп­ре­де­ле­ния. Про­цес­сор мак­ро­ко­манд дол­жен рас­по­зна­вать мак­ро­оп­ре­де­ле­ния, вы­де­ляе­мые со­от­вет­ст­вую­щи­ми псев­до­ко­ман­да­ми. В язы­ке мак­ро­ас­семб­ле­ра эти­ми псев­до­опе­ра­то­ра­ми яв­ля­ют­ся псев­до­ко­ман­ды MACRO и MEND. Эта за­да­ча мо­жет быть ус­лож­не­на тем, что внут­ри мак­ро­оп­ре­де­ле­ний мо­гут встре­чать­ся так­же дру­гие мак­ро­оп­ре­де­ле­ния. Ко­гда мак­ро­оп­ре­де­ле­ния вло­же­ны, как бы­ло про­де­мон­ст­ри­ро­ва­но вы­ше, мак­ро­про­цес­сор дол­жен пра­виль­но рас­по­зна­вать вло­же­ния и со­пос­та­вить на­ча­ло и ко­нец мак­ро­са. Весь вло­жен­ный текст, вклю­чая и дру­гие мак­ро­оп­ре­де­ле­ния оп­ре­де­ля­ет от­дель­ную мак­ро­ко­ман­ду.

За­по­ми­нать мак­ро­оп­ре­де­ле­ния. Про­цес­сор дол­жен за­пом­нить оп­ре­де­ле­ния мак­ро­ко­манд, ко­то­рые бу­дут впо­след­ст­вии ис­поль­зо­вать­ся для рас­ши­ре­ния мак­ро­вы­зо­вов

Рас­по­зна­вать вы­зо­вы. Не­об­хо­ди­мо так­же и рас­по­зна­вать мак­ро­вы­зо­вы, пред­став­лен­ные в ви­де мне­мо­ни­че­ско­го ко­да опе­ра­ции. Это пред­по­ла­га­ет, что име­на мак­ро­ко­манд об­ра­ба­ты­ва­ют­ся на тех же са­мых ос­но­ва­ни­ях, как и один из ко­дов опе­ра­ции.

Вы­пол­нять рас­ши­ре­ние мак­ро­ко­манд и под­ста­нов­ку фак­ти­че­ских па­ра­мет­ров. Вме­сто фор­маль­ных па­ра­мет­ров мак­ро­оп­ре­де­ле­ния мак­ро­про­цес­сор дол­жен под­ста­вить со­от­вет­ст­вую­щие опе­ран­ды мак­ро­ко­ман­ды. Этот текст, в свою оче­редь мо­жет со­дер­жать как мак­ро­ко­ман­ды так и мак­ро­оп­ре­де­ле­ния.

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


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


На­при­мер, ес­ли из один из па­ра­мет­ров дол­жен быть со­еди­нен с дру­гим (macro[x,y] = xy), то воз­мо­жен син­так­сис x&y, что оз­на­ча­ет кон­ка­те­на­цию фор­маль­но­го па­ра­мет­ра x с фор­маль­ным па­ра­мет­ром y. Этот слу­чай не вы­зы­ва­ет боль­ших труд­но­стей. Го­раз­до слож­ней об­ра­ба­ты­ва­ет­ся слу­чай, ко­гда речь идет о под­ста­нов­ке па­ра­мет­ра внут­ри сим­воль­ной стро­ки. В та­ком слу­чае воз­мож­ным вы­хо­дом бу­дет кон­ка­те­на­ция по умол­ча­нию двух по­сле­до­ва­тель­но друг за дру­гом иду­щих сим­воль­ных строк, а так­же пре­об­ра­зо­ва­ние фор­маль­но­го па­ра­мет­ра, за­клю­чен­но­го в скоб­ки к сим­воль­ной стро­ке. Та­ким об­ра­зом, ес­ли мы хо­тим, что­бы в мак­ро­се фи­гу­ри­ро­ва­ла стро­ка ви­да “blablabla[x]xxxxx”, где [x] долж­но за­ме­нять­ся фор­маль­ным па­ра­мет­ром впол­не воз­мож­но за­ме­нить стро­ку та­ко­го ви­да стро­кой ти­па “blablabla”(x)”xxxxx”.


На­до за­ме­тить, что мно­же­ст­во за­ме­ча­тель­ных идей по реа­ли­за­ции по­доб­ных мак­ро­язы­ков реа­ли­зо­ва­но в язы­ке REXX, под­дер­жи­вае­мом на сис­тем­ном уров­не опе­ра­ци­он­ной сис­те­мой OS/2 ком­па­нии IBM.


Так­же для вы­пол­не­ния функ­ций ус­лов­ных пе­ре­хо­дов долж­ны вы­чис­лять­ся не­ко­то­рые ариф­ме­ти­че­ские вы­ра­же­ния (возь­мем в при­мер хо­тя бы обык­но­вен­ных счет­чик). Та­ким об­ра­зом час­то ока­зы­ва­ет­ся по­лез­ной воз­мож­ность ис­поль­зо­ва­ния псев­до-пе­ре­мен­ных вре­ме­ни ком­пи­ля­ции внут­ри мак­ро­сов.


ДВУ­ПРОС­МОТ­РО­ВЫЙ АЛ­ГО­РИТМ


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


Мак­ро­про­цес­сор, как и язык ас­семб­ле­ра, про­смат­ри­ва­ет и об­ра­ба­ты­ва­ет стро­ки тек­ста. Но в язы­ке все стро­ки свя­за­ны ад­ре­са­ци­ей - од­на стро­ка мо­жет ссы­лать­ся на дру­гую при по­мо­щи ад­ре­са или име­ни, ко­то­рое долж­но быть “из­вест­но” ас­семб­ле­ру. Бо­лее то­го, ад­рес присваеваемый ка­ж­дой от­дель­ной стро­ке за­ви­сит от со­дер­жи­мо­го, ко­ли­че­ст­ва и ад­ре­сов пред­ше­ст­вую­щих строк. Ес­ли рас­смат­ри­вать мак­ро­оп­ре­де­ле­ние, как еди­ный объ­ект, то мож­но ска­зать, что стро­ки на­ше­го мак­ро­оп­ре­де­ле­ния не так силь­но взаи­мо­свя­за­ны. Мак­ро­оп­ре­де­ле­ния не мо­гут ссы­лать­ся на объ­ек­ты во­вне это­го мак­ро­оп­ре­де­ле­ния. Пред­по­ло­жим, что в те­ле мак­ро­оп­ре­де­ле­ния есть стро­ка INCR X, при­чем пе­ред этой ко­ман­дой па­ра­метр Х по­лу­чил зна­че­ние 10. Мак­ро­про­цес­сор не про­из­во­дит син­так­си­че­ский ана­лиз, а про­из­во­дит про­стую тек­сто­вую под­ста­нов­ку вме­сто “Х” под­став­ля­ет­ся “10”.


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


ДАН­НЫЕ ДЛЯ ПЕР­ВО­ГО ПРО­СМОТ­РА


1. ВХТ - Вход­ной текст

2. ВЫХ1 - Вы­ход­ная ко­пия тек­ста для ис­поль­зо­ва­ния во вто­рой про­ход.

3. МДТ - таб­ли­ца мак­ро­оп­ре­де­ле­ний, в ко­то­рой хра­нят­ся те­ла мак­ро­оп­ре­де­ле­ний

4. МНТ - таблица имен, не­об­хо­ди­мая для хра­не­ния имен мак­ро­ко­манд, оп­ре­де­лен­ных в МНТ

5. МДТС - счет­чик для таб­ли­цы МДТ

6. МНТС - счет­чик для таб­ли­цы МНТ

7. АЛА - мас­сив спи­ска па­ра­мет­ров для под­ста­нов­ки ин­декс­ных мар­ке­ров вме­сто фор­маль­ных па­ра­мет­ров, пе­ред за­по­ми­на­ни­ем оп­ре­де­ле­ния.


ДАН­НЫЕ ДЛЯ ВТО­РО­ГО ПРО­СМОТ­РА


1. ВЫХ1 - Вы­ход­ная ко­пия тек­ста по­сле­ пер­во­го про­хо­да

2. ВЫХ2 - Вы­ход­ная ко­пия тек­ста по­сле­ второ­го про­хо­да

3. МДТ - таб­ли­ца мак­ро­оп­ре­де­ле­ний, в ко­то­рой хра­нят­ся те­ла мак­ро­оп­ре­де­ле­ний

4. МНТ - таблица имен, не­об­хо­ди­мая для хра­не­ния имен мак­ро­ко­манд, оп­ре­де­лен­ных в МНТ

5. МДТС - счет­чик для таб­ли­цы МДТ

6. МНТС - счет­чик для таб­ли­цы МНТ

7. АЛА - мас­сив спи­ска па­ра­мет­ров для под­ста­нов­ки ин­декс­ных мар­ке­ров вме­сто фор­маль­ных па­ра­мет­ров, пе­ред за­по­ми­на­ни­ем оп­ре­де­ле­ния.

АЛГОРИТМ


Ни­же при­ве­де­на фор­маль­ная за­пись со­от­вет­ст­вую­щих ал­го­рит­мов об­ра­бот­ки мак­ро­оп­ре­де­ле­ний двух­про­смот­ро­вым спо­со­бом.


Ка­ж­дый из ал­го­рит­мов осу­ще­ст­в­ля­ет по­строч­ный про­смотр вход­но­го тек­ста.


ПЕР­ВЫЙ ПРО­СМОТР - МАК­РО­ОП­РЕ­ДЕ­ЛЕ­НИЯ: Ал­го­ритм пер­во­го про­смот­ра про­ве­ря­ет ка­ж­дую стро­ку вход­но­го тек­ста. Ес­ли она пред­став­ля­ет со­бой псев­до­опе­ра­цию MACRO, то все сле­дую­щие за ней стро­ки за­по­ми­на­ют­ся в бли­жай­ших сво­бод­ных ячей­ках МДТ. Пер­вая стро­ка мак­ро­оп­ре­де­ле­ния - это имя са­мо­го мак­ро­са. Имя за­но­сит­ся в таблицу имен МНТ с ин­дек­сом этой стро­ки в МДТ. При этом про­ис­хо­дит так­же под­ста­нов­ка но­ме­ров фор­маль­ных па­ра­мет­ров, вме­сто их имен. Ес­ли в те­че­ние про­смот­ра встре­ча­ет­ся ко­ман­да END, то это оз­на­ча­ет, что весь текст об­ра­бо­тан, и управ­ле­ние мож­но пе­ре­да­вать вто­ро­му про­смот­ру для об­ра­бот­ки мак­ро­ко­манд.


ВТО­РОЙ ПРО­СМОТР - РАС­ШИ­РЕ­НИЕ МАК­РО­КО­МАНД: Ал­го­ритм вто­ро­го про­смот­ра про­ве­ря­ет мне­мо­ни­че­ский код ка­ж­до­го пред­ло­же­ния. Ес­ли это имя со­дер­жит­ся в МНТ, то про­ис­хо­дит об­ра­бот­ка мак­ро­пред­ло­же­ния по сле­дую­ще­му пра­ви­лу: из таб­ли­цы МНТ бе­рет­ся ука­за­тель на на­ча­ло опи­са­ния мак­ро­са в МДТ. Макропроцессор го­то­вит мас­сив спи­ска АЛА со­дер­жа­щий таб­ли­цу ин­дек­сов фор­маль­ных па­ра­мет­ров и со­от­вет­ст­вую­щих опе­ран­дов мак­ро­ко­ман­ды. Чте­ние про­из­во­дит­ся из МДТ, по­сле че­го в про­чи­тан­ную стро­ку под­став­ля­ют­ся не­об­хо­ди­мые па­ра­мет­ры, и по­лу­чен­ная та­ким об­ра­зом стро­ка за­пи­сы­ва­ет­ся в ВЫХТ2. Ко­гда встре­ча­ет­ся ди­рек­ти­ва END, текст по­лу­чен­но­го ко­да пе­ре­да­ет­ся для ком­пи­ля­ции ас­семб­ле­ру.


Пер­вый про­смотр


На­ча­ло ал­го­рит­ма


МДТС = 0

МНТС = 0

ФЛАГ ВЫХОДА = 0


цикл по­ка (ФЛАГ ВЫХОДА == 0) {


чтение следующей строки ВХТ


если !(операция MACRO) {

вывод строки в ВЫХТ1

если (операция END) ФЛАГ ВЫХОДА = 1

}


иначе {

чтение идентификатора

запись имени и индекса в МНТ

МНТС ++

приготовить массив списка АЛА

запись имени в МДТ

МДТС ++


цикл {

чтение следующей строки ВХТ

подстановка индекса операторов

добавление в МДТ

МДТС ++

} пока !(операция MEND)

}

}


переход ко второму проходу


конец алгоритма


Второй просмотр


Начало алгоритма


ФЛАГ ВЫХОДА = 0


цикл пока (ФЛАГ ВЫХОДА == 0) {


чтение строки из ВЫХТ1

НАЙДЕНО = поиск кода в МНТ


если !(НАЙДЕНО) {

запись в ВЫХТ2 строки


если (операция END) {

ФЛАГ ВЫХОДА = 1

}

}


иначе {


УКАЗАТЕЛЬ = индекс из МНТ

Заполнение списка параметров АЛА


цикл {

УКАЗАТЕЛЬ ++

чтение след. строки из МДТ

подстановка параметров

вывод в ВЫХТ2

} пока !(операция MEND)

}

}


переход к компиляции


конец алгоритма


ОДНОПРОСМОТРОВЫЙ АЛГОРИТМ


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


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


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

АЛГОРИТМ


Однопросмотровый макроассемблер


Начало алгоритма


МТДС = 0

МНТС = 0

ФЛАГ ВЫХОДА = 0


цикл пока !(ФЛАГ ВЫХОДА) {


чтение следующей строки ВХТ

НАЙДЕНО = поиск кода в МНТ


если (НАЙДЕНО) {


МДИ = 1

УКАЗАТЕЛЬ = индекс из МНТ

Заполнение списка параметров АЛА


цикл {

УКАЗАТЕЛЬ ++

чтение след. строки из МДТ

подстановка параметров

вставка во ВХТ

} пока !(операция MEND)


иначе если !(операция MACRO) {

вывод строки в ВЫХТ1

если (операция END) ФЛАГ ВЫХОДА = 1

}

иначе {

чтение идентификатора

запись имени и индекса в МНТ

МНТС ++

приготовить массив списка АЛА

запись имени в МДТ

МДТС ++


цикл {

чтение следующей строки ВХТ

подстановка индекса операторов

добавление в МДТ

МДТС ++

} пока !(операция MEND)

}

}


конец алгоритма


ОПИСАНИЕ АЛГОРИТМА


данный алгоритм является упрощением алгоритма приведенного в [1], глава 4.3.2. Различие состоит в том, что современные средства интеллектуализации программирования дают нам возможность осуществлять вставки и удаления из крупных массивов с минимальными затратами процессорного времени, что было невозможно при использовании перфокарт. Кроме того, скорость работы современных процессоров настолько велика, что позволяет производить прямые вставки и удаления в массивах данных средней величины (скажем, до 64 килобайт) в режиме реального времени. Таким образом, расширение исходного макроса может быть напрямую вставлено в массив исходного текста и обработано в расширенном виде. Такая технология позволяет значительно упростить алгоритм обработки макроязыка.


РЕАЛИЗАЦИЯ ВНУТРИ АССЕМБЛЕРА


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


Основные преимущества включения макропроцессора в первый просмотр состоят в следующем:


Многие функции не надо реализовывать дважды (например, функции ввода-вывода, проверки на тип, и.т.п.)

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

У программиста появляются дополнительные возможности по совмещению средств ассемблера (например, команды EUQ) совместно с макрокомандами.

Основные недостатки:


Программа должна требовать больше оперативной памяти, что критично на некоторых типах ЭВМ, не имеющих много оперативной памяти.

Реализация подобного типа задачи может оказаться на порядок сложнее, чем отдельная реализация ассемблера и макропроцессора.

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


ВЫВОДЫ


Макроязыки и соответствующие им макропроцессоры представляют собой самостоятельную форму языков программирования. При использовании вместе с ассемблером, макропроцессор является для программиста полезным инструментом и по существу, позволяет ему самому определять свой язык “вы­со­ко­го” уровня.


Существуют четыре основных задачи, решаемых макропроцессором:


Распознавание макроопределений

Хранение макроопределений

Распознавание макрокоманд

Расширение макрокоманд и подстановка параметров

Макропроцессор в ассемблере может быть реализован несколькими способами:


Независимый двухпросмотровый ассемблер

Независимый однопросмотровый ассемблер

Процессор, совмещенный с первым проходом стандартного двухпросмотрового ассемблера.


ССЫЛКИ


В работе над рефератом использовалась следующая литература:


[1] Дж. Джор­дан - “Сис­тем­ное про­грам­ми­ро­ва­ние”

[2] IBM OS/2 - “REXX Programmer’s Reference”

[3] Borland C++ - Included documentation and sources.


Москва, 1 Ноября 1995 г.