Многопросмотровые ассемблеры 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Многопросмотровые ассемблеры



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

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

ALPHA EQU BETA

BETA EQU DELTA

DELTA EQU 1

Когда во время первого просмотра встретится метка BETA, мы не сможем назначить ей адрес, так как DELTA еще не определена. Поэтому мы не сможем вычислить значение метки ALPHA во время второго просмотра. Это означает, что любой ассемблер, выполняющий только два последовательных просмотра исходной программы, не может обрабатывать такие последовательности определений.

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

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

 

 

1 HALFSZ EQU MAXLEN/2

2 MAXLEN EQU BUFEND-BUFFER

3 PREVBT EQU BUFFER-1

*

*

*

4 BUFFER RESB 4096

5 BUFEND EQU *

 

a

 
 

 


HALFSZ &1 MAXLEN/2 0

       
 
 
   

 

 


MAXLEN * HALFSZ 0

       
   
 
 

 


b

       
 
   
 

 


BUFEND * MAXLEN 0

       
   
 
 

 


HALFSZ &1 MAXLEN/2 0

       
 
 
   

 

 


MAXLEN &2 BUFEND-BUFFER HALFSZ 0

       
   
 
   

 


BUFFER * MAXLEN 0

       
   
 
 

 

 


в

 

 
 

 


BUFEND * MAXLEN 0

       
   
 
 

 


HALFSZ &1 MAXLEN/2 0

   
 
 
 

 


PREVBT &1 BUFFER-1 0

       
 
 
   

 


MAXLEN &2 BUFEND-BUFFER HALFSZ 0

           
   
 
     

 


BUFFER * MAXLEN PREVBT 0

 

 

 
 


г

       
 
   
 

 

 


BUFEND * MAXLEN 0

       
   
 
 

 


HALFSZ &1 MAXLEN/2 0

   
 
 
 

 


PREVBT 1033 0

       
 
 
   

 


MAXLEN &1 BUFEND-BUFFER HALFSZ 0

 

 

 
 


BUFFER 1034 0

 

 

 
 


д

 

 
 

 

 


BUFEND 2034 0

 
 

 

 


HALFSZ 800 0

   
 
 
 

 

 


PREVBT 1033 0

 

 
 


MAXLEN 1000 0

   
 
 
 

 


BUFFER 1034 0

   
 
 
 

 

 


е

 

Рис. 2.23. Пример работы многопросмотрового ассемблера.

 

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

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

На рис. 2.23б приведены элементы таблицы имен, получившиеся после первого просмотра предложения

HALFSZ EQU MAXLEN/2

Имя MAXLEN еще не определено, поэтому невозможно вычислить значение HALFSZ. Вместо значения HALFSZ в таблице имен запоминается определяющее его выражение Элемент &1показывает, что в определяющем выражении не определено одно имя. Конечно, в реальной реализации это определение может храниться где-нибудь в другом месте. SYMTAB может просто содержать указатель на определяющее выражение. Имя MAXLEN также занесено в таблицу имен и снабжено признаком *, указывающим на то, что оно не определено. С этим именем связан список имен, значения которых зависят отMAXLEN; в данном случае HALFSZ. Обратите внимание на схожесть со способом обработки ссылок вперед в однопросмотровом ассемблере.

Аналогично обрабатывается определение MAXLEN (рис. 223в). В данном случае в состав определения входят два неопределенных имени: BUFEND и BUFFER. Оба этих имени заносятся в SYMTAB вместе со списком, указывающим на зависимость MAXLEN от этих имен. Точно так же при обработке определения PREVBT потребуется занесение этого имени в список имен, зависящих от BUFFER (рис. 2.23г).

До сих пор мы просто запоминали определения имен для последующей обработки. Определение BUFFER в строке 4позволяет нам начать вычисление некоторых из них. Предположим, что, когда мы читаем строку 4, счетчик размещений содержит шестнадцатеричное значение 1034. Этот адрес запоминается в качестве значения BUFFER. Затем ассемблер просматривает список имен, зависящих от значения BUFFER. Элемент таблицы имен для первого имени данного списка (MAXLEN) показывает, что он зависит от двух имен, которые к данному моменту не определены. Поэтому сразу вычислить значение MAXLEN нельзя. Вместо этого &2 заменяется на &1для того, чтобы показать, что теперь только одно имя в определении (BUFEND) осталось неопределенным. Другое имя списка (PREVBT) можно вычислить, так как оно зависит только от BUFFER. Выражение, определяющее значение PREVBT, вычисляется и запоминается в SYMTAB. Результат показан на рис. 2.23д.

Дальнейшая обработка осуществляется аналогично. Когда в строке 5 определяется BUFEND, его значение заносится в таблицу имен. Список, связанный с BUFEND, предписывает ассемблеру вычислить MAXLEN, а занесение значения MAXLEN вызывает, в свою очередь, вычисление имен из связанного с ним списка (HALFSZ). Как показано на рис. 2.23е, на этом процесс определения имен заканчивается. Если какие-либо имена остаются неопределенными, то они отмечаются как ошибочные.

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

 

Примеры реализации

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

Мы обсудим примеры ассемблеров для System/370, VAX и CYBER. Прежде чем продолжить чтение данного раздела, вам следует посмотреть в гл. 1 описания этих машин.

Ассемблер System/370

Относительная базовая адресация в System/370 используется с той же целью, что и в УУМ/ДС, - для экономии места, занимаемого машинной командой. Полный адрес System/370 занимает 24 разряда. Вместе с тем тот же самый адрес можно закодировать с помощью номера базового регистра (4 разряда) и смещения (12 разрядов). Однако есть и отличие: в System/370 нет ни адресации относительно счетчика команд, ни чего-либо похожего на расширенный командный формат УУМ/ДС. Поэтому все команды, ссылающиеся на оперативную память, должны использовать относительную базовую адресацию. Как следствие этого при перемещении объектной программы System/370 модификация требуется только для элементов данных, значениями которых являются фактические адреса (т. е. для адресных констант).

В System/370 любой регистр общего назначения (за исключением R0) может использоваться в качестве базового регистра. Решение о том, какие регистры использовать для этой цели, возлагается на программиста. В больших программах обычно одновременно используются несколько различных базовых регистров. Какие регистры могут использоваться в качестве базовых и каково их содержимое, программист сообщает при помощи директивы ассемблера USING. По своим функциям она похожа на директиву BASE языка ассемблера УУМ/ДС. Таким образом, предложения

USING LENGTH,R1

USING BUFFER,R4

определяют в качестве базовых регистры R1 и R4. Предполагается, что R1 будет содержать адрес LENGTH, а R4 - адрес BUFFER. Так же как и в УУМ/ДС, программист должен предусмотреть команды, обеспечивающие загрузку этих регистров во время выполнения программы. Дополнительные предложения USING можно помещать в любом месте программы. Если базовый регистр в дальнейшем необходимо использовать для других целей, то программист с помощью предложения DROP может сообщить ассемблеру, что дальнейшее использование регистра в качестве базового запрещено.

Дополнительная гибкость в использовании регистров влечет за собой увеличение объема работы, выполняемой ассемблером. Для того чтобы знать, какие регистры общего назначения могут в данный момент использоваться в качестве базовых регистров и каково их значение, используется таблица базовых регистров. При выполнении предложения USING в таблицу заносится новый элемент (или модифицируется уже существующий); при выполнении предложения DROP соответствующий элемент удаляется из таблицы. Для каждой команды, операнд которой является адресом оперативной памяти, ассемблер ищет в таблице подходящий для адресации базовый регистр. Если для адресации подходит более одного регистра, то выбирается тот, который дает наименьшую величину смещения. Если ни один из регистров не подходит, то ассемблирование команды невозможно. Процесс вычисления смещения в точности такой же, как и для УУМ/ДС.

Наряду с этим в языке ассемблера System/370 разрешено явное задание базового регистра и смещения непосредственно в исходном предложении. Например, в предложении

L R2,8(R4)

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

Другой проблемой, которая возникает в ассемблере System/370, является выравнивание областей данных и команд. Некоторые команды выполняются более эффективно, если их операнды выровнены по границам памяти, соответствующим их длинам. Например, операнд длиной в одно слово (32 разряда) должен начинаться с байта, адрес которого кратен 4, а операнд длиной в полслова (16 разрядов) - с адреса, кратного 2. Точно так же требуется, чтобы машинная команда начиналась с байта, адрес которого кратен 2.

Заботу о таком выравнивании берет на себя ассемблер, продвигая, если это необходимо, счетчик размещений. Предположим, например, что счетчик размещений содержит 0015 и необходимо разместить элемент данных длиной в одно слово. В этом случае, прежде чем резервировать память для этого слова, счетчик размещений следует увеличить до 0018 (ближайшее кратное 4 больше чем 0015). Байты объектной программы, пропущенные для того, чтобы обеспечить соответствующее выравнивание, называются пассивными байтами (slack bytes). (В некоторых ассемблерах System/370 включение или выключение выравнивания задается по выбору во время ассемблирования.)

Пассивные байты являются для объектной программы потерянной памятью. Величина этих потерь существенно зависит от того, в каком порядке определяются элементы данных. Рассмотрим, например, последовательность предложений резервирования памяти, изображенную на рис. 2.24а. Если при обработке первого предложения счетчик размещений содержит, как это показано, адрес, кратный 4, то для размещения с выравниванием потребуется 20 байт памяти. Так как сами данные занимают только 14 байт, то это означает, что внесение пассивных байтов увеличило объем занимаемой оперативной памяти почти на 50 %.

 

Адрес Исходное предложение

.

.

.

0024 A DS C 1 БАЙТ

0025 (3 пассивных байта)

0028 B DS F СЛОВО

002C C DS 3C 3 БАЙТА

002F (1 пассивный байт)

0030 D DS H ПОЛУСЛОВО

0032 (2 пассивных байта)

0034 E DS F СЛОВО

.

.

.

 

а

 

Адрес Исходное предложение

.

.

.

0024 B DS F СЛОВО

0028 E DS F СЛОВО

002C D DS H ПОЛУСЛОВО

002E C DS 3C 3 БАЙТА

0031 A DS C 1 БАЙТ

.

.

.

 

б

 

Рис. 2.24. Влияние выравнивания данных на требуемый объем оперативной памяти.

 

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

Ассемблер мало что может сделать с последовательностью определений данных, написанной программистом. В то же время размещение литеральных операндов непосредственно контролируется ассемблером. Большинство ассемблеров System/370 располагают элементы данных в литеральном пуле так, чтобы минимизировать потери памяти. Вначале назначаются адреса для всех литералов, которые требуют для своего размещения двойное слово, затем - слово, полуслово и т. д.

Ассемблер System/370 обеспечивает поддержку аппарата управляющих секций (их называют CSECT). По своим функциям этот аппарат похож на средства, описанные в разд. 2.3.5. В то же время не предусмотрено никакого механизма, прямо соответствующего программным блокам (см. разд. 2.3.4). В System/370 управляющие секции могут состоять из нескольких отдельных сегментов. Сборка этих сегментов осуществляется ассемблером примерно так же, как это было описано для программных блоков. Однако управляющие секции не образуют единый программный модуль. Каждая из них остается самостоятельной единицей и обрабатывается загрузчиком или редактором связей независимо от других секций.

Для каждого внешнего имени, используемого в CSECT, программист должен зарезервировать одно слово для хранения адресной константы. Значение этой константы заносится загрузчиком с помощью механизма, похожего на тот, что был описан в разд.2.3.5. Программист должен предусмотреть команды, которые обеспечат во время исполнения программы загрузку адресной константы в базовый регистр. Информация о том, какой базовый регистр может быть, использован для разрешения внешних ссылок, сообщается ассемблеру с помощью предложения USING.

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

Как можно видеть, язык ассемблера System/370 использует аппарат CSECT для достижения двух логически различных целей - реорганизации объектной программы (аналогично программным блокам УУМ/ДС) и разбиения программы на отдельные модули (аналогично управляющим секциям УУМ/ДС). Это часто приводит к тому, что программисты, впервые познакомившиеся с данными концепциями на подобной системе, путают эти два понятия.

Язык ассемблера System/370 предоставляет также возможность использовать управляющую секцию специального вида, которая называется фиктивной секцией (DSECT - Dummy SECTion). В DSECT может быть использовано любое предложение языка ассемблера, однако эти предложения не становятся частью объектной программы. Чаще всего DSECT используется для описания структуры сложных областей данных (записей, таблиц и т. п.), определенных вне данной программы. Метки, использованные в DSECT, определяют имена, которые могут быть использованы для адресации полей записи или таблицы (после того как будет задан подходящий базовый регистр).

Дополнительную информацию о типовом ассемблере System/370 можно найти в IBM [1979], IBM [1974] и IBM [1982].

Ассемблер ЭВМ VAX

В ЭВМ VAX используется намного более гибкий метод кодирования операндов, чем в большинстве машин. Имеется необычно много способов адресации, и (за небольшим исключением) каждый из этих способов может быть использован в любой команде. Спецификаторы операндов, связанные с различными способами адресации, занимают различный объем памяти. Как мы увидим, это увеличивает объем работы, выполняемой ассемблером.

Терминология, используемая в языке ассемблера VAX, несколько отличается от стандартного набора терминов, который мы использовали. Например, есть два способа адресации, в которых значения операнда хранятся как часть команды, - не посредственный и литеральный. (Для операндов этого типа мы использовали в разд. 2.2 термин непосредственная адресация.) Функционально эти два способа эквивалентны, и в исходной программе они задаются с помощью одной и той же нотации. Во время первого просмотра ассемблер, анализируя величину операнда, решает, какой способ адресации использовать. Если операнд является целым между 0 и 63 (или какой-либо другой величиной, которую можно разместить в 6-разрядном поле), то используется литеральный способ. Если операнд нельзя разместить в 6-разрядном поле или ассемблер еще не может определить его значение, то выбирается непосредственный способ. При непосредственном способе длина спецификатора операнда зависит от типа операнда, используемого в команде (слово, длинное слово и т. д.). Длина спецификатора операнда для литерального способа всегда равна одному байту.

Обратите внимание, что операнды VAX, использующие литеральный способ адресации, обрабатываются совершенно иначе, чем литералы, о которых мы говорили в разд. 2.3. В языке ассемблера VAX нет никаких средств, которые бы соответствовали тому, что мы называли литералами в нашем ассемблере для УУМ/ДС.

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

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

В большинстве языков ассемблера длина ассемблированной команды однозначно определяется по ее мнемоническому коду операции. Для ЭВМ VAX это не так. Каждый спецификатор операнда VAX в зависимости от типа операнда может иметь длину от 1 до 9 байт. Например, в команде

MOVB R1, R5

оба операнда находятся в регистрах. Каждый спецификатор операнда требует 1 байт; поэтому ассемблированная команда будет занимать 3 байт. В то же время в команде

MOVB 1,8 (R6)

для первого операнда используется литеральный способ адресации (длина спецификатора 1 байт), а для второго - базовая относительная адресация. С учетом величины смещения (8) для спецификатора второго операнда требуется 2 байт; таким образом, вся ассемблированная команда будет занимать 4 байт. В команде

MOVB R1, ALPHA

для спецификатора первого операнда требуется 1 байт. Для второго операнда используется адресация относительно счетчика команд. В зависимости от величины смещения его спецификатор может занимать от 2 до 5 байт. Таким образом, зависимости от адреса, назначенного метке ALPHA, данная команда может занимать от 4 до 7 байт.

Это означает, что ассемблер ЭВМ VAX должен во время первого просмотра выполнять значительно более сложную работу, чем, скажем, ассемблер System/370. Во время первого просмотра ассемблер VAX должен анализировать не только коды операций, но и операнды команд. Таблица кодов операций также должна иметь более сложную структуру, так как в ней необходимо иметь информацию о том, какие способы адресации допустимы для каждого из операндов.

Язык ассемблера VAX обеспечивает возможность организации управляющих секций, которые называются программными секциями (PSECT - Program SECTions). Подобно CSECT языка ассемблера System/370, PSECT используются для двух различных целей - реорганизации программы и разбиения программы на модули. В языке ассемблера VAX обработка PSECT отличается: меньшая часть работы выполняется ассемблером и большая - программой связывания. Если из одной PSECT происходит ссылка на имя, определенное в другой PSECT, и эти секции ассемблируются совместно, то для ссылки используется адресация относительно счетчика команд. Так как взаимное расположение секций относительно друг друга во время ассемблирования неизвестно, то величину смещения вычислить нельзя. Поэтому ассемблер генерирует команды для программы связывания, которые позволят ей определить смещение и занести его в команду. Этот процесс похож на тот, что был описан в разд. 2.3.4 для разрешения ссылок между программными блоками. Более детально мы рассмотрим работу программы связывания в следующей главе.

При трансляции PSECT могут задаваться некоторые атрибуты, в том числе атрибут доступа: "только чтение", "только исполнение" и т. п. Кроме того, в каждой PSECT можно указать, разрешено или нет выравнивание элементов данных. (Проблемы выравнивания в VAX похожи на те, что мы обсуждали в связи с System/370.) Программа связывания собирает вместе все сегменты каждой PSECT и все программные секции, имеющие аналогичные атрибуты. Средства операционной системы VAX могут быть использованы для обеспечения защиты PSECT в соответствии с ее атрибутами.

Ассемблер VAX предполагает по умолчанию, что все имена, которые были использованы, но не были определены во время ассемблирования, являются внешними ссылками. Никакого явного объявления внешних имен (подобно предложению ЕХТREF УУМ/ДС) не требуется. К несчастью, это приводит к тому, что ошибки типа пропуска символа в имени нельзя обнаружить до момента связывания программы. Однако программист может задать режим работы ассемблера, который отменяет данное правило умолчания и требует явного объявления внешних имен.

Дополнительную информацию об ассемблере VAX можно найти в DEC [1982] и DEC [1979].

Ассемблер ЭВМ CYBER

Язык ассемблера ЭВМ CYBER, который называется COMPASS, имеет несколько существенных отличий от других языков. Первое отличие является прямым следствием структуры машины. Дело в том, что размер машинного слова CYBER позволяет разместить в нем несколько различных ассемблированных команд. В общем случае задачей ассемблера является упаковка как можно большего количества последовательно расположенных команд в одно слово объектной программы. Конечно, можно было бы просто размещать по одной машинной команде в слове, а неиспользованное пространство заполнять невыполняемыми командами, но такое решение весьма неэффективно с точки зрения как занимаемого пространства, так и времени исполнения.

Для упаковки команд в ассемблере предусмотрен счетчик позиций (position counter). Этот счетчик показывает количество свободных разрядов, оставшихся в текущем слове объектной программы. В начале нового слова в счетчик позиций заносится число 60 (число разрядов слова CYBER). При генерации команды количество разрядов, требуемое для ее размещения, вычитается из счетчика позиций. Если в текущем слове нет места для размещения очередной команды, то оставшиеся разряды (если они есть) заполняются неисполняемыми командами, а для работы берется новое слово объектной программы. В этот момент счетчик размещений и счетчик слов (его мы опишем в этом разделе ниже) увеличиваются на 1, после чего они будут содержать адрес следующего слова.

Предыдущее описание представляет собой обычную последовательность действий: команды (или элементы данных) упаковываются в машинное слово до тех пор, пока это возможно, а затем осуществляется переход к следующему слову. Однако в некоторых случаях требуется перейти к следующему слову несмотря на то, что в текущем слове еще достаточно места для размещения следующего элемента объектного кода. Такая необходимость является следствием того, что в CYBER применяется пословная, а не побайтная адресация оперативной памяти. Рассмотрим, например, команду безусловного перехода. Адрес операнда в данной команде должен быть адресом слова. После того как в счетчик команд будет занесен адрес, заданный в команде перехода, следующей командой, выбираемой для выполнения, будет первая команда, упакованная в слово с адресом, равным целевому адресу команды перехода. Это означает, что мы можем непосредственно передать управление только на команду, расположенную в начале слова объектной программы.

Процесс размещения команды или элемента данных в начале слова, даже если в предыдущем слове достаточно места, называется проталкиванием (forsing upper). При этом остаток предыдущего слова заполняется неисполняемыми командами, счетчик слов и счетчик размещений увеличиваются на 1, а в счетчик позиций заносится число 60. Ассемблер COMPASS выполняет проталкивание в следующих случаях:

1. Ассемблируемое предложение имеет метку (так как адрес метки указывает на начало слова).

2. Ассемблируемое предложение является предложением резервирования памяти, и в нем не задана упаковка битовых полей в одно слово.

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

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

Кроме счетчика позиций ассемблер использует в своей работе еще два счетчика - счетчик, размещений и счетчик слов. Вместе эти два счетчика служат для того же, что и LOCCTR, описанный в разд. 2.1. Основная функция счетчика слов та же, что и у LOCCTR: счетчик слов вместе со счетчиком позиций указывает на относительное местоположение в объектном коде следующей ассемблируемой команды. Счетчик размещений используется ассемблером для назначения адресов внутренним меткам программы. Ранее для этого мы также использовали LOCCTR.

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

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



Поделиться:


Последнее изменение этой страницы: 2017-02-17; просмотров: 166; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.191.5.239 (0.274 с.)