В.Н. Пильщиков - Программирование на языке ассемблера IBM PC (1110551), страница 8
Текст из файла (страница 8)
Именна эту пару и надо дэзывать в командах, когда хотим получить доступ к звену. 103. Списки В этом разделе рассматриваотся способы представления и методы работы со ,заскаьги в машинных программах. Списком (линейным, однонаправленныы) называется последовательность ,гевьев, которые могут размещаться в произвольных местах памяти и в каждом н которых указывается элеыент списка (Е1) и ссылка на следующее звено (,всбражена стрелкой): 182 Программироивиии иа языки ассемблера!8М РС Здесь )г - константное выражение с неотрипательным значением. Згз выражение даскно быть таким, чтобы можно было вычислить его срез) (например, в нем не должно быть ссылок вперед). Вычислив значение 1 макрогенератор создает )г точных копий тела блока и подставляет их в окон. чательный текст программы.
Например, по блоку вевт 3 явв АХ,1 енли будет построен следующий фрагмент окончательной программы: внв ЬХ,1 ЕВЕ ЬХ,1 8НЕ Ахр1 Другой пример (слева указан фрагмент исходной программы, справа построенный по нему фрагмент окончательной программы): Отметим, что в блоках повторения довольно часто используется директив присваивания (=).
Например, описать 100-байтовый ыассив Х, злемегггы которсл имеют начальные значения от 0 до 99, можно так (справа указан тека окончательной программы, который фактически эквивалентен директив Х РВ 0,1,2,3,...,99): х вв о к=о 11.2 '2. 1КР-блошг Блоки повторения этого типа имеют следующий вид: Хав р,<чг, ..., ти> <ооло> яном (Замечалиег уголки в записи <т1, ...,т)г> - это явно указываемые симвсз" а не ыетасимволы.) н еоо б веют н-4 Вв О,1 вв 2 енвм х пв о к-о везя 88 к-к+1 лв к хнвм И ЕОВ б ОВ Е,1 ПВ 2 ов О,1 вв г Е К+1 пв к :Ф к к 99 таких пар вв к магссссэлсгэа звв 1ИР В,<1,б> чхвбв пя г хвои Назначение знака й - указать гранину формального параметра, выделить его из окружающего текста, при этом в окончательный текст программы он не попадает.(Если й поставить не около параметра, то он будет просто опущен.) Махрооператор ес используется не только тогда, когда формальный параметр "сливается" с соседними именами и числами, но и когда его надо указать внутри строк.
Дело в том, что макрогенератор игнорирует вхождения формального парэыетра в строки, и чтобы обратить его внимание на эти вхождения, перед параметроы в строках надо ставить знак Й (а если не ясна его правая гранина, то бг надо указывать и после параметра). Например: 1ВРС Х,-< вв х,ьа,ьаьв' ьъпм пв х,«,в И еще одна особенность макрооператора йс если рядом поставпь несколько знаков й, то макрогенератор удалит только один из них.
Это сделано спепиально, учитывая возможность вложенности. блоков повторений (и/или зюкросов). Например: 1ВРС Рг,зи 1ЯРС Рз,нь 1ИС Р1ьЬР2 юли пюи гаРс Р2,нь 1НС ХЬР2 хипм 1ВРС Р2 р 3П 1НС ВЬР2 внпм 1НС ХН пгс аь пгс вн пгс вь Встретив в тексте исходной программы блок повторения, указанный в левой колонке, макрогенератор сначала создаст первую копию тела внешнего блока, в котором все вхождения его формального параметра Р1 будут заменены на символ А (сщ три верхние строчки средней колонки). При этом из двух подряд егоялзих и команде 1ХС знаков ег будет удален только один, и оставшийся знак к будет отделять формальный параметр Р2 внутреннего блока ст стоящей слева ли<лог-ммьи то получится неоднозначность: становится непонятным, когда зЧ обозначает формальнмй параыетр, а когда саму букву % (почему в ЧАЖМ надо % заменять на 1 и б, а в 1)% не надой).
Во всех предыдущих примерах ьзы не сталкивались с такой проблеьюй, т. к. формальные параметры легко выделялись из окрузгаюшего текста благодаря ограничителям (пробелам, зэгитыы и т. и.), стоящим слева и справа от них. Но если рядом с параметром стоит иьи или число, то гранины параметра станомтся неопределяемыми. В подобной ситуапии следует между параметром и соседним с ним числом или именем поставить символ ее (Ам%г, 1йзЧегВ и т. п.). Например, наш блок повторения должен быть записан следующим образоьс многомодульные цзоппоммы яяа кзяи и.ьви,и.оат,и.ьвт; ьпщ и.овг,и.вхв; х.вхв - трписаидиа - "обэедиаевио" - счет 122.
Модули. Внешние и общие имена. Мы рассыотрели, что надо сделать лля того, чтобы бмла отгранслирована э выполнена ыногомслульная программа. Теперь мы рассмотрим, как следует вписывать сами модули, какие проблемы возникают в многомодульных программах и как они решаются. 12 ч.1. Структура модулей. Локализацггя имен Каждый модуль записывается так, как если бы он бьш самостоятельной прог- )эммой, т. е. представляет собой последовательность предложений, оканчиваювуюся директивой ~зП): ппрвдиововав> зпрвдвоиовио> гав [<точка ввода>] Среди всех ыодулей программы вьщеляется цзин, называемый головным (главным).
Это модуль, который должен выполняться первым, с него начинается зиполнение программы, а уж он затем передает управление всем другим модулям. Синтаксически головной модуль отличается от других только тем, что в его дирекгвве ЕХьг указывается точка входа - метка той команды этого ыолуля, с которой Зплухно начинаться выполнение программы. В остальных модулях точха входа не )хазывается.
(Если точки входа все же указаны в нескольких модулях програмыы, 'и учитывается только та, что первой "попалась на глаза" компоновщику.) Отметим очень важную особенность модулей все имена, описанные в модуле, эпхализуются в нем. Это значит, что в разных модулях программы можно псльзоцгься одинаковыми иыенами и никаких конфликтов из-за этого не будет.
Такая эпкапизация очень выгодна, если модули составляются разными людьми, которые "и должны бояться, что используемые иыи имена совпалуг. Траиеляг)ил и вмиолнвиив одномооульной дрограммы Мы рассмотрели, как транслируется и выполняется програмиа, состоящая вз нескольких модулей. А теперь рассмотрим, что делать с программой, состоящей только из одного модуля. Ясно, что лля такой программы не нужен этап обьелинения модулей в един)по программу, что по исхцяному файлу можно сразу строить ЕХЕ-файл.
Однако, чгобы не иметь двух схем трансляции (одну - лля многомодульных програым, э другую - лля одномолульных), принято компоновщик использовать всегда, даже гели програлцга состоит только из одного модуля. В связи с этим трансляция и счет одномодульной программы осуществляются с помощью следующих приказов (счнтаеы, что текст программы на ЯА находится в фаще М.АэМ): 224 Прогрвммнроввнне нв явмяв всеембяере 1ВМ РС 12.22.
Внешнце и обшие имена. Директивы ЕХТВр( и РСВИС Хотя обычно в виде модулей описываются достаточно независимые друг от друга части программы, эти модули, конечно, как-то взаимодействуют друг с другом - делают переходы, обмениваются данными. И вот при таком взаимодействии возникает ряд проблем. Рассмотрим их. Пусть в программе имеется два модуля М1 и М2.
Пусть в М2 описана процедура Р, к которой будет обрашаться модуль М1, и пусть модуль М2, в свою очередь, пользуется переменной Х и константой К из модуля М1: модуль Мг ; модуль Ид г лаос глк х пв г К Хац 1ОО моч х,о иоч лх,к При независимой трансляции модулей ассемблер сталкивается со следующей проблемой. Имена Х и К принадлежат модулю М1, поэтому они описываются э модуле М1 и не должны описываться в молуле М2.
Когда ассемблер транслирует модуль М2, то в это время он ничего не знает о модуле М1, о его именах. Поз. тому, встретив в М2 имена Х и К и не найдя их описания в М2, ассемблер, хо. нечно, зафиксирует ошибку "неописанное имя". Чтобы не было такой ошибка, надо как-то сообщить ассемблеру, что имена Х и К, хотя и используются в М2, описаны все же а другом модуле, откуда они и берутся. Такое сообщение делается с помощью директивм БХТйг( (ехгегпа1, внешний), иыеющей следующий внд: Вктдд <имв>:<вии>, ..., <иив>:<вии> где <гип> - это Вг'ТЕ, %ОЙВ, ПЮОЙ(), АВЗ, АБАЕ или РАК.
(Замечание.' АВЗ - это стандартная константа ЯА со значением 0.) Данная директива может указываться любое число раз н в любьш местах модуля. В нашеы конкретном случае в модуле М2 надо указать директиву вхтли хгвхтк, кэьвв Она сообщает ассемблеру, что имена Х и К являются, как говорят, внешниив по отношению к данному модулю, т. е. берутся извне, из другого модуля, и пото. му всселгблер не должен искать описание этих имен в модуле М2.
Кроме того, в директиве указываются и типы имен. Например, в нашей дирех' тине сказано, что Х - шш переменной разьгерол~ в байт. Без этой инфорлшции эо семблер не сможет правильно оттранслировать команды и директивы, содер:хэ' шие идти Х. В самом леле, как ассемблер должен транслировать команду М(зг Х,О - как пересылку байта или как пересылку слова? Чтобы не было такой во определенности, и надо указывать ассемблеру типы внешних имен.
Типы ВУТо ЧУОЕ(Э и ПЮОВП указываются для имен переменных, тип АВЗ - для имен ко"' стант, а типы 1<ЕАЕ и РАК - для меток или имен процедур. Например, дирехтим Чнсгомодульиме лрогрвммм 225 вхтви у:влл которую, кж следует из всего сказанною, надо поместить в ыодуль М1, сообшает, что Р - это ыетка или югя пропелуры из какого-то иного ыодуля, причем вызов ее должен быть дальним. Отметим, что ответственность за согласованность типа внешнего иыени, указанного в директиве ЕХТЙХ, и типа, которое юи получает при описании в "своем" модуле, несет автор программы. Например, если в модуле М1 имя К описано как имв константы, то и в модуле М2 внешнее имя К должно быть обьявлеио именеы константы (указано с типоы АВЗ). Игах, поместив директиву ЕХТВ)ь( в модуль М2, мы сообщили ассемблеру, что имена Х и К являются внешними, т.