ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы.



ГЛАВА 7     ФОРМАТЫ ЗАГРУЖАЕМЫХ ОБЪЕКТНЫХ МОДУЛЕЙ
     __________________________________________________________

     7.1   Введение
     7.1.1   Определение терминов
     7.2   Идентификация модуля и атрибуты
     7.2.1   Определение сегмента
     7.2.2   Адресация сегмента
     7.2.3   Определение имен
     7.2.4   Индексы
     7.3   Концепция привязки
     7.3.1   Внунтрисегментная привязка
     7.3.2   Межсегментная привязка
     7.4   Последовательность записей
     7.5   Форматы записей
     7.5.1   Формат записи-примера        (SAMREC)
     7.5.2   Заголовочная запись Т-модуля (THEADR)
     7.5.3   Заголовочная запись L-модуля (LHEADR)
     7.5.4   Запись списка имен           (LNAMES)
     7.5.5   Запись определения сегмента  (SEGDEF)
     7.5.6   Запись определения группы    (GRPDEF)
     7.5.7   Запись определения имен 'public'   (PUBDEF)
     7.5.8   Запись определения имен 'communal' (COMDEF)
     7.5.9   Запись определения имен 'local'    (LOCSYM)
     7.5.10  Запись определения имен 'external' (EXTDEF)
     7.5.11  Запись нумерации строк             (LINNUM)
     7.5.12  Логическая упорядоченная запись данных (LEDATA)
     7.5.13  Логическая запись повторяемых данных   (LIDATA)
     7.5.14  Запись привязки              (FIXUPP)
     7.5.15  Конечная запись модуля       (MODEND)
     7.5.16  Запись комментариев          (COMENT)
     7.6   Представление типа для переменных 'communal'

     __________________________________________________________


t0                             - 237 -




     7.1 Введение

     В  этой  главе дается описание форматов записей объектных
модулей,  определяющих  объектный  язык  для  микропроцессоров
8086,  80186  и  80286.  Объектный  язык  процессора 8086
является  выходным  продуктом  трансляторов  со  всех  языков,
(имеющих процессор 8086) собираемым в последствии  программой
Microsoft  linker.  Объектный  язык  8086   используется   при
вводе/выводе для процессоров объектных языков (сборщики и др.)
операционных систем XENIX, PC-DOS и MS-DOS.
     Полный  список  записей  приведен  в оглавлении. Описание
форматов записей будет дано ниже.
     __________________________________________________________
     Примечание
               Если объектный модуль содержит неопределенные
               величины, то поведение сборщика Microsoft
               неопределено. Все неопределенные величины резер-
               вируются фирмой Microsoft для использования в
               будущих версиях системы.
     __________________________________________________________

     7.1.1 Определение терминов

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

     OMF - Форматы объектного модуля.

     MAS - Адресное пространство памяти.
           8086  MAS  равно  одному  мегабайту (1048576 байт).
           Следует отметить, что MAS  отличается  от  реальной
           памяти, т.к. последняя занимает только часть MAS.

     Модуль  - это неделимое единство объектного кода и другой
               информации,  создаваемое  в  результате  работы
               транслятора.

     Т-модуль - это модуль, создаваемый такими трансляторами,
                как Pascal или FORTRAN.
                _______________________________________________
                -   Каждый  модуль  должен  иметь  имя.  Если
                таковое не указано, то транслятор присваивает
                имя по умолчанию (имя файла или нулевое имя).
                - Каждый Т-модуль  в  группе  модулей  должен
                иметь  уникальное имя. Для сборщика Microsoft
                linker это не обязательно.
              _________________________________________________

     Фрагмент  -  это  непрерывный  участок MAS, длиной  64К,
                 начинающийся на границе  параграфа  (или  на
                 селекторе    80286).   Сегментные   регистры
                 процессора    определяют    только    четыре
                 фрагмента   (возможно  перекрывающихся).  Ни
                 один 16-разрядный адрес не имеет  доступа  к
                 памяти вне четырех текущих фрагменов.

                             - 238 -



     Логический сегмент (ЛСЕГ) - непрерывный участок памяти,
                                 чье  содержимое определяется
                                 во  время   трансляции   (за
                                 исключением         адресной
                                 привязки). Размер ЛСЕГ также
                                 не  окончателен,  т.к.   при
                                 сборке  несколько ЛСЕГ могут
                                 быть объеденены в один ЛСЕГ.
                                 Размер   ЛСЕГ   не    должен
                                 превышать     64К.     Таким
                                 образом, 16-битовое смещение
                                 от      базы      фрагмента,
                                 содержащего    ЛСЕГ,   может
                                 адресовать  любой   байт   в
                                 ЛСЕГ.
     Физический сегмент (ФСЕГ) - Эквивалент термина "Фрагмент".

     Номер  фрагмента  - Каждый фрагмент начинается на границе
                         параграфа.   Параграфы   памяти  (16
                         байт) можно пронумеровать  от  0  до
                         65535.   Эти   номера   и   являются
                         номерами соответствующих фрагментов.

     Группа  -  это  несколько  ЛСЕГ, определенных  во   время
                трансляции, чье положение в MAS  скомпановано
                таким  образом,  что  существует хотя бы один
                фрагмент, перекрывающий все  ЛСЕГ  в  группе.
                Запись "Гр А(X,Y,Z)" означает, что логические
                сегменты  X,  Y  и  Z формируют группу А. Эта
                запись  не  содержит  никакой  информации   о
                взаимном   расположении   сегментов.  Текущая
                версия  сборщика   Microsoft   не   допускает
                принадлежности  логического  сегмента к более
                чем одной группе.

     Канонический фрагмент - Каждая ячейка MAS содержится в
                             4096 фрагментах, один из которых
                             имеет   наибольший  номер.  Этот
                             фрагмент называется каноническим
                             фрагментом данной ячейки памяти.
                             Другими  словами,   каноническим
                             фрагментом данной ячейки памяти
                             является фрагмент, смещение от на-
                             чала которого данной ячейки памяти
                             находится в пределах 0-15.
                             Это  понятие  применимо и группе
                             ячеек,  например,   канонический
                             фрагмент ЛСЕГ или канонический
                             фрагмент группы ЛСЕГ.

     Имя  сегмента  -  Каждому  ЛСЕГ назначается имя во время
                       трансляции. Это делается по  следующим
                       причинам:

                       - необходимо определить во время сборки,
                         какие  ЛСЕГ  скомбинированы  друг  с
                         другом;
                       - необходимо указать членство в группах.


                             - 239 -


     Имя класса - Во время  трансляции  логическому  сегменту
                  может быть назначено имя класса. Два ЛСЕГ
                  принадлежат одному классу, если они имеют
                  одинаковые имена класса.
                  Имена  класса  имеют  следующий  смысл: имя
                  класса  "CODE"  или  любое  имя  класса   с
                  с  таким  суффиксом  подразумевает, что все
                  сегменты того класса содержат только код.

     Имя наложения - Логическому сегменту может быть назначено
                     имя наложения. Это имя игнорируется сбор-
                     щиками   Microsoft  версий  3.0  и  позже,
                     однако  стандартный  сборщик   Microsoft
                     поддерживает его.

     Полное  имя - Полное имя ЛСЕГ включает имя сегмента, имя
                   класса и имя наложения. Сборщик соединяет
                   логические сегменты из различных модулей,
                   если совпадают их полные имена.



     7.2 Идентификация модуля и атрибуты

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

     7.2.1 Определение сегмента

     Модуль представляет собой совокупность объектного  кода,
описываемую    последовательностью    записей,    создаваемых
транслятором. Объектный код  представляет  собой  непрерывные
участки  памяти,  содержимое  которых  определяется  во время
трансляции. Этими  участками  являются  логические  сегменты.
Модуль  определяет  атрибуты каждого ЛСЕГ. Запись определения
сегмента (SEGDEF)  содержит  всю  информацию  по  ЛСЕГ  (имя,
длина,   выравнивание   и   т.п.).  Сборщик  запрашивает  эту
информацию, когда комбинирует различные ЛСЕГ и  устанавливает
сегментную  адресацию.  SEGDEF всегда следует за заголовочной
записью.

     7.2.2 Адресация сегмента

     Механизм  адресации  микропроцессора  8086  обеспечивает
адресацию   64К   памяти  в  каждом  из  четырех  фрагментов,
адресуемых базовыми регистрами - CS (регистр сегмента кодов),
DS и ES (регистры сегмента данных) и  SS  (регистр  стэкового
сегмента).
     Возможное  количество  ЛСЕГ,  составляющих образ памяти,
чаще всего намного превышает количество имеющихся  сегментных
(базовых)  регистров. Поэтому при модульном программировании,
когда собираются множество небольших ЛСЕГ,  требуется  частая
перезагрузка базовых регистров.
     Разумеется, такая перезагрузка нежелательна. Лучше всего

                             - 240 -


собирать  небольшие  по  размеру  ЛСЕГ  вместе  в  один блок,
помещающийся в одном фрагменте. В этом случае все ЛСЕГ  можно
адресовать,  использую  один  и тот же базовый регистр. Таким
блоком и является группа (см. Раздел 7.1.1).
     Для введения взаимной адресации внутри группы, вы должны
явно определить каждую группу в  модуле.  Запись  определения
группы  (GRPDEF)  как  раз предназначена для этого и содержит
список имен сегментов.
     GRPDEF  следует  сразу  за  всеми  SEGDEF,  т.к.  GRPDEF
обращается  к  ним  для описания группы. Все остальные записи
идут после GRPDEF.

     7.2.3 Определение имен

     Определение имен осуществляется  с  помощью  трех  типов
записей - PUBDEF, COMDEF и EXTDEF.

     7.2.4 Индексы

     Понятие  индекс  понимается  в  этой  главе,  как целое,
указывающее  на  конкретный  элемент  из  списка   элементов.
Например,  индекс  имени,  индекс  сегмента,  индекс  группы,
индекс типа и т.п.
     _________________________________________________________
     Примечание
               Индекс обычно положительное число. Значение ноль
               зарезервировано и может нести особый смысл,  в
               зависимости от типа индекса (например, нулевой
               индекс сегмента указывает на абсолютный псевдо-
               сегмент без имени; нулевой индекс типа указывает
               на тип "без типа".
     _________________________________________________________

     В  целом, значения индексов в объектных файлах обычно не
превышают 50-100, поэтому отводимая для них память  также  не
превышает 1-2 байта.
     Если  старший  бит  первого  (и  возможно единственного)
байта равен нулю, то значение индекса варьируется в  пределах
0-127  и  занимает  один  байт.  Если  этот  бит  равен 1, то
значение индекса это число, между 0 и 32К-1,  занимающее  два
байта и определяемое следующим образом: младшие восемь бит во
втором байте, а старшие семь бит в первом байте.


     7.3 Концепция привязки

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

     - Место и тип привязываемого адресного поля.
     - Один из двух возможных режимов привязки.
     - Цель,  т.е.  адрес  в  памяти  к  которому  обращается
       адресное поле.
     - Фрагмент, к которому имеет место обращение.

     а) Существует пять типов адресных полей:

        - Указатель (старшее слово имеет больший адрес).

                             - 241 -


        - База   это   старшее  слово  указателя  (сборщику
          безразлично, есть ли младшее слово указателя или
          нет).
        - Смещение это младшее слово указателя (сборщику
          безразлично, следует ли за ним старшее слово).
        - Старший байт это старший байт смещения (сборщику
          безразлично, предшествует ли младший байт).
        - Младший байт это младший байт смещения (сборщику
          безразлично следует ли за ним старший байт).

t1                           _____________________________
        Указатель:         і                           і
                           і___________________________і
                                          ______________
        База:                             і            і
                                          і____________і
                           _______________
        Смещение:          і             і
                           і_____________і
                                  ________
        Старший байт:             і      і
                                  і______і
                           ________
        Младший байт:      і      і
                           і______і

t0        Тип адресного поля указывается в поле LOC поля LOCAT
        записи   FIXUPP,  а  его  местоположение  -  в  поле
        DATA_RECORD_OFFSET того же поля LOCAT.

     б) Сборщик Microsoft linker выполняет привязку в одном
        из двух режимов:

        - Внутрисегментный режим используется для привязки
          8-битовых  и  16-битовых  смещений,  указываемых  в
          командах CALL, JUMP и JUMP SHORT.
        - Межсегментный режим используется при всех других
          режимах адресации (8086).

     в) Цель это объект в MAS к которому осуществляется
        обращение ( точнее, самый младший байт этого объекта ).
        Сборщик определяет цель одним из шести способов, причем
        три способа из указанных являются основными.
        Каждый  из  основных  способов  использует  два  вида
        данных - индекс Х и смещение D:

        Метод      Определение цели
        ______________________________________________________
        (Т0)       Х - это индекс сегмента. Цель это D-ный байт
                   в  логическом   сегменте, идентифицируемом
                   индексом сегмента.
        (Т1)       Х - это индекс группы. Цель это D-ный байт в
                   логическом    сегменте,   идентифицируемом
                   индексом группы.
        (Т2)       Х - это индекс внешнего имени. Этот индекс
                   идентифицирует внешнее имя, которое, в свою
                   очередь, дает адрес соответствующего байта.
                   Целью является байт, D-ный после указанного.
        ______________________________________________________


                             - 242 -


        Остальные способы используют только один вид данных -
        индекс Х, т.е. смещение D считается равным нулю.

        Метод      Определение цели
        ______________________________________________________
        (Т4)       Х - это индекс сегмента. Цель это первый
                   байт в ЛСЕГ, идентифицируемом индексом сег-
                   мента.
        (Т5)       Х - это индекс группы. Цель это первый байт
                   в логическом сегменте указанной группы. Этот
                   ЛСЕГ идет первым в группе.
        (Т6)       Х - это индекс внешнего имени. Целью
                   является байт, который адресуется  внешним
                   именем,    которое,    в   свою   очередь,
                   идентифицируется индексом внешнего имени.
        _______________________________________________________

        Таким  образом,  определение  цели   можно   записать
        следующим образом:

        Номенклатура                        Метод
        ______________________________________________________
        Цель: SI(имя сегмента), смещение    Т0
        Цель: GI(имя группы), смещение      Т1
        Цель: EI(внешнее имя), смещение     Т2
        Цель: SI(имя сегмента)              Т4
        Цель: GI(имя группы)                Т5
        Цель: EI(внешнее имя)               Т6
        ______________________________________________________

        Примеры:

        Цель: SI(CODE),1024      - 1025-ый байт в сегменте
                                   CODE.
        Цель: GI(DATAAREA)       - Позиция в MAS группы с
                                   именем DATAAREA.
        Цель: EI(SIN)            - Адрес внешней процедуры
                                   SIN.
        Цель: EI(PAYSCHEDULE),24 - 24-ый  байт во внешней
                                   структуре  данных
                                   PAYSCHEDULE.

     г) Каждая ячейка памяти, к которой происходит  обращение
        содержится в том или ином фрагменте.   Этот  фрагмент
        определяется содержимым сегментного регистра. Для фор-
        мирования корректной ссылки к памяти, сборщик должен
        знать цель и фрагмент, к которому выполняется обраще-
        ние. Существует пять способов определения фрагмента.
        При этом используются индекс Х и данные (необязатель-
        но):

        Метод      Определение фрагмента
        ______________________________________________________
        (F0)       Х - это индекс сегмента. Фрагментом является
                   канонический фрагмент логического сегмента,
                   идентифицируемого индексом сегмента.
        (F1)       Х - это индекс группы. Фрагментом является
                   канонический фрагмент группы.
        (F2)       Х - это индекс внешнего имени. Фрагмент оп-
                   ределяется, когда сборщик находит определе-

                             - 243 -


                   ние внешнего имени как 'public'. При этом
                   существует две ситуации:

                   (F2a) - Отсутствие ассоциированной группы.
                           Фрагментом является канонический
                           фрагмент логического сегмента,
                           связанного с внешним именем.
                   (F2c) - ЛСЕГ входит в группу. Фрагментом
                           является канонический фрагмент
                           группы. (Группа указана в поле
                           GROUP_INDEX записи PUBDEF).

        (F4)       Нет индекса. Фрагмент это канонический фраг-
                   мент   логического  сегмента,  содержащего
                   адресное поле.
        (F5)       Нет индекса. Цель определяет фрагмент. При
                   возможны три ситуации:

                   (F5a) - Цель определяет  индекс  сегмента.
                           Фрагмент определяется способом (F0).
                   (F5b) - Цель определяет индекс группы.
                           Фрагмент определяется способом (F1).
                   (F5c) - Цель  определяет индекс внешнего
                           имени. Фрагмент определяется спосо-
                           бом (F2).
        ______________________________________________________

        Ниже приведена номенклатура определений фрагмента:

        Фрагмент: SI (Имя сегмента)   (F0)
        Фрагмент: GI (Имя группы)     (F1)
        Фрагмент: EI (Внешнее имя)    (F2)
        Фрагмент: Адресное поле       (F4)
        Фрагмент: Цель                (F5)
        Фрагмент:  -                  (F6)

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


     7.3.1 Внутрисегментная привязка

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

     - Если адресное поле  представляет  собой  смещение,  то
       сборщик прибавляет его (по модулю 65536) к значению IP.
     - Если  адресное  поле  это  младший  байт,  то сборщик
       прибавляет его (по модулю 256) к значению IP.
     - Если адресное поле это база, указатель или старший байт,
       то намерения транслятора неясны, а  действия  сборщика
       неопределены.

                             - 244 -



     7.3.2 Межсегментная привязка

     Межсегментная   привязка  выполняется  следующим образом.
     Неотрицательный 16-битовый номер, FBVAL,  определен,  как
номер фрагмента или значение селектора, указанных при привязке.
Знаковый  20-битный  номер,  FOVAL, определен, как расстояние
между базой фрагмента и  целью.  Если  этот  20-битный  номер
меньше  0  или  больше  65535, то сборщик выдает сообщение об
ошибке. В противном случае сборщик использует значения  FBVAL
и FOVAL для привязки адресного поля следующим образом.

     - Если адресное поле это указатель, то сборщик прибавляет
       FBVAL  (по модулю 65536) к старшему слову указателя, а
       FOVAL (по модулю 65536) к младшему слову указателя.
     - Если адресное поле это  база,  то  сборщик  прибавляет
       FBVAL (по модулю 65536) к базе и игнорирует FOVAL.
     - Если адресное поле это смещение, то сборщик прибавляет
       FOVAL (по модулю 65536) к смещению и игнорирует FBVAL.
     - Если  адресное  поле  это  старший  байт,  то сборщик
       прибавляет (FOVAL/256)(по модулю 256) к старшему байту и
       игнорирует FBVAL. (При делении берется только целое).
     - Если  адресное  поле  это  младший  байт,  то  сборщик
       прибавляет (FOVAL/256)(по модулю 256) к младшему слову и
       игнорирует FBVAL.


     7.4 Последовательность записей

     Ниже  приведен  допустимый  порядок следования записей в
объектном модуле.
     _________________________________________________________
     Примечание
               Описательный     язык,     используемый      в
               нижеприведенной  синтаксической схеме подробно
               рассматривается в WIRTH: CAMC, November 1977,
               том 20, N 11, стр. 822-823. Сами записи (выделе-
               ны заглавными буквами) рассмотриваются в следую-
               щих разделах.
     _________________________________________________________

  object file   = tmodule
  tmodule       = {THEADR | LHEADR} seg-grp {component} modtail
  seg-grp       = {LNAMES} {SEGDEF} {EXTDEF | GRPDEF}
  component     = data | debug-record
  data          = content-def | thread-def |
                       PUBDEF | EXTDEF | COMDEF | LOCSYM
  debug-record  = LINNUM
  content-def   = data-record {FIXUPP}
  thread-def    = FIXUPP (содержащая только поля thread)
  data-record   = LIDATA | LEDATA
  modtail       = MODEND

  - Запись FIXUPP всегда относится к предыдущей записи данных.
  - Все   записи  LNAMES,  SEGDEF,  GRPDEF  и  EXTDEF  должны
    предшествовать всем записям, обращающимся к ним.
  - Запись комментариев может быть  в  любом  месте  файла.
    Однако она не может быть первой или последней записью файла,
    а также входить в content-def.


                             - 245 -



     7.5 Форматы записей

     Далее  в книге излагаются форматы записей в схематической
форме. Первым приводится формат записи  примера  для  введения
основных понятий и терминов.

     7.5.1 Формат записи примера (SAMREC)
t1
     ______________________///__________іііі___________
     і rec і  record   і   name    і   number   і chk і
     і typ і  length   і           і            і sum і
     і xxH і           і           і            і     і
     і_____і___________і___///_____і____іііі____і_____і
                       і____rpt____і
t0
     а) Название и официальная аббревиатура

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

     б) Блоки

        Каждый  формат изображен в виде блоков двух размеров.
        Узкий блок представляет один  байт.  Простой  широкий
        блок  представляет  два  байта.  Если  сверху и снизу
        широкого  блока  помещены  три  наклонные  черты,  то
        размер  блока зависит от его содержимого и может быть
        равен  одному  или  более  байтам.  Широкий  блок   с
        четыремя   вертикальными   чертами   сверху  и  снизу
        представляет четыре байта.

     в) rectyp

        Первый байт каждой записи содержит значение от нуля до
        255, указывающее тип записи.

     г) record length

        Второе поле в каждой записи содержит количество байт в
        записи, исключая первые два поля и представляет собой
        16-битное число (младший байт идет первым).

     д) name

        Это поле содержит имя. Любое  поле,  содержащее  имя,
        имеет следующую структуру: первый байт содержит число
        от  0  до  127  включительно и указывает число байт в
        поле, не считая байт длины.

     е) number

        Четырехбайтное    поле   номера   содержит   32-битное
        беззнаковое целое.

     ж) rpt или cond

        Если участок формата помечен снизу скобкой и подписью

                             - 246 -


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

     з) chksum

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

     и) поля бит

        Содержание некоторых полей может описываться на уровне
        бит. Например, следующий  байт  имеет  три  поля  бит,
        длиною, соответственно 3, 1 и 4 бита:
t1
        ________________________________
        і         і    і               і
        і_________і____і_______________і
             3      1          4


     7.5.2 Заголовочная запись Т-модуля (THEADR)

     ______________________///____________
     і rec і  record   і T-module  і chk і
     і typ і  length   і name      і sum і
     і 80H і           і           і     і
     і_____і___________і___///_____і_____і

     Поле T-module name содержит имя Т-модуля.


     7.5.3 Заголовочная запись L-модуля (LHEADR)

     ______________________///____________
     і rec і  record   і L-module  і chk і
     і typ і  length   і name      і sum і
     і 82H і           і           і     і
     і_____і___________і___///_____і_____і

t0     L-module name содержит имя L-модуля.
     Каждый модуль должен иметь  заголовочную  запись  THEADR
     или  LHEADR.  Эта  запись  всегда  идет первой в модуле.
     Любые другие  записи  будут  проигнорированы  сборщиком.
     LHEADR  идентична  THEADR,  за  исключением лишь rectyp,
     равного 82Н.


     7.5.4 Запись списка имен (LNAMES)

t1     ______________________///____________
     і rec і  record   і           і chk і
     і typ і  length   і   name    і sum і
     і 96H і           і           і     і
     і_____і___________і___///_____і_____і
                       і___rpt_____і
t0

                             - 247 -


     Запись LNAMES содержит список имен,  которые  последующие
     записи SEGDEF и GRPDEF могут использовать в качестве имен
     сегментов, классов и/или групп.
     Порядок  записей  LNAMES в модуле и порядок имен в записи
     LNAMES составлен так, что каждое имя имеет  свой  номер
     (1, 2, 3 и т.д.), используемый в качестве индекса имени в
     полях  Group  name index, Class name index и Segment name
     index записей SEGDEF и GRPDEF.
     Имя, указываемое в поле name, может иметь и нулевую длину.


     7.5.5 Запись определения сегмента (SEGDEF)
t1
_________________///______________///______///_____///_______
іrecі record і segmentі segmentі segmentі class іoverlayіchkі
іtypі length і attr   і length і name   і name  іname   іsumі
і98Hі        і        і        і index  і index іindex  і   і
і___і________і___///__і________і__///___і__///__і__///__і___і

t0     Индекс сегмента может принимать значения от 1 до 32767  и
используется в других записях для ссылки на определенный ЛСЕГ.
Нумерация  индексов определяется последовательностью появления
в объектном файле записей SEGDEF.

     а) segment attr

        Это поле содержит информацию о различных атрибутах
        сегмента и имеет следующий формат:
t1        ________________________
        іacbpі frame  і offset і
        і    і number і        і
        і____і________і________і
             і_______cond______і

        - Байт ACBP  имеет следующий формат:
          _________________________
          і   a   і   c   і b і p і
          і_______і_______і___і___і
              3       3     1   1
t0
          Битовое  поле  А  (выравнивание)  указывает  атрибут
          выравнивания ЛСЕГ:

          А=0  -  SEGDEF   описывает абсолютный ЛСЕГ
          A=1  -  SEGDEF   описывает   перемещаемый   ЛСЕГ,
                  выравненный на границу байта.
          A=2  -  SEGDEF   описывает   перемещаемый   ЛСЕГ,
                  выравненный на границу слова.
          A=3  -  SEGDEF   описывает   перемещаемый   ЛСЕГ,
                  выравненный на границу параграфа.
          A=4  -  SEGDEF   описывает   перемещаемый   ЛСЕГ,
                  выравненный на границу страницы (256 байт).

                  Если  А=0,  то  поля  Frame  number  (номер
                  фрагмента)      и     offset     (смещение)
                  присутствуют.  Сборщик   Microsoft   linker
                  поддерживает    использование    абсолютных
                  сегментов только для  адресации,  например,
                  для  определения  стартового  адреса  ПЗУ и
                  определения   символических   имен   вместо

                             - 248 -


                  адресов   ПЗУ.   Сборщик  игнорирует  любые
                  данные, принадлежащие абсолютному  сегменту
                  , и выводит предупреждение, если абсолютные
                  сегменты     определены    для    программ,
                  запускаемых в защищенном режиме.

          Битовое  поле  С  (сочетание)  определяет   атрибут
          сочетания  ЛСЕГ.  Для  абсолютных сегментов С равно
          нулю. Для перемещаемых сегментов, поле  С  кодирует
          способ сочетания сегментов (0,1,2,3,4,5,6 и 7). Для
          интерпретации     этого     атрибута     необходимо
          предварительно   рассмотреть   принципы   сочетания
          логических сегментов. Допустим, например, что X и Y
          это   логические   сегменты,  а  Z  это  логический
          сегмент, получаемый в результате комбинации X и  Y.
          Пусть LX и LY это длины соответственно Х и Y, a MXY
          это  их общая длина. Пусть G это промежуток между Х
          и Y (определяется атрибутом выравнивания), а LZ это
          длина Z (сумма LХ, LY  и  промежутка  между  ними).
          Пусть  теперь dx (0

© KOAP Open Portal 2000


?????? ???????????