DEMO.DESIGN
Frequently Asked Questions
 
оглавление | demo party в ex-СССР | infused bytes e-mag | новости от ib/news | другие проекты | письмо | win koi lat

следующий фpагмент (2)
__________________________________________________________ ГЛАВА 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) -- 448 -- 7.5.14 Запись привязки (FIXUPP) 7.5.15 Конечная запись модуля (MODEND) 7.5.16 Запись комментариев (COMENT) 7.6 Представление типа для переменных 'communal' __________________________________________________________ -- 449 -- 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. -- 450 -- Модуль - это неделимое единство объектного кода и другой информации, создаваемое в результате работы транслятора. Т-модуль - это модуль, создаваемый такими трансляторами, как Pascal или FORTRAN. _______________________________________________ - Каждый модуль должен иметь имя. Если таковое не указано, то транслятор присваивает имя по умолчанию (имя файла или нулевое имя). - Каждый Т-модуль в группе модулей должен иметь уникальное имя. Для сборщика Microsoft linker это не обязательно. _________________________________________________ Фрагмент - это непрерывный участок MAS, длиной 64К, начинающийся на границе параграфа (или на селекторе 80286). Сегментные регистры процессора определяют только четыре фрагмента (возможно перекрывающихся). Ни один 16-разрядный адрес не имеет доступа к памяти вне четырех текущих фрагменов. Логический сегмент (ЛСЕГ) - непрерывный участок памяти, чье содержимое определяется во время трансляции (за исключением адресной привязки). Размер ЛСЕГ также не окончателен, т.к. при сборке несколько ЛСЕГ могут быть объеденены в один ЛСЕГ. Размер ЛСЕГ не должен превышать 64К. Таким -- 451 -- образом, 16-битовое смещение от базы фрагмента, содержащего ЛСЕГ, может адресовать любой байт в ЛСЕГ. Физический сегмент (ФСЕГ) - Эквивалент термина "Фрагмент". Номер фрагмента - Каждый фрагмент начинается на границе параграфа. Параграфы памяти (16 байт) можно пронумеровать от 0 до 65535. Эти номера и являются номерами соответствующих фрагментов. Группа - это несколько ЛСЕГ, определенных во время трансляции, чье положение в MAS скомпановано таким образом, что существует хотя бы один фрагмент, перекрывающий все ЛСЕГ в группе. Запись "Гр А(X,Y,Z)" означает, что логические сегменты X, Y и Z формируют группу А. Эта запись не содержит никакой информации о взаимном расположении сегментов. Текущая версия сборщика Microsoft не допускает принадлежности логического сегмента к более чем одной группе. Канонический фрагмент - Каждая ячейка MAS содержится в 4096 фрагментах, один из которых имеет наибольший номер. Этот фрагмент называется каноническим фрагментом данной ячейки памяти. Другими словами, каноническим фрагментом данной ячейки памяти является фрагмент, смещение от на- -- 452 -- чала которого данной ячейки памяти находится в пределах 0-15. Это понятие применимо и группе ячеек, например, канонический фрагмент ЛСЕГ или канонический фрагмент группы ЛСЕГ. Имя сегмента - Каждому ЛСЕГ назначается имя во время трансляции. Это делается по следующим причинам: - необходимо определить во время сборки, какие ЛСЕГ скомбинированы друг с другом; - необходимо указать членство в группах. Имя класса - Во время трансляции логическому сегменту может быть назначено имя класса. Два ЛСЕГ принадлежат одному классу, если они имеют одинаковые имена класса. Имена класса имеют следующий смысл: имя класса "CODE" или любое имя класса с с таким суффиксом подразумевает, что все сегменты того класса содержат только код. Имя наложения - Логическому сегменту может быть назначено имя наложения. Это имя игнорируется сбор- щиками Microsoft версий 3.0 и позже, однако стандартный сборщик Microsoft поддерживает его. Полное имя - Полное имя ЛСЕГ включает имя сегмента, имя класса и имя наложения. Сборщик соединяет -- 453 -- логические сегменты из различных модулей, если совпадают их полные имена. 7.2 Идентификация модуля и атрибуты Заголовочная запись модуля содержит имя модуля и всегда идет первой в модуле. Кроме этого, модуль может представлять собой главную программу (main) с указанием стартового адреса. При сборке различных модулей, вы должны указать только один модуль, имеющий атрибут main. Если таковых будет несколько, то главным будет считаться первый. Суммируя сказанное, модули могут или не могут быть главными и могут иметь или не могут иметь стартовый адрес. 7.2.1 Определение сегмента Модуль представляет собой совокупность объектного кода, описываемую последовательностью записей, создаваемых транслятором. Объектный код представляет собой непрерывные участки памяти, содержимое которых определяется во время трансляции. Этими участками являются логические сегменты. Модуль определяет атрибуты каждого ЛСЕГ. Запись определения сегмента (SEGDEF) содержит всю информацию по ЛСЕГ (имя, длина, выравнивание и т.п.). Сборщик запрашивает эту информацию, когда комбинирует различные ЛСЕГ и устанавливает сегментную адресацию. SEGDEF всегда следует за заголовочной записью. 7.2.2 Адресация сегмента Механизм адресации микропроцессора 8086 обеспечивает -- 454 -- адресацию 64К памяти в каждом из четырех фрагментов, адресуемых базовыми регистрами - CS (регистр сегмента кодов), DS и ES (регистры сегмента данных) и SS (регистр стэкового сегмента). Возможное количество ЛСЕГ, составляющих образ памяти, чаще всего намного превышает количество имеющихся сегментных (базовых) регистров. Поэтому при модульном программировании, когда собираются множество небольших ЛСЕГ, требуется частая перезагрузка базовых регистров. Разумеется, такая перезагрузка нежелательна. Лучше всего собирать небольшие по размеру ЛСЕГ вместе в один блок, помещающийся в одном фрагменте. В этом случае все ЛСЕГ можно адресовать, использую один и тот же базовый регистр. Таким блоком и является группа (см. Раздел 7.1.1). Для введения взаимной адресации внутри группы, вы должны явно определить каждую группу в модуле. Запись определения группы (GRPDEF) как раз предназначена для этого и содержит список имен сегментов. GRPDEF следует сразу за всеми SEGDEF, т.к. GRPDEF обращается к ним для описания группы. Все остальные записи идут после GRPDEF. 7.2.3 Определение имен Определение имен осуществляется с помощью трех типов записей - PUBDEF, COMDEF и EXTDEF. -- 455 -- 7.2.4 Индексы Понятие индекс понимается в этой главе, как целое, указывающее на конкретный элемент из списка элементов. Например, индекс имени, индекс сегмента, индекс группы, индекс типа и т.п. _________________________________________________________ Примечание Индекс обычно положительное число. Значение ноль зарезервировано и может нести особый смысл, в зависимости от типа индекса (например, нулевой индекс сегмента указывает на абсолютный псевдо- сегмент без имени; нулевой индекс типа указывает на тип "без типа". _________________________________________________________ В целом, значения индексов в объектных файлах обычно не превышают 50-100, поэтому отводимая для них память также не превышает 1-2 байта. Если старший бит первого (и возможно единственного) байта равен нулю, то значение индекса варьируется в пределах 0-127 и занимает один байт. Если этот бит равен 1, то значение индекса это число, между 0 и 32К-1, занимающее два байта и определяемое следующим образом: младшие восемь бит во втором байте, а старшие семь бит в первом байте. -- 456 -- 7.3 Концепция привязки Привязка это адресная привязка объектного кода, запраши- ваемая транслятором и выполненная сборщиком. Для специфицирования привязки необходимо указать четыре типа данных: - Место и тип привязываемого адресного поля. - Один из двух возможных режимов привязки. - Цель, т.е. адрес в памяти к которому обращается адресное поле. - Фрагмент, к которому имеет место обращение. а) Существует пять типов адресных полей: - Указатель (старшее слово имеет больший адрес). - База это старшее слово указателя (сборщику безразлично, есть ли младшее слово указателя или нет). - Смещение это младшее слово указателя (сборщику безразлично, следует ли за ним старшее слово). - Старший байт это старший байт смещения (сборщику безразлично, предшествует ли младший байт). - Младший байт это младший байт смещения (сборщику безразлично следует ли за ним старший байт). -- 457 -- _____________________________ Указатель: ¦ ¦ ¦___________________________¦ ______________ База: ¦ ¦ ¦____________¦ _______________ Смещение: ¦ ¦ ¦_____________¦ ________ Старший байт: ¦ ¦ ¦______¦ ________ Младший байт: ¦ ¦ ¦______¦ Тип адресного поля указывается в поле LOC поля LOCAT записи FIXUPP, а его местоположение - в поле DATA_RECORD_OFFSET того же поля LOCAT. б) Сборщик Microsoft linker выполняет привязку в одном из двух режимов: - Внутрисегментный режим используется для привязки 8-битовых и 16-битовых смещений, указываемых в командах CALL, JUMP и JUMP SHORT. - Межсегментный режим используется при всех других режимах адресации (8086). в) Цель это объект в MAS к которому осуществляется обращение ( точнее, самый младший байт этого объекта ). Сборщик определяет цель одним из шести способов, причем три способа из указанных являются основными. -- 458 -- Каждый из основных способов использует два вида данных - индекс Х и смещение D: Метод Определение цели ______________________________________________________ (Т0) Х - это индекс сегмента. Цель это D-ный байт в логическом сегменте, идентифицируемом индексом сегмента. (Т1) Х - это индекс группы. Цель это D-ный байт в логическом сегменте, идентифицируемом индексом группы. (Т2) Х - это индекс внешнего имени. Этот индекс идентифицирует внешнее имя, которое, в свою очередь, дает адрес соответствующего байта. Целью является байт, D-ный после указанного. ______________________________________________________ Остальные способы используют только один вид данных - индекс Х, т.е. смещение D считается равным нулю. Метод Определение цели ______________________________________________________ (Т4) Х - это индекс сегмента. Цель это первый байт в ЛСЕГ, идентифицируемом индексом сег- мента. (Т5) Х - это индекс группы. Цель это первый байт в логическом сегменте указанной группы. Этот ЛСЕГ идет первым в группе. (Т6) Х - это индекс внешнего имени. Целью является байт, который адресуется внешним именем, которое, в свою очередь, идентифицируется индексом внешнего имени. _______________________________________________________ -- 459 -- Таким образом, определение цели можно записать следующим образом: Номенклатура Метод ______________________________________________________ Цель: 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. г) Каждая ячейка памяти, к которой происходит обращение содержится в том или ином фрагменте. Этот фрагмент определяется содержимым сегментного регистра. Для фор- мирования корректной ссылки к памяти, сборщик должен знать цель и фрагмент, к которому выполняется обраще- ние. Существует пять способов определения фрагмента. При этом используются индекс Х и данные (необязатель- но): -- 460 -- Метод Определение фрагмента ______________________________________________________ (F0) Х - это индекс сегмента. Фрагментом является канонический фрагмент логического сегмента, идентифицируемого индексом сегмента. (F1) Х - это индекс группы. Фрагментом является канонический фрагмент группы. (F2) Х - это индекс внешнего имени. Фрагмент оп- ределяется, когда сборщик находит определе- ние внешнего имени как 'public'. При этом существует две ситуации: (F2a) - Отсутствие ассоциированной группы. Фрагментом является канонический фрагмент логического сегмента, связанного с внешним именем. (F2c) - ЛСЕГ входит в группу. Фрагментом является канонический фрагмент группы. (Группа указана в поле GROUP_INDEX записи PUBDEF). (F4) Нет индекса. Фрагмент это канонический фраг- мент логического сегмента, содержащего адресное поле. (F5) Нет индекса. Цель определяет фрагмент. При возможны три ситуации: (F5a) - Цель определяет индекс сегмента. Фрагмент определяется способом (F0). (F5b) - Цель определяет индекс группы. Фрагмент определяется способом (F1). (F5c) - Цель определяет индекс внешнего имени. Фрагмент определяется спосо- -- 461 -- бом (F2). ______________________________________________________ Ниже приведена номенклатура определений фрагмента: Фрагмент: SI (Имя сегмента) (F0) Фрагмент: GI (Имя группы) (F1) Фрагмент: EI (Внешнее имя) (F2) Фрагмент: Адресное поле (F4) Фрагмент: Цель (F5) Фрагмент: - (F6) Таким образом, при внутрисегментных ссылках фрагментом обычно является канонический фрагмент логи- ческого сегмента, содержащего адресное поле. Аналогично, фрагментом при межсегментных ссылках является канонический фрагмент логического сегмента, содержащего цель. -- 462 -- 7.3.1 Внутрисегментная привязка Внутрисегментная привязка выполняется следующим образом. Если адресное поле или цель находятся вне указанного фрагмента, то сборщик выдает предупреждение. В противном случае смещение цели относительно фрагмента будет равно сумме значений регистра IP на момент ссылки (указывает на байт, содержащий код следующей команды) и указываемого смещения. - Если адресное поле представляет собой смещение, то сборщик прибавляет его (по модулю 65536) к значению IP. - Если адресное поле это младший байт, то сборщик прибавляет его (по модулю 256) к значению IP. - Если адресное поле это база, указатель или старший байт, то намерения транслятора неясны, а действия сборщика неопределены. 7.3.2 Межсегментная привязка Межсегментная привязка выполняется следующим образом. Неотрицательный 16-битовый номер, FBVAL, определен, как номер фрагмента или значение селектора, указанных при привязке. Знаковый 20-битный номер, FOVAL, определен, как расстояние между базой фрагмента и целью. Если этот 20-битный номер меньше 0 или больше 65535, то сборщик выдает сообщение об ошибке. В противном случае сборщик использует значения FBVAL и FOVAL для привязки адресного поля следующим образом. - Если адресное поле это указатель, то сборщик прибавляет FBVAL (по модулю 65536) к старшему слову указателя, а FOVAL (по модулю 65536) к младшему слову указателя. - Если адресное поле это база, то сборщик прибавляет FBVAL (по модулю 65536) к базе и игнорирует FOVAL. -- 463 -- - Если адресное поле это смещение, то сборщик прибавляет FOVAL (по модулю 65536) к смещению и игнорирует FBVAL. - Если адресное поле это старший байт, то сборщик прибавляет (FOVAL/256)(по модулю 256) к старшему байту и игнорирует FBVAL. (При делении берется только целое). - Если адресное поле это младший байт, то сборщик прибавляет (FOVAL/256)(по модулю 256) к младшему слову и игнорирует FBVAL. -- 464 -- 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. -- 465 -- 7.5 Форматы записей Далее в книге излагаются форматы записей в схематической форме. Первым приводится формат записи примера для введения основных понятий и терминов. 7.5.1 Формат записи примера (SAMREC) ______________________///__________¦¦¦¦___________ ¦ rec ¦ record ¦ name ¦ number ¦ chk ¦ ¦ typ ¦ length ¦ ¦ ¦ sum ¦ ¦ xxH ¦ ¦ ¦ ¦ ¦ ¦_____¦___________¦___///_____¦____¦¦¦¦____¦_____¦ ¦____rpt____¦ а) Название и официальная аббревиатура Для упрощения унификации различных программ, включая трансляторы и отладчики, используйте официальную абб- ревиатуру как в коде, так и в документации. Ее длина всегда шесть букв. б) Блоки Каждый формат изображен в виде блоков двух размеров. Узкий блок представляет один байт. Простой широкий блок представляет два байта. Если сверху и снизу широкого блока помещены три наклонные черты, то размер блока зависит от его содержимого и может быть равен одному или более байтам. Широкий блок с четыремя вертикальными чертами сверху и снизу представляет четыре байта. -- 466 -- в) rectyp Первый байт каждой записи содержит значение от нуля до 255, указывающее тип записи. г) record length Второе поле в каждой записи содержит количество байт в записи, исключая первые два поля и представляет собой 16-битное число (младший байт идет первым). д) name Это поле содержит имя. Любое поле, содержащее имя, имеет следующую структуру: первый байт содержит число от 0 до 127 включительно и указывает число байт в поле, не считая байт длины. е) number Четырехбайтное поле номера содержит 32-битное беззнаковое целое. ж) rpt или cond Если участок формата помечен снизу скобкой и подписью rpt, то это означает, что помеченный участок может повторяться. Если участок формата помечен снизу скобкой и подписью cond, то это означает, что наличие помеченного участка зависит от истинности некоторого условия. з) chksum -- 467 -- Последним полем в каждой записи является поле chksum, содержащее дополнение до двух суммы (по модулю 256) всех остальных байт в записи. -- 468 -- и) поля бит Содержание некоторых полей может описываться на уровне бит. Например, следующий байт имеет три поля бит, длиною, соответственно 3, 1 и 4 бита: ________________________________ ¦ ¦ ¦ ¦ ¦_________¦____¦_______________¦ 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 ¦ ¦ ¦ ¦ ¦_____¦___________¦___///_____¦_____¦ L-module name содержит имя L-модуля. Каждый модуль должен иметь заголовочную запись THEADR -- 469 -- или LHEADR. Эта запись всегда идет первой в модуле. Любые другие записи будут проигнорированы сборщиком. LHEADR идентична THEADR, за исключением лишь rectyp, равного 82Н. -- 470 -- 7.5.4 Запись списка имен (LNAMES) ______________________///____________ ¦ rec ¦ record ¦ ¦ chk ¦ ¦ typ ¦ length ¦ name ¦ sum ¦ ¦ 96H ¦ ¦ ¦ ¦ ¦_____¦___________¦___///_____¦_____¦ ¦___rpt_____¦ Запись LNAMES содержит список имен, которые последующие записи SEGDEF и GRPDEF могут использовать в качестве имен сегментов, классов и/или групп. Порядок записей LNAMES в модуле и порядок имен в записи LNAMES составлен так, что каждое имя имеет свой номер (1, 2, 3 и т.д.), используемый в качестве индекса имени в полях Group name index, Class name index и Segment name index записей SEGDEF и GRPDEF. Имя, указываемое в поле name, может иметь и нулевую длину. -- 471 -- 7.5.5 Запись определения сегмента (SEGDEF) _________________///______________///______///_____///_______ ¦rec¦ record ¦ segment¦ segment¦ segment¦ class ¦overlay¦chk¦ ¦typ¦ length ¦ attr ¦ length ¦ name ¦ name ¦name ¦sum¦ ¦98H¦ ¦ ¦ ¦ index ¦ index ¦index ¦ ¦ ¦___¦________¦___///__¦________¦__///___¦__///__¦__///__¦___¦ Индекс сегмента может принимать значения от 1 до 32767 и используется в других записях для ссылки на определенный ЛСЕГ. Нумерация индексов определяется последовательностью появления в объектном файле записей SEGDEF. а) segment attr Это поле содержит информацию о различных атрибутах сегмента и имеет следующий формат: ________________________ ¦acbp¦ frame ¦ offset ¦ ¦ ¦ number ¦ ¦ ¦____¦________¦________¦ ¦_______cond______¦ - Байт ACBP имеет следующий формат: _________________________ ¦ a ¦ c ¦ b ¦ p ¦ ¦_______¦_______¦___¦___¦ 3 3 1 1 Битовое поле А (выравнивание) указывает атрибут выравнивания ЛСЕГ: А=0 - SEGDEF описывает абсолютный ЛСЕГ -- 472 -- A=1 - SEGDEF описывает перемещаемый ЛСЕГ, выравненный на границу байта. A=2 - SEGDEF описывает перемещаемый ЛСЕГ, выравненный на границу слова. A=3 - SEGDEF описывает перемещаемый ЛСЕГ, выравненный на границу параграфа. A=4 - SEGDEF описывает перемещаемый ЛСЕГ, выравненный на границу страницы (256 байт). Если А=0, то поля Frame number (номер фрагмента) и offset (смещение) присутствуют. Сборщик Microsoft linker поддерживает использование абсолютных сегментов только для адресации, например, для определения стартового адреса ПЗУ и определения символических имен вместо адресов ПЗУ. Сборщик игнорирует любые данные, принадлежащие абсолютному сегменту , и выводит предупреждение, если абсолютные сегменты определены для программ, запускаемых в защищенном режиме. Битовое поле С (сочетание) определяет атрибут сочетания ЛСЕГ. Для абсолютных сегментов С равно нулю. Для перемещаемых сегментов, поле С кодирует способ сочетания сегментов (0,1,2,3,4,5,6 и 7). Для интерпретации этого атрибута необходимо предварительно рассмотреть принципы сочетания логических сегментов. Допустим, например, что X и Y это логические сегменты, а Z это логический сегмент, получаемый в результате комбинации X и Y. Пусть LX и LY это длины соответственно Х и Y, a MXY это их общая длина. Пусть G это промежуток между Х -- 473 -- и Y (определяется атрибутом выравнивания), а LZ это длина Z (сумма LХ, LY и промежутка между ними). Пусть теперь dx (0<dx<LX) это смещение какого либо байта в Х, и, аналогично, dy это смещение в Y. Тогда атрибут сочетания С может быть представлен ввиде таблицы, где dx' и dy' это смещения в Z, байтов, имеющих смещения в Х и Y, соответственно dx и dy: ______________________________________________________ С LZ dx' dy' ______________________________________________________ 2 LX+LY+G dx dy+LX+G "Public" 5 LX+LY+G dx dy+LX+G "Stack" 6 MXY dx dy "Common" ______________________________________________________ Если С=0, то перемещаемый ЛСЕГ не может сочетаться. Значения 1 и 3 не определены. С=4 и С=7 тоже самое, что и С=2. Бит В при установке в единицу означает, что длина сегмента точно 64К (65536), при этом поле Segment length должно содержать ноль. Бит Р всегда равен нулю. - Поля Frame number и Offset (номер фрагмента и смещение) предназначены только лишь для указания адреса абсолютного сегмента в MAS (А=0). Величина смещения может принимать значения от 0 до 15 включительно. Если значение смещения превышает 15, то необходимо увеличить номер фрагмента. -- 474 -- б) segment length Это поле содержит длину сегмента в байтах. Длина может равняться нулю. В этом случае сегмент не удаляется из модуля, т.к. для указания длины сегмента, равной 64К, вы должны использовать бит В поля АСВР в поле segment attr, а описываемое поле сбросить в ноль. в) segment name index Имя сегмента это имя, которое программист или транслятор присваивает сегменту, например, code, data, modulename-code, taxdata или stack. Описываемое поле содержит индекс имени сегмента, т.е. указывает имя сегмента его индексом в списке имен записи LNAMES. г) class name index Имя класса это имя, которое программист или транслятор присваивает сегменту. Если таковое не присвоено, то его длина равна нулю. Имя класса дает программисту "рычаг" управления построением сегментов в MAS, например, red, white, blue; или rom, fastram, displayram. Описываемое поле содержит индекс имени класса, т.е. указывает имя класса его индексом в списке имен записи LNAMES. д) overlay name index Имя наложения это имя, которое транслятор и/или сборщик присваивает, по указанию программиста, -- 475 -- сегменту. Длина этого имени может равняться нулю. Описываемое поле содержит индекс имени наложения, т.е. указывает имя наложения его индексом в списке имен записи LNAMES. ________________________________________________________ Примечание Сборщики Microsoft версий 3.00 и позже игнорируют имя наложения. Это имя принимается во внимание стандартным сборщиком MS-DOS. ________________________________________________________ -- 476 -- 7.5.6 Запись определения группы (GRPDEF) ______________________///___________///_____________ ¦ rec ¦ record ¦ group ¦ group ¦ chk ¦ ¦ typ ¦ length ¦ name ¦ component ¦ sum ¦ ¦ 9AH ¦ ¦ index ¦ descriptor ¦ ¦ ¦_____¦___________¦___///_____¦_____///______¦_____¦ ¦___rpt________¦ а) group name index Сборщик может обращаться к группе ЛСЕГ по имени группы. Кроме того, всегда существует фрагмент, который покрывает в MAS все ЛСЕГ группы. Описываемое поле содержит индекс имени группы, т.е. указывает имя группы его индексом в списке имен записи LNAMES. б) group component descriptor Это повторяющееся поле (описатель компонента группы) имеет следующий формат: _____________///_______ ¦ FFH ¦ segment index ¦ ¦_____¦______///______¦ Первый байт поля равен 0FFH. Поле segment index (индекс сегмента) указывает ЛСЕГ, описываемый в одной из предыдущих записей SEGDEF. -- 477 -- 7.5.7 Запись определения имен 'public' (PUBDEF) _________________///_____///_______________///_______ ¦rec¦ record ¦ public ¦ public ¦ public ¦ type ¦chk¦ ¦typ¦ length ¦ base ¦ name ¦ offset ¦ index ¦sum¦ ¦90H¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦___¦________¦___///__¦__///___¦________¦__///__¦___¦ ¦____________rpt__________¦ Запись PUBDEF содержит список имен 'public'. Для каждого имени приводится три вида данных: (1) значение базы для имени, (2) значение смещения для имени и (3) тип имени. (1) public base Это поле имеет следующий формат: ____///______///______________ ¦ group ¦ segment ¦ frame ¦ ¦ index ¦ index ¦ number ¦ ¦___///__¦___///___¦_________¦ ¦___cond__¦ Формат поля group index был описан ранее и содержит значение от 0 до 32767, включительно. Его ненулевое значение ассоциирует группу с именем, имеющим атрибут 'public', и используется, как указано в Разделе 7.3 для случая (F2c). Нулевое значение индекса означает отсутствие ассоциируемой группы. Формат поля segment index был описан ранее и содержит значение от 0 до 32767, включительно. Ненулевое значение индекса указывает (выбирает) ЛСЕГ. В этом случае поле public -- 478 -- offset (смещение имени 'public') содержит смещение имени, указанного в поле public name (имя 'public'), относительно первого байта выбранного ЛСЕГ, при этом поле frame number (номер фрагмента) отсутствует. Нулевое значение индекса означает, что имена имеют абсолютные адреса в памяти. В этом случае индекс группы игнорируется, при этом поле frame number содержит номер фрагмента, а поле public offset смещение. Ненулевое значение индекса группы выбирает группу. Эта группа рассматривается, как "фрагмент" для обращений ко всем именам 'public', определенным в этой записи. Сборщик выполняет следующие действия: - Любую привязку следующей формы: Цель: EI(имя_'public') Фрагмент: цель сборщик преобразует в форму: Цель: SI(имя_сегмента),смещение Фрагмент: GI(имя_группы) Имя сегмента указывается индексом сегмента, а смещение полем public offset. - Когда сборщик преобразовывает имя 'public', используя значения полей segment index, public offset и возможно frame number, в пару {база:смещение}, то база из этой пары это база указанной группы. Нулевое значение индекса группы не выбирает никакой -- 479 -- группы. В качестве базы берется канонический фрагмент сегмента (ЛСЕГ или ФСЕГ), указываемого индексом сегмента. Поле public name (имя с атрибутом 'public') должно содержать соответствующее имя, длиной в один или несколько символов. (2) public offset Это поле содержит смещение (16 бит) имени 'public' относительно ЛСЕГ (если индекс сегмента больше нуля) или указанного фрагмента (если индекс сегмента равен нулю). (3) type index Это поле (индекс типа) идентифицирует единственную предшествующую запись TYPDEF (Запись определения типа), которая содержит описание типа объекта, представленного именем 'public'. Сборщик игнорирует это поле. -- 480 -- 7.5.8 Запись определения имен 'communal' (COMDEF) _________________///_______///____________________________ ¦rec¦ record ¦ communal ¦ type ¦ data ¦ communal ¦chk¦ ¦typ¦ length ¦ name ¦ index ¦ segment ¦ length ¦sum¦ ¦B0H¦ ¦ ¦ ¦ type ¦ ¦ ¦ ¦___¦________¦___///____¦__///___¦_________¦__________¦___¦ ¦____________________rpt_________________¦ Запись COMDEF содержит список из одного или более имен 'communal', определяющих переменные типа 'communal'. Переменная типа 'communal' это инициализированная переменная, чье конечное положение и размер не определены во время компиляции. Переменные типа 'communal' сходны с блоками 'common' языка ФОРТРАН, т.е. при сборке объектных модулей, каждый из которых объявляет переменную типа 'communal', размер памяти, отводимый переменной, равен размеру наибольшей из них. В языке СИ все инициадизированные переменные 'public' имеют тип 'communal'. Рассмотрим следующий пример объявления переменных типа 'communal' в языке СИ: char array[4] /* в файле а.с */ char array[1] /* в файле в.с */ char array[1024] /* в файле с.с */ При сборке объектных модулей, полученных из файлов а.с, в.с и с.с, сборщик выделит 1024 байта для символьного массива "array". Запись COMENT класса 161 должна предшествовать в модуле записи COMDEF. а) communal name -- 481 -- В этом поле содержится имя переменной типа 'communal', длиной в один или несколько символов. Такие имена рассматриваются как внешние и упорядочены вместе с внешними именами. Таким образом, обращение к ним осуществляется также, как и к внешнему имени через индекс (cм. описание записи EXTDEF). б) type index Это поле (индекс типа) игнорируется сборщиком Microsoft. в) data segment type Это однобайтовое поле идентифицирует сегмент данных, в котором находится переменная типа 'communal' и может содержать следующие значения: 62Н(FAR) - переменная находится в текущем сегменте данных. 61Н(NEAR) - переменная находится не в текущем сегменте данных. -- 482 -- г) communal length Это поле содержит длину переменной типа 'communal' в соответствии со значением поля data segment type. Если значение поля data segment type равно 62Н, то длина представлена в байтах. Если 61Н, то описываемое поле имеет следующий формат: _____///____________///_________ ¦ количество ¦ размер элемента ¦ ¦ элементов ¦ в байтах ¦ ¦____///_____¦______///________¦ Формат любого поля длины выглядит следующим образом: ___________ ¦ 0 - 127 ¦ ¦_________¦ _______________________________ ¦ 81Н ¦ ¦ ¦ от 0 до 64К-1 ¦_________¦_________¦_________¦ __________________________________________ ¦ 84Н ¦ ¦ ¦ ¦ от 0 до 16М-1 ¦_________¦_________¦_________¦__________¦ _____________________________________________________ ¦ 88Н ¦ ¦ ¦ ¦ ¦ ¦_________¦_________¦_________¦__________¦__________¦ от -2G-1 до 2G-1 Первый формат (один байт) может содержать значение от 0 до 127. Второй формат имеет лидирующий идентификационный байт 81Н и содержит значение в следующих двух байтах. -- 483 -- Третий формат имеет лидирующий идентификационный байт 84Н и содержит значение в следующих трех байтах. Четвертый формат имеет лидирующий идентификационный байт 88Н и содержит знаковое значение в следующих четырех байтах. Совпадающее с определением переменной типа 'communal' определение в PUBDEF затирает определение переменной типа 'communal'. Два определения переменной типа 'communal' совпадают, если совпадают имена в их определениях. Если два совпадающих определения различаются отношением к текущему сегменту ( FAR и NEAR ), то сборщик выбирает NEAR. Если переменная NEAR, то ее размер равен наибольшему из размеров, указанных для нее. Если переменная FAR, то в случае различия размеров элементов массива сборщик выдает предупреждение. Иначе, размер переменной равен размеру элемента, умноженному на наибольшее указанное количество элементов. Кроме того, сумма размеров всех переменных NEAR не должна превышать 64К, а сумма размеров всех переменных FAR - размер адресного пространства машины. Переменная FAR, размер которой превышает 64К (HUGE) размещается в последовательных сегментах (для 8086) или секторах (для 80286). Никакие другие данные не могут размещаться в сегментах, занимаемых HUGE-переменной типа 'communal'. Если сборщик находит совпадающие определения 'communal'- переменных HUGE и NEAR, то он выдает предупреждение, т.к. NEAR-переменная не может иметь размер, больший 64К. -- 484 -- 7.5.9 Запись определения имен 'local' (LOCSYM) _________________///_______///________________///_______ ¦rec¦ record ¦ local ¦ local ¦ local ¦ type ¦chk¦ ¦typ¦ length ¦ base ¦ name ¦ offset ¦ index ¦sum¦ ¦92H¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦___¦________¦___///___¦___///___¦_________¦__///___¦___¦ ¦__________rpt_______________¦ Запись LOCSYM содержит информацию для определения имен 'local'. Формат и назначение каждого из полей local base, local name, local offset и type index аналогичны формату и назначению соответствующих полей public base, public name, public offset и type index записи PUBDEF. Запись COMENT класса (161) должна предшествовать в модуле записи LOCSYM. -- 485 -- 7.5.10 Запись определения имен 'external' (EXTDEF) _________________///_________///________ ¦rec¦ record ¦ external ¦ type ¦chk¦ ¦typ¦ length ¦ name ¦ index ¦sum¦ ¦B0H¦ ¦ ¦ ¦ ¦ ¦___¦________¦___///____¦____///___¦___¦ ¦_________rpt_________¦ Запись EXTDEF содержит список имен 'external' и описание для каждого имени типа объекта, представляемого этим внешним именем. Сборщик присваивает каждому имени 'external' значения идентичных имен 'public' и 'local' (если идентичное имя будет найдено). а) external name Это поле содержит имя внешнего объекта. Это имя не может иметь нулевую длину. Включение имени в запись EXTDEF является явным запросом на сборку объектного файла с модулем, содержащим это же имя, объявленное как 'public', если имя не определено как 'local' в том же модуле, что и EXTDEF. Порядок записей EXTDEF в модуле и порядок внешних имен в самой записи EXTDEF вместе с записями COMDEF и именами 'communal' определяется индексацией всех внешних имен, запрашиваемых модулем, т.е. для обращения к конкретному внешнему имени сборщик использует индексы в полях target datum и/или frame datum записи FIXUPP. Индекс внешнего имени не может ссылаться вперед. Например, запись EXTDEF, определяющая N-ный объект, должна предшествовать любой записи, ссылающейся на объект с индексом N. -- 486 -- б) type index Это поле игнорируется сборщиком Microsoft, за исключением версий до 3.05 и объектных модулей без записи COMENT класса 161. Для этих случаев смотрите Раздел 7.6. -- 487 -- 7.5.11 Запись нумерации строк (LINNUM) _________________///_________________________ ¦rec¦ record ¦ line ¦ line ¦ line ¦chk¦ ¦typ¦ length ¦ number ¦ number ¦ number ¦sum¦ ¦94H¦ ¦ base ¦ ¦ offset ¦ ¦ ¦___¦________¦___///__¦________¦________¦___¦ ¦_______rpt_______¦ Эта запись позволяет транслятору соотносить номер строки исходного кода с соответствующей строкой транслированного кода. а) line number base Это поле (база номера строки) имеет следующий формат: ____///_______///____ ¦ group ¦ segment ¦ ¦ index ¦ index ¦ ¦___///___¦___///___¦ Поле group index (индекс группы) игнорируется сборщиком Microsoft. Поле segment index (инлекс сегмента) определяет положение первого байта кода, соответствующего строкам исходного кода. б) line number Это поле (номер строки) содержит двоичный номер строки от 0 до 32767 включительно. Если старший бит не равен нулю, то номер неопределен. -- 488 -- в) line number offset Это поле содержит 16-битное смещение номера строки по отношению к ЛСЕГ (если индекс сегмента больше нуля). 7.5.12 Логическая упорядоченная запись данных (LEDATA) __________________///__________________________ ¦rec¦ record ¦ segment ¦ enumerated ¦dat¦chk¦ ¦typ¦ length ¦ index ¦ data ¦ ¦sum¦ ¦A0H¦ ¦ ¦ offset ¦ ¦ ¦ ¦___¦_________¦___///____¦____________¦___¦___¦ ¦rpt¦ ¦___¦ Эта запись содержит связные данные, из которых сборщик затем строит часть образа памяти микропроцессора 8086. а) segment index Это поле (индекс сегмента) не может быть нулевым и содержит индекс, ссылающийся на одну из записей SEGDEF, предшествующих этой записи LEDATA. б) enumerated data offset Это поле (смещение упорядоченных данных) содержит смещение упорядоченных данных относительно ЛСЕГ, ука- занного индексом сегмента, т.е. смещение первого байта данных из поля dat. в) dat -- 489 -- Это поле содержит до 1024 последовательных байт перемещаемых или абсолютных данных. -- 490 -- 7.5.13 Логическая запись повторяемых данных (LIDATA) __________________///_____________________///________ ¦rec¦ record ¦ segment ¦ iterated ¦ iterated ¦chk¦ ¦typ¦ length ¦ index ¦ data ¦ data ¦sum¦ ¦A2H¦ ¦ ¦ offset ¦ block ¦ ¦ ¦___¦_________¦___///____¦___________¦____///___¦___¦ ¦____rpt___¦ Эта запись содержит связные данные, из которых сборщик затем строит часть образа памяти микропроцессора 8086. а) segment index Это поле (индекс сегмента) не может быть нулевым и содержит индекс, ссылающийся на одну из записей SEGDEF, предшествующих этой записи LIDATA. б) iterated data offset Это поле (смещение повторяемых данных) содержит смещение повторяемых данных относительно ЛСЕГ, ука- занного индексом сегмента, т.е. смещение первого байта данных из поля iterated data block. -- 491 -- в) iterated data block Это поле (блок повторяемых данных) содержит повторяе- мые данные и имеет следующий формат: _______________________________ ¦ repeat ¦ block ¦ content ¦ ¦ count ¦ count ¦ ¦ ¦_________¦_________¦___///___¦ _______________________________________________________ Примечание Сборщик не обрабатывает записи LIDATA, чьи блоки повторяемых данных превышают 512 байт. _______________________________________________________ - repeat count Это поле указывает число повторений содержимого поля content и не может иметь нулевое значение. - block count Значение этого поля может интерпретироваться следующим образом. Если оно равно нулю, то содержимое поля content понимается как последовательность байт данных. Если значение поля block count (число блоков) ненулевое, то в поле content содержатся новые блоки повторяемых данных, число которых указано в поле block count. - content -- 492 -- Значение этого поля может интерпретироваться следующим образом. Если значение поля block count равно нулю, то содержимое поля content понимается как последовательность байт данных. Если значение поля block count (число блоков) ненулевое, то в поле content содержатся новые блоки повторяемых данных, число которых указано в поле block count, т.е. первый байт поля content рассматривается как первый байт другого блока повторяемых данных. -- 493 -- 7.5.14 Запись привязки (FIXUPP) __________________///_________ ¦rec¦ record ¦ thread ¦chk¦ ¦typ¦ length ¦ или ¦sum¦ ¦9CH¦ ¦ fixup ¦ ¦ ¦___¦_________¦___///____¦___¦ ¦____rpt___¦ Запись FIXUPP может определять ноль и более привязок, каждая из которых обращается к адресному полю, содержащемуся в предыдущей записи данных. Запись данных может предшествовать нескольким записям FIXUPP, обращающимся к ней. Каждая привязка определяется в поле fixup следующими четыремя типами данных - адресное поле, режим, цель и фрагмент. Цель и фрагмент могут быть полностью определены как полем fixup, так и ссылкой на предыдущее поле thread. Поле thread определяет текущие цель или фрагмент, к которым в последствии можно ссылаться. Как только в поле thread определены цель или фрагмент, любое поле fixup, следующее за ним (в той же или последующих записях FIXUPP), может обращаться к цели или фрагменту, пока другое поле thread с тем же типом ( D ) и номером (0-3) не появится в той же или другой записи FIXUPP. -- 494 -- a) thread Это поле имеет следующий формат: _______///___ ¦trd¦ index ¦ ¦dat¦ ¦ ¦___¦__///__¦ ¦_cond__¦ - Поле trd dat представляет собой байт со следующей структкрой: _______________________________ ¦ 0 ¦ D ¦ 0 ¦ method ¦ trdnum ¦ ¦___¦___¦___¦________¦________¦ 1 1 1 3 2 Бит D определяет тип поля thread. Если D=0, то поле определяет цель. Если D=1, то поле определяет фрагмент. Битовое поле method содержит номер метода определения цели (D=0) или фрагмента (D=1), т.е. Т0, Т1, T2, T4, T5, T6 или F0, F1, F2, F4, F5. Как было описано выше, метод определяет тип используемого индекса (если используется). Битовое поле trdnum содержит номер от 0 до 3 включительно и ассоциирует этот номер поля thread с фрагментом или целью, определяемым в поле thread. - Поле index содержит индекс. Это может быть индекс сегмента, группы или внешнего имени, в зависимости от метода, указанного в поле method. Если указаны методы -- 495 -- F4 и F5, то поле index отсутствует. -- 496 -- б) fixup Это поле имеет следующий формат: _________________///_____///_________///_______ ¦ locat ¦fix¦ frame ¦ target ¦ target ¦ ¦ ¦dat¦ datum ¦ datum ¦ displacement ¦ ¦________¦___¦___///__¦__///___¦_____///______¦ ¦_______________cond_____________¦ - Два байта поля locat имеют следующую структуру: _____________________________________________________ ¦ 1 ¦ М ¦ 0 ¦ loc ¦ data record offset ¦ ¦___¦___¦___¦___________¦___________________________¦ ¦_______младший байт________¦____старший байт_______¦ Бит М указывает режим привязки: М=0 - внутрисегментный М=1 - межсегментный _______________________________________________ Примечание Внутрисегментный режим не применим для записей LIDATA. _______________________________________________ -- 497 -- Битовое поле loc (3 бита) определяет тип привязываемого адресного поля, содержащегося в предшествующей записи данных: 0 - младший байт 1 - смещение 2 - база 3 - указатель 4 - старший байт 5 - смещение (определяется загрузчиком) Все другие значения не разрешены. Поле data record offset содержит число от 0 до 1023 включительно, определяющее смещение адресного поля в предшествующей записи данных. Смещение вычисляется относительно первого байта данных. ________________________________________________ Примечание Если предшествующей записью является запись LIDATA, то вполне возможно, что смещение будет указывать на поля repeat count или block count блока повторяемых данных. В результате такой ошибочной ссылки действия сборщика не определены. _________________________________________________ -- 498 -- - Байт fix dat имеет следующий формат: _________________________________ ¦ F ¦ frame ¦ T ¦ P ¦ target ¦ ¦___¦__________¦___¦___¦________¦ 1 3 1 1 2 Бит F означает следующее: F=0 - Фрагмент определен в битовом поле frame. F=1 - Фрагмент определен в поле thread. Битовое поле frame может интерпретироваться двояко, в зависимости от значения бита F: F=0 - Поле frame указывает метод определения фрагмента 0-5, т.е. F0-F5. F=1 - Поле frame содержит номер поля thread, где дано определение фрагменту (поле thread может может находится в этой же или в одной из предшествующих записей FIXUPP). Бит Т означает следующее: Т=0 - Цель определена в поле fixup. Т=1 - Цель определена в поле thread. Бит Р означает следующее: Р=0 - Требуются данные о смещении цели. (Методы Т0, Т1 и Т2) Р=1 - Данные о смещении цели не требуются. -- 499 -- Битовое поле target может интерпретироваться двояко, в зависимости от значения бита Т: Т=0 - Поле target содержит число 0-3 включительно, соответствующее методам Т0, Т1, Т2 или Т4, Т5, Т6, в зависимости от значения бита Р. Т=1 - Поле target содержит номер поля thread, где дано определение цели. - Поле frame datum содержит индекс сегмента, группы или внешнего имени для спецификации фрагмента. Это поле отсутствует, если фрагмент определен в поле thread (F=1), или если он определен методами F4, F5 или F6. - Поле target datum содержит индекс сегмента, группы или внешнего имени для спецификации цели. Это поле отсутствует, если цель определена в поле thread (T=1). - Поле target displacement содержит 16-битное смещение, требуемое для определения цели методами Т0, Т1 и Т2. Если Р=1, то это поле отсутствует. __________________________________________________________ Примечание Описание всех методов определения цели и фрагмента приводится в Разделе 7.3. __________________________________________________________ -- 500 -- 7.5.15 Конечная запись модуля (MODEND) ______________________///_________ ¦rec¦ record ¦mod¦ start ¦chk¦ ¦typ¦ length ¦typ¦ address ¦sum¦ ¦8AH¦ ¦ ¦ ¦ ¦ ¦___¦_________¦___¦___///____¦___¦ ¦___cond___¦ Эта запись предназначена для указания сборщику конца модуля, а также для сообщения ему, содержит ли данный модуль стартовый адрес всей собираемой программы. а) mod typ Этот байт указывает атрибут модуля: _________________________________ ¦ mattr ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 1 ¦ ¦_______¦___¦___¦___¦___¦___¦___¦ 2 mattr Атрибут ______________________________________________________ 0 Не главный модуль без стартового адреса. 1 Не главный модуль со стартовым адресом. 2 Главный модуль без стартового адреса. 3 Главный модуль со стартовым адресом. ______________________________________________________ -- 501 -- б) start address Это поле имеет следующий формат (присутствует, если mattr равно 1 или 3): _______///______///___________________ ¦end¦ frame ¦ target ¦ target ¦ ¦dat¦ datum ¦ datum ¦ displacement ¦ ¦___¦__///___¦__///___¦______________¦ ¦______________cond______________¦ Эти поля имеют те же форматы и тот же смысл, что и поля fix dat, frame datum, target datum и target displacement записи FIXUPP. Разрешены только основные методы привязки (с использованием смещения). Метод F4 не разрешен. 7.5.16 Запись комментариев ____________________________///________ ¦rec¦ record ¦ comment ¦ comment ¦chk¦ ¦typ¦ length ¦ type ¦ ¦sum¦ ¦88H¦ ¦ ¦ ¦ ¦ ¦___¦_________¦_________¦___///___¦___¦ Эта запись позволяет включать в объектный текст необходимые комментарии. -- 502 -- а) comment type Это поле (тип комментария) имеет следующую структуру: ________________________________________________________ ¦ n ¦ n ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ 0 ¦ comment class ¦ ¦ p ¦ l ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦___¦___¦___¦___¦___¦___¦___¦___¦______________________¦ ¦_________младший байт__________¦_____старший байт_____¦ Если NP=1, то комментарии не могут быть удалены из объектного файла. Если NL=1, то комментарии не должны появляться в листинге (распечатке) объектного файла. Байт comment class может принимать следующие значения: Сlass Значение _______________________________________________________ 0 Комментарий транслятора (устаревший). Если поле comment содержит одну из строк "MS PASCAL" или "FORTRAN 77", то запись COMENT активизирует ключ dsallocation сборщика Microsoft. 156(9СН) Версия ДОС. Поле comment содержит 2-байтное целое, отражающее номер версии ДОС. 157(9DH) Модель памяти. Поле comment содержит единственный байт: S - small M - medium L - large H - huge Эта запись используется только сборщиком -- 503 -- Microsoft XENIX. 158(9EH) Выстраивание сегментов. Действие этой записи аналогично действию ключа dosseg сборщика Microsof. 159(9FH) Спецификатор библиотеки. 129(81Н) Спецификатор библиотеки (устаревший). Поле comment содержит имя включаемой библиотеки. Обратите внимание на то, что в данном случае имени не предшествует его длина. Она определяется исходя из значения поля record length (длина записи). По ключу nodefaultlibrarysearch сборщик игнорирует записи с данным классом. Записи с классом 159 игнорируются сборщиком Microsoft XENIX. 161(А1Н) Расширения Microsoft. Сообщает, что объектный модуль имеет расширенный формат, т.е. включает записи COMDEF и LOCSYM. б) comment Это поле содержит комментарий или информацию, определяемую классом комментария. -- 504 -- 7.6 Представление типа для переменных 'communal' __________________________________________________________ Примечание Объектные модули, не содержащие записи COMENT класса 161, могут представлять определения переменных 'communal' только старым способом, описанным ниже. Сборщики фирмы Микрософт версий до 3.05 признают только этот метод. В настоящее время для определения переменных 'communal' используется запись COMDEF. __________________________________________________________ Переменная 'communal' определяется в обектном файле записью EXTDEF и записью TYPDEF, к которой запись EXTDEF обращается. Запись TYPDEF имеет следующий формат: _____________________///_________ ¦rec¦ record ¦ 0 ¦ eight ¦chk¦ ¦typ¦ length ¦ ¦ leaf ¦sum¦ ¦8ЕH¦ ¦ ¦descriptor¦ ¦ ¦___¦_________¦___¦___///____¦___¦ -- 505 -- a) eight leaf descriptor Это поле имеет следующий формат: _________///______ ¦ e ¦ leaf ¦ ¦ n ¦ descriptor ¦ ¦___¦____///_____¦ - Байт EN может принимать следующие значения: EN=0 - следующие восемь бланков описания (leaf descriptor) имеют тип EASY. EN=1 - следующие восемь бланков описания имеют тип NICE. Этот байт всегда равен нулю в записях TYPDEF для переменных 'communal'. - Поле бланка описания может иметь один из двух форматов. Для переменных 'communal', находящихся в текущем сегменте (NEAR) оно имеет формат: ______________///_________///_____ ¦near¦var ¦ длина в ¦ var ¦ ¦62H ¦typ ¦ битах ¦ subtyp ¦ ¦____¦____¦___///____¦____///____¦ ¦_необязат._¦ -- 506 -- Поле vartyp (тип переменной) может принимать следующие значения: 7BH - скалярная 79H - структурная 77H - массив Поле var subtyp (подтип) игнорируется сборщиком. Формат бланка описания для переменных 'communal', находящихся не в текущем сегменте (FAR), имеет вид: ______________///_________///_____ ¦near¦var ¦количество¦ element ¦ ¦61H ¦typ ¦элементов ¦type index ¦ ¦____¦____¦___///____¦____///____¦ Поле vartyp должно быть 77Н (массив). Поле element type index содержит индекс TYPDEF соответствующего формата. Форматы полей 'длина в битах' и 'количество элементов' аналогичны формату поля communal length записи COMDEF. Все записи EXTDEF, ссылающиеся на запись TYPDEF, рассматриваются как определения переменных 'communal'. Все остальные записи рассматриваются как определения внешних имен, для которых должны существовать соответствующие определения записями PUBDEF. Описание записи определения имен 'communal' приводится в Разделе 7.5.8. ------------ ModulesNames TranlatorsNames SourcesNames ? ? empty ? Segments... [Groups...] [Puplics...] ? Code... EntryPoint ModulesNames: 80 Len (0007) Lstring ModulNm ChkSum ModulesNames. TranslatorsNames: 88 Len(0020) 00 00 Lstring TranslatorNm ChkSum TranslatorsNames. SourcesNames: 88 Len (000d) 40 e9 23 9c 4d 1c Lstring SourceNm ChkSum SourcesNames. ?: 88 Len (0003) 40 e9 ChkSum (4c) ?. ?: 96 Len (0002) 0 ChkSum ?. ?: 88 Len (0003) 40 a1 ChkSum (94) ?. Segments: SegGrFullNm: 96 Define seg names Len Lstring SegGrNm Lstring SegDescr ;if present ChkSum SegGrFullNm. SegParams: 98 Define seg params Len SegFlags 20 - byte 40 - word 60 - para 08 - public SegLen SegGrNo (from 02) 01 01 ChkSum SegParams. Segments. Groups: SegGrFullNm GrParams: 9a Len SegGrNo (from 02) SegList...: SegNo (from 01) ff ChkSum GrParams. Groups. Publics: 90 Len GroupNo (from 01, 0 if no) SegNo (from 01, 0 - equalent) if SegNo=0 00 00 Lstring PublicNm DispInSeg 00 ChkSum Publics. ?: 88 Len (0004) 40 a2 01 ChkSum (91) ?. Code: a0 Len (0005) Seg (from 01) DispInSeg (0000) Codes ChkSum Code. EntryPoint: 8a Len (0007) c1 00 Doubled SegNo (from 01) (02 02) DispInSeg ChkSum EntryPoint.
следующий фpагмент (3)|пpедыдущий фpагмент (1)
TopSpeed Binary File Formats ============================ This file describes the format of TopSpeed binary files. BNF and Pascal/Modula-2-like languages are used in the descriptions. THE INFORMATION IS NOT GUARANTEED TO BE COMPLETE, UP TO DATE OR ACCURATE, it is intended to give you a flying start if you want to write utility programs which operate on the binary files. The debug format may change slightly in future versions. .OBJ/.LIB ( object file ) ------------------------- This is the standard Intel object file format, with extra coment records used by the 'make'. Only the subset generated by TopSpeed compilers is described here. (The linker does however support other record types such as iterated data etc.) BNF <lib file> ::= <lib-coment> { <object file> } <object file> ::= <header> { <item> } <trailer> <header> ::= 80H Length <string> Crc (* string is source name *) <trailer> ::= | 8AH Length 0 Crc (* not program entry point *) | 8AH Length 0C1H 0 <segment-index> <segment-index> 0 0 Crc (* program entry point *) <item> ::= | <lnames> | <segdef> | <grpdef> | <extdef> | [ <io-priv-coment> ] <pubdef> | <ledata> [ <fixupp> ] | <source-date-coment> (* used by make *) | <option-coment> (* used by make *) | <include-object-coment> (* used by make *) | <stack-heap-size-coment> | <shared-data-coment> (* applies to last segdef *) <lnames> ::= 96H Length { <string> } Crc <segdef> ::= 98H Length Attr SegLen <name-index> <name-index> <name-index> Crc <grpdef> ::= 9AH Length <name-index> { 0FFH <segment-index> } Crc <extdef> ::= 8CH Length { <string> Type } Crc <pubdef> ::= 90H Length <group-index> <segment-index> [ Frame ] { <string> Offset Type } Crc <ledata> ::= 0A0H Length <segment-index> Offset { Byte } Crc <fixupp> ::= 9CH Length { Locat FixDat Index [ Index ] [ Offset ] } Crc <lib-coment> ::= COMENT Length 0C700H Hash Crc (* used by make *) <source-date_coment> ::= COMENT Length 0C500H Date { Char } Crc <option-coment> ::= COMENT Length 0C900H { Char } Crc <project-command-coment> ::= COMENT Length 0CF00H { Char } Crc <include-object-coment> ::= COMENT Length 0CB00H { Char } Crc <stack-heap-size-coment> ::= COMENT Length 0CD00H HeapSize StackSize Crc <shared-data-coment> ::= COMENT Length 0CA00H Crc <io-priv-coment> ::= COMENT Length 0C800H Crc <string> ::= Len { Char } <name-index> ::= Index <group-index> ::= Index <segment-index> ::= Index Terminal symbols: Length is a 2-byte value present in every record which is the length in bytes of the record - 3. Len is a 1-byte string length. Char is a 1-byte character, which should be a printing character. Crc is a 1-byte checksum. It is either zero or -(sum of bytes in record). Index is a 2 byte value represented as 1 or 2 bytes. If getb() returns the next byte from the file, a routine to fetch an Index is as follows: tmp := CARDINAL( getb() ); IF tmp < 128 THEN RETURN tmp; ELSE RETURN ( tmp - 128 ) * 256 + CARDINAL( getb() ); END; <lnames>, <extdef>, <pubdef>, <segdef> and <grpdef> records implicitly define indices which are then used to refer to the objects defined. The indices start from 1. Offset is a 2-byte offset in a segment. Frame is present only when the segment index for the public is zero (an absolute public), and is normally 0. Type is a 1-byte hash value in the range 0..127 used by the JPI linker to perform type-consistency checks (note that this is a deviation from standard Intel format where this is interpreted as a type-index, but existing linkers mostly ignore this field. If there is a problem the field could be set to zero by a utility program or by disabling smart linking. Byte is a 1-byte data value. Attr is the 1-byte segment attribute. SegLen is the 2-byte length of the segment. Locat (2 bytes) defines the offset in the preceding ledata record which is to be fixed up (bits 0..9), the kind of location (bits 10..12) and whether the fixup is non-relative (bit 14). Bit 15 is always 1, Bit 13 is always 0. The location kinds are 1=>offset, 2=>segment, 3=>pointer FixDat (1 byte) defines what kind of index is used for the target of the fixup (bits 0..1), whether the offset is missing (bit 2), and what kind of index is used for the frame of the fixup (bits 4..6). The bits 3 and 7 are zero. The encoding of the index kind is 0=><segment-index>, 1=><group-index>, 2=><external-index>, 5=>no frame index, use target Hash is a 4-byte hash value used by the make system. Date is a 4-byte file date in MSDOS/OS2 format. HeapSize and StackSize are 2-byte values for the heap and stack of the program (specified by the data pragma in the main module). .EXE/.DLL ( executable file format ) ------------------------------------ The .exe/.dll file format is as follows: <exe file> ::= <standard exe file> <debug info> <trailer> <debug info> ::= <header> { <module info> } <end marker> <module info> ::= <module name size> <module name> <lseg count> { <lseg address> } <trailer> ::= longcard size of <standard exe file> <end marker> ::= byte 0 <module name size> ::= byte size of following <module name> <lseg count> ::= word count of following <lseg address> <seg address> ::= word offset followed by word segment <header> ::= 'jpi0' where <standard exe file> is the standard Microsoft .exe/.dll format. .DBD file ( debug information ) ------------------------------- The BNF for a modules debug data is as follows : <module debug data> ::= Mod { <item> } EndMod <item> ::= <proc> | <var> | <type> <proc> ::= Proc { <item> } EndProc <type> ::= Signed | Unsigned | Float | Char | Boolean | Procedure | Indirect | Array <type> <type> | OpenArray <type> Aux | Pointer <type> | SubRange <type> | Set <type> | ShortPtr <type> Aux | <simple> | Rec { <field> } EndRec | (Enum|SparseEnum) { EnumVal } EndEnum . <var> ::= Var <type> <field> ::= Field <type> | BitField <type> The terminal symbols in the grammar correspond to records of the following type: TYPE DbRec = RECORD (* variable size *) recsize : SHORTCARD; (* record size in bytes, including this byte *) CASE tag: DbRecKind OF | Source: sourcename : string; | Module: lang : SHORTCARD; ofs : CARDINAL; seg : CARDINAL; (* -1 => external *) name : string; | EndModule: modulesize : t_offset; | LineNum: line : ARRAY [0..62] OF RECORD (* variable size *) ofs : CARDINAL; num : CARDINAL; END; | Rte: rteofs : CARDINAL; rtenum : CARDINAL; rtecol : CARDINAL; | Var, Aux: varflags : DbVarFlags; ofs : CARDINAL; (* 1 => no address if local or param *) seg : CARDINAL; name : string; | Field: fieldofs : CARDINAL; fieldname : string; | BitField: fieldofs : CARDINAL; bitfieldbitofs : SHORTCARD; bitfieldsize : SHORTCARD; bitfieldname : string; | Proc: procflags : DbProcFlags; (* the complete set is only in EndProc !! *) ofs : CARDINAL; seg : CARDINAL; name : string; | EndProc: procflags : DbProcFlags; procsize : t_offset; | Indirect: handle : Handle; | Rec: typesize : CARDINAL; id : Handle; | EndRec: | Enum: typesize : CARDINAL; id : Handle; | EnumVal: enumval : INTEGER; enumname : string; | EndEnum: | Subrange: typesize : CARDINAL; rangehigh, rangelow:LONGCARD; | Signed, Unsigned, Float, Char, Boolean, Pointer, Procedure, Array, OpenArray, Set, ShortPtr: typesize:CARDINAL; ELSE b:ARRAY [0..252] OF SHORTCARD; END; END; where TYPE Handle = LONGCARD; CONST Nil = MAX(Handle); (* 0FFFFFFFFH *) TYPE string = ARRAY [0..127] OF CHAR; (* variable length *) TYPE DbRecKind = ( Module, EndModule, LineNum, Rte, Var, Proc, EndProc, Indirect, Rec, EndRec, Enum, EnumVal, Field, BitField, EndEnum, Subrange, Void, Signed, Unsigned, Float, Char, Boolean, Pointer, Procedure, Array, OpenArray, Set, ShortPtr, Source, Aux ); TYPE DbVarTypeEnum = ( varparam, valparam,local,nonvolatile); TYPE DbVarFlags = SET OF DbVarTypeEnum; TYPE DbProcTypeEnum = (near,NoFrame,VarArg,OptVarArg); TYPE DbProcFlags = SET OF DbProcTypeEnum; An Indirect record is a pointer to an Enumeration or Record type so that these types can be re-used. Note that the following records expect sub types to follow (i.e. be defined immediately afterwards) Array expects <Index type> + <Element type> to follow OpenArray expects <Element type> + Aux to follow Pointer expects <dereferenced type> to follow Subrange expects <base type> to follow Set expects <element type> to follow ShortPtr expects <dereferenced type> + Aux to follow The segment values correspond to segment indices in the .OBJ file, and are translated into run-time segment values using the VID information at the end of the .EXE/.DLL file. .SES, .CFG, .HLP files ---------------------- not yet done ------------------------------------------------------------------------------

Всего 2 фpагмент(а/ов) |пpедыдущий фpагмент (2)

Если вы хотите дополнить FAQ - пожалуйста пишите.

design/collection/some content by Frog,
DEMO DESIGN FAQ (C) Realm Of Illusion 1994-2000,
При перепечатке материалов этой страницы пожалуйста ссылайтесь на источник: "DEMO.DESIGN FAQ, http://www.enlight.ru/demo/faq".