Управляющие секции и связывание программ 


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



ЗНАЕТЕ ЛИ ВЫ?

Управляющие секции и связывание программ



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

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

На рис.2.15 показано, как наша модельная программа может быть записана в виде нескольких управляющих секций, В данном случае имеются три управляющие секции: одна для главной программы и по одной для каждой из подпрограмм. Предложение START определяет начало ассемблируемой программы и задает имя (COPY) первой управляющей секции. Первая секция расположена вплоть до предложения CSECT в строке 109. Эта директива ассемблера сигнализирует о начале новой управляющей секции с именем RDREC. Аналогично предложение CSECT в строке 193 начинает управляющую секцию с именем WRREC. Для каждой управляющей секции ассемблер заводит отдельный счетчик размещений (начинающийся с 0) точно так же, как он это делает для программных блоков.

От программных блоков управляющие секции отличаются тем, что они обрабатываются ассемблером независимо друг от друга. (Необязательно даже, чтобы все управляющие секции программы ассемблировались одновременно.) Имена, определенные в одной управляющей секции, не могут непосредственно использоваться в другой секции. Для того чтобы загрузчик смог их обработать, они должны быть описаны как внешние ссылки. На рис.2.15 показаны две директивы ассемблера для задания таких ссылок: EXTDEF (определение внешних имен) и ЕХТREF (объявление внешних ссылок). Предложение EXTDEF определяет имена, описанные в данной управляющей секции, но доступные для использования в других секциях. Такие имена называются внешними именами (external symbols). Имена управляющих секций (в данном случае COPY, RDREC и WRREC) определять в предложении EXTDEF не требуется, так как они автоматически считаются внешними. Предложение EXTREF объявляет имена, которые используются в данной управляющей секции, но определены где-либо еще. Например, имена BUFFER, BUFEND и LENGTH, определенные в управляющей секции с именем COPY, делаются доступными другим секциям с помощью предложения EXTDEF в строке 6. В третьей управляющей секции (WRREC), согласно предложению EXTREF (строка 207), используются два внешних имени. Порядок перечисления имен в предложениях EXTDEF и EXTREF несуществен.

Теперь мы готовы к тому, чтобы посмотреть, как ассемблер обрабатывает внешние ссылки. На рис.2.16 для каждого предложения программы показан сгенерированный объектный код.

 

Строка Исходное предложение

5 COPY START 0 КОПИРОВАНИЕ ФАЙЛА

6 EXTDEF BUFFER,BUFEND,LENGTH

7 EXTREF RDREC,WRREC

10 FIRST STL RETADR СОХРАНЕНИЕ АДРЕСА ВОЗВРАТА

15 CLOOP +JSUB RDREC ВВОД ВХОДНОЙ ЗАПИСИ

20 LDA LENGTH ПРОВЕРКА НА EOF (LENGTH = 0)

25 COMP #0

30 JEQ ENDFIL ВЫХОД, ЕСЛИ НАШЛИ EOF

35 +JSUB WRREC ВЫВОД ВЫХОДНОЙ ЗАПИСИ

40 J CLOOP ЦИКЛ

45 ENDFIL LDA =C"EOF" ЗАНЕСЕНИЕ МАРКЕРА КОНЦА ФАЙЛА

50 STA BUFFER

55 LDA #3 УСТАНОВИТЬ LENGTH = 3

60 STA LENGTH

65 +JSUB WRREC ЗАПИСЬ EOF

70 J @RETADR ВОЗВРАТ ИЗ ПРОГРАММЫ

95 RETADR RESW 1

100 LENGTH RESW 1 ДЛИНА ЗАПИСИ

103 LTORG

105 BUFFER RESB 4096 ДЛИНА БУФЕРА – 4096 БАЙТ

106 BUFEND EQU *

107 MAXLEN EQU BUFEND-BUFFER МАКСИМАЛЬНАЯ ДЛИНА ЗАПИСИ

109 RDREC CSECT

110 *

115 * ПОДПРОГРАММА ВВОДА ЗАПИСИ НА БУФЕР

120 *

122 EXTREF BUFFER,LENGTH,BUFEND

125 CLEAR X ОБНУЛЕНИЕ СЧЕТЧИКА ЦИКЛА

130 CLEAR A ОБНУЛЕНИЕ РЕГИСТРА А

132 CLEAR S ОБНУЛЕНИЕ РЕГИСТРА S

133 LDT MAXLEN

135 RLOOP TD INPUT ПРОВЕРКА УСТРОЙСТВА ВВОДА

140 JEQ RLOOP ЦИКЛ ДО ПОЛУЧЕНИЯ ГОТОВНОСТИ

145 RD INPUT ЧТЕНИЕ СИМВОЛА В РЕГИСТР А

150 COMP A,S ПРОВЕРКА НА КОНЕЦ ЗАПИСИ (Х"00")

155 JEQ EXIT ВЫХОД ИЗ ЦИКЛА ПО КОНЦУ ЗАПИСИ

160 +STCH BUFFER,X ЗАПИСЬ СИМВОЛА В БУФЕР

165 TIXR T ЦИКЛ ДО ДОСТИЖЕНИЯ МАКСИМАЛЬНОЙ

170 JLT RLOOP ДЛИНЫ

175 EXIT +STX LENGTH ЗАПОМИНАНИЕ ДЛИНЫ ЗАПИСИ

180 RSUB ВОЗВРАТ ИЗ ПОДПРОГРАММЫ

185 INPUT BYTE X"F1" КОД УСТРОЙСТВА ВВОДА

190 MAXLEN WORD BUFEND-BUFFER

193 WRREC CSECT

195 *

200 * ПОДПРОГРАММА ВЫВОДА ЗАПИСИ ИЗ БУФЕРА

205 *

207 EXTREF LENGTH,BUFFER

210 CLEAR X ОБНУЛЕНИЕ СЧЕТЧИКА ЦИКЛА

212 +LDT LENGTH

215 WLOOP TD =X"05" ПРОВЕРКА УСТРОЙСТВА ВЫВОДА

220 JEQ WLOOP ЦИКЛ ДО ПОЛУЧЕНИЯ ГОТОВНОСТИ

225 +LDCH BUFFER,X ЧТЕНИЕ СИМВОЛА ИЗ БУФЕРА

230 WD =X"05" ВЫВОД СИМВОЛА

235 TIXR T ЦИКЛ, ПОКА НЕ БУДУТ ВЫВЕДЕНЫ

240 JLT WLOOP ВСЕ СИМВОЛЫ

245 RSUB ВОЗВРАТ ИЗ ПОДРОГРАММЫ

255 END FIRST

 

Рис. 2.15.Иллюстрация управляющих секций и связывания программы.

 

 

Строка Адрес Исходное предложение Объектный код

5 0000 COPY START 0

6 EXTDEF BUFFER,BUFEND,LENGTH

7 EXTREF RDREC,WRREC

10 0000 FIRST STL RETADR 172027

15 0003 CLOOP +JSUB RDREC 4B100000

20 0007 LDA LENGTH 032023

25 000A COMP #0 290000

30 000D JEQ ENDFIL 332007

35 0010 +JSUB WRREC 4B100000

40 0014 J CLOOP 3F2FEC

45 0017 ENDFIL LDA =С"EOF" 032016

50 001A STA BUFFER 0F2016

55 001D LDA #3 010003

60 0020 STA LENGTH 0F200A

65 0023 +JSUB WRREC 4B100000

70 0027 J @RETADR 3E2000

95 002A RETADR RESW 1

100 003D LENGTH RESW 1

103 LTORG

0030 * =C"EOF" 454F46

105 0033 BUFFER RESB 4096

106 1033 BUFEND EQU *

107 1000 MAXLEN EQU BUFEND-BUFFER

109 0000 RDREC CSECT

110 *

115 * ПОДПРОГРАММА ВВОДА ЗАПИСИ НА БУФЕР

120 *

122 EXTREF BUFFER,LENGTH,BUFEND

125 0000 CLEAR X B410

130 0002 CLEAR A B400

132 0004 CLEAR S B440

133 0006 LDT MAXLEN 77201F

135 0009 RLOOP TD INPUT E3201B

140 000C JEQ RLOOP 332FFA

145 000F RD INPUT DB2015

150 0012 COMPR A,S A004

155 0014 JEQ EXIT 332009

160 0017 +STCH BUFFER,X 57900000

165 001B TIXR T B850

170 001D JLT RLOOP 3B2FE9

175 0020 EXIT +STX LENGTH 13100000

180 0024 RSUB 4F0000

185 0027 INPUT BYTE X"F1" F1

190 0028 MAXLEN WORD BUFEND-BUFFER 000000

193 0000 WRREC CSECT

195 *

200 * ПОДПРОГРАММА ВЫВОДА ЗАПИСИ ИЗ БУФЕРА

205 *

207 EXTREF LENGTH,BUFFER

210 0000 CLEAR X B410

212 0002 +LDT LENGTH 77100000

215 0006 WLOOP TD =X"05" E32012

220 0009 JEQ WLOOP 332FFA

225 000C +LDCH BUFFER,X 53900000

230 0010 WD =X"05" DF2008

235 0013 TIXR T B850

240 0015 JLT WLOOP 3B2FEE

245 0018 RSUB 4F0000

255 END FIRST

001B * =X"05" 05

 

Рис.2.16. Объектный код для программы на рис.2.15.

 

Для начала рассмотрим команду

15 0003 CLOОР + JSUB RDREC 4В100000

Ее операнд (RDREC) объявлен в предложении EFTREF, и, следовательно, это внешняя ссылка. Ассемблеру ничего неизвестно о том, куда будет загружена управляющая секция, содержащая RDREC, и поэтому он не может обработать адресную часть данной команды. Вместо этого он устанавливает адрес равным 0 и передает загрузчику информацию, позволяющую ему занести во время загрузки нужный адрес. Поскольку неизвестно, будет ли адрес RDREC взаимосвязан с чем-либо в данной управляющей секции, относительную адресацию использовать нельзя. Следовательно, для того чтобы иметь достаточно места для занесения фактического адреса, необходимо использовать расширенный командный формат. Это справедливо для любой команды, операнд которой ссылается на внешнее имя.

Аналогично в команде

160 0017 +SТCН BUFFER,Х 57 900 000

имеется внешняя ссылка на метку BUFFER. Эта команда ассемблируется с использованием расширенного командного формата и нулевым адресом. Разряд х установлен в 1, что является признаком индексной адресации. Предложение

190 0028 MAXLEN WORD BUFEND - BUFFER 000000

лишь незначительно отличается от предыдущих. Здесь значение генерируемой 1-словной константы определяется с помощью выражения, в котором используются две внешние ссылки: BUFEND и BUFFER. Как и ранее, ассемблер заносит для этой константы нулевое значение. Загрузчик во время загрузки прибавит к этому значению адрес метки BUFEND, а затем вычтет из него адрес BUFFER, что и даст в итоге требуемое значение.

Укажем на различие в обработке выражения в строке 190 и похожего выражения в строке 107. Имена BUFEND и BUFFER определены в той же управляющей секции, что и предложение EQU в строке 107. Поэтому значение этого выражения может быть вычислено непосредственно ассемблером. Для строки 190 это сделать нельзя, так как BUFEND и BUFFER определены в другой управляющей секции и, следовательно, во время ассемблирования их значения неизвестны.

Как видно из предыдущих рассуждений, ассемблер должен запоминать (в SYMTAB), в какой управляющей секции было определено то или иное имя. Любая попытка использовать имя из другой управляющей секции должна отмечаться как ошибка, если только это имя не объявлено (с помощью EXTREF) в качестве внешнего. Ассемблер должен разрешать использовать одинаковые имена в разных управляющих секциях. Например, противоречивые определения MAXLEN в строках 107 и 190 не должны вызвать никаких проблем. Ссылки на MAXLEN в управляющей секции COPY будут использовать определение в строке 107, тогда как ссылки в RDREC - определение в строке 190.

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

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

Запись-определение:

Столбец 1 D.

Столбцы 2–7 Идентификатор внешнего имени, определенный в

данной управляющей секции

Столбцы 8–13 Относительный адрес имени (шестнадцатеричный).

Столбцы 14–73 Информация, аналогичная столбцам 2-13 для других

внешних имен.

Запись-ссылка:

Столбец 1 R.

Столбцы 2-7 Идентификатор внешнего имени, на который есть

ссылка в данной управляющей секции.

Столбцы 8-73 Информация, аналогичная столбцам 2-7 для других

внешних имен.

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

Запись-модификатор:

Столбец 1 М.

Столбцы 2-7 Начальный адрес модифицируемого адресного поля

относительно начала управляющей секции

(шестнадцатеричный).

Столбцы 8-9 Длина модифицируемого адресного поля в

полубайтах (шестнадцатеричная).

Столбец 10 Признак модификации (+ или -).

Столбцы 11-16 Внешнее имя, значение которого надо добавить к

заданному полю или вычесть из него.

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

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

Записи-определения и записи-ссылки каждой управляющей секции содержат имена, объявленные в предложениях EXTDEF и EXTREF. Запись-определение содержит, кроме того, относительный адрес каждого внешнего имени внутри данной управляющей секции. Для имен, объявленных в EXTREF, информации об адресах нет. Эти имена просто перечисляются в записи -ссылке.

Давайте теперь изучим процесс связывания внешних ссылок, начиная с ранее рассмотренных исходных предложений. Поле адреса команды JSUB в строке 15 начинается с относительного адреса 0004. В объектной программе его начальное значение равно 0. Запись-модификатор

М00000405 + RDREC

управляющей секции COPY определяет, что адрес метки RDREC должен быть прибавлен к этому полю, что и даст требуемый машинный адрес. Две другие записи-модификаторы в секции COPY выполняют сходные функции для команд в строках 35 и 65. Аналогично первая запись-модификатор в управляющей секции RDREC указывает на занесение внешней ссылки для строки 160.

Обработка 1-словной константы, сгенерированной по строке 190, мало чем отличается от ранее описанного процесса. Значением этой константы является выражение BUFEND - BUFFER, где обе метки определены в другой управляющей секции. Ассемблер генерирует эту константу (расположенную по относительному адресу 0028 в управляющей секции RDREC) с нулевым начальным значением. Две последние записи-модификаторы в RDREC требуют, чтобы адрес BUFEND был добавлен к указанному полю, а адрес BUFFER был вычтен. Эти вычисления выполняются во время загрузки, и в результате получается требуемая константа.

 

H_COPY _000000_001033

D_BUFFER_000033_BUFEND_001033_LENGTH_00002D

R_RDREC _WRREC T_000000_1D_172027_4B100000_032023_290000_332007_4B100000_3F2FEC_032016_0F2016 T_00001D_0D_010003_0F200A_4B100000_3E2000

T_000030_03_454F46

M_000004_05_+RDREC

M_000011_05_+WRREC

M_000024_05_+WRREC

E_000000

 

 

H_RDREC _000000_00002D

R_BUFFER_LENGTH_BUFEND T_000000_1D_B410_B400_B440_77201F_E3201B_332FFA_DB2015_A004_332009_57900000_B850 T_00001D_0E_3B2FE9_13100000_4F0000_F1_000000

M_000018_05_+BUFFER

M_000021_05_+LENGTH

M_000028_06_+BUFEND

M_000028_06_-BUFFER

E

 

 

H_WRREC _000000_00001C

R_LENGTH_BUFFER T_000000_1C_B410_77100000_E32012_332FFA_53900000_DF2008_B850_3B2FEE_4F0000_05 M_000003_05_+LENGTH

M_00000D_05_+BUFFER

E

 

Рис. 2.17. Объектная программа, соответствующая рис.2.15.

 

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

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

М00000705

М00001405

М00002705

будут заменены на записи-модификаторы вида

М00000705 + COPY

М00001405 + COPY

М00002705 + COPY

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

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

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

Варианты построения ассемблеров

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

В разд. 2.4.1 мы опишем оверлейную структуру, которая обычно используется для двухпросмотровых ассемблеров. В разд. 2.4.2 и 2.4.3 обсуждаются две альтернативные (по отношению к стандартной двухпросмотровой) схемы ассемблирования. В разд. 2.4.2 описываются структура и алгоритм однопросмотрового ассемблера. Такие ассемблеры используются там, где желательно или даже необходимо обойтись без второго просмотра исходной программы. В разд. 2.4.3 дается представление о многопросмотровых ассемблерах. В этих ассемблерах получает свое дальнейшее развитие двухпросмотровая схема ассемблирования, что позволяет обрабатывать ссылки вперед в предложениях определения имен.



Поделиться:


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

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