Вперед Назад Содержание

4. Секции и пеpемещения

4.1 Общие положения

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

Линкер ld считывает много объектных файлов (частей программ) и комбинирует их содержание в исполняемую программу. Когда as делает объектный файл предполагается, что частичная программа начинается с адреса 0. Ld ставит в соответствие частичной программе конечный адрес, так чтобы различные частичные программы не накладывались друг на друга. На самом деле все гораздо сложнее, но этого достаточно, чтобы объяснить, как as использует секции.

Ld перемещает блоки данных вашей программы на их адреса во время исплолнения. Эти блоки, как единое целое, перемещаются на те адреса, которые они будут иметь во время выполнения; их длина и поpядок байтов в них не меняются. Такой цельный кyсок называется секцией. Назначение секциям адpесов, которые они будут иметь во вpемя исполнения называется пеpемещением. Это включает задачy пpиведения в соответствие адpесов, встpечающихся в объектных файлах, так чтобы они ссылались на нyжные адpеса во вpемя исполнения. Для H8/300, H8/500, и Hitachi SH, as в случае необходимости расширяет секции, так что бы они оканчивались на границу слова (шестнадцать бит).

Объектный файл, созданный as, имеет по крайней мере три секции, каждая из которых может быть пустой. Они называются "text", "data" и "bss".

Когда as генерирует объектный модуль в формате COFF, он также создает любые другие секции, которые вы определили с помощью директивы .section (смотрите раздел 7.48 [.section]). Если вы не используете директив, которые помещают вывод в секции .data и .text, эти секции все равно существуют, но остаются пустыми.

Когда as генерирует объектные модули в форматах SOM или ELF для HPPA, он также может создавать секции с любыми другими именами при помощи директив .space и .subspace. Смотрите 'HP9000 Series 800 Assembly Language Reference Manual' (HP 92432-90001) для более подробного знакомства с директивами .space и .subspace.

Кроме этого, as использует отличные имена для стандартных секций text, data и bss, когда генерирует SOM-вывод. Код программы помещается в секцию $CODE$, данные в `$DATA$', и BSS в `$BSS$'.

Внутри объектного файла секция кода начинается с адреса 0, далее идет секция data, а затем секция bss.

Генерируя объектные модули в форматах SOM или ELF на HPPA, as начинает секцию text с адреса 0, секцию данных с адреса 0x4000000, а секция bss следует за секцией данных.

Чтобы передать ld, какие данные меняются при перемещениях секций, и как их нужно менять, as сохраняет в объектном файле всю требуемую для выполнения перемещений информацию. Для произведения необходимых перемещений ld должен знать о каждом вхождении адреса в объектный файл следующие данные:

Фактически, любой используемый as адрес представляется в виде (СЕКЦИЯ) + (СМЕЩЕНИЕ В СЕКЦИИ)

Более того, большинство выражений, вычисляемых as, связаны с секциями. (Для некоторых объектных форматов, таких как SOM на HPPA, некоторые выражения задаются относительно символов.)

В этом руководстве мы используем запись {SECNAME N} что означает "смещение N в секции SECNAME".

Кроме секций text, data и bss вам нужно знать об "абсолютных" секциях. Когда ld смешивает частичные программы, адреса в абсолютной секции не меняются. Например, адрес {absolute 0} "перемещается" ld в адрес 0 во время исполнения. Хотя линкер никогда не оставляет пересекающихся секций данных двух частичных программ, по определению их абсолютные секции должны накладываться. Адрес {absolute 239} в одной части программы всегда совпадает с адресом {absolute 239} в любой другой части программы.

Идея секций также распространяется на "неопределенную" секцию. Любой адрес, секция которого не известна во время ассемблирования, переносится по определению в секцию {undefined U} где U определяется позже. Поскольку числа всегда определены, единственный способ определить неопределенный адрес состоит в использовании неопределенногог символа. Ссылка на имя общего блока будет таким символом: ее значение не известно во время ассемблирования, поэтому она относится к неопределенной секции.

По аналогии слово "секция" используется для описания групп секций слинкованных программ. Ld помещает все секции кода программ в одну непрерывную цепочку адресов в слинкованной программе. Обычно "секция кода программы" означает совокупность адресов всех секций кода частичных программ. Это относится и к секциям data и bss.

Некотоpыми секции используются ld, остальные предназначены для использования исключительно в as и имеют значение только во время ассемблирования.

4.2 Секции ld

Ld работает только с четырьмя типами секций, описанными ниже.

*именованные секции*

*секции text*

*секции data*

Эти секции содержат вашу программу. As и ld рассматривают их как отдельные, но равноправные секции. Все что вы можете сказать про одну из них, справедливо и для другой. Тем не менее, когда программа выполняется, обычно секция text не должна изменятся. Секция text часто совместно используется процессами: она содержит инструкции, константы и другую подобную информацию. Секция data по ходу исполнения программы обычно изменяется: например, переменные в программах на языке C будет храниться в секции data.

*секция bss*

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

*секция absolute*

Адрес 0 это секции всегда "перемещается" в адрес 0 времени исполнения. Это нужно, когда вы хотите сослаться на адрес, который ld не должен менять во время перемещения. В этом смысле мы говорим об абсолютном адресе как о "неперещаемом": он не должен меняться вовремя перемещения.

*секция undefined*

Эта "секция" считается содержащей все ссылки на адреса, которые не были определены в предыдущих секциях.

Далее следует идеализированный пример трех перемещаемых секций. Пример использует традиционные имена секций .text и .data. Адреса памяти отложены на горизонтальных осях.

+-----+----+--+ частичная программа # 1: |ttttt|dddd|00| +-----+----+--+ text data bss seg. seg. seg. +---+---+---+ частичная программа # 2: |TTT|DDD|000| +---+---+---+ +--+---+-----+--+----+---+-----+~~ слинкованная программа: | |TTT|ttttt| |dddd|DDD|00000| +--+---+-----+--+----+---+-----+~~ адреса: 0...

4.3 Внутренние секции as

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

ASSEMBLER-INTERNAL-LOGIC-ERROR!

Была найдена внутренняя логическая ошибка ассемблера. Это значит, что найдена ошибка в ассемблере.

expr section

Ассемблер хранит сложные выражения как комбинацию символов. Когда ему нужно представить выражение в виде символа, он помещает его в секцию expr.

4.4 Подсекции

Ассемблиpованные байты обычно pазмещаются в двyх секциях: text и data. Возможно вам понадобиться разделить группы данных в названных секциях, если вы хотите разместить их рядом в объектном файле, даже если они не лежат рядом в ассемблерном исходнике. As позволяет вам использовать для этих целей "подсекции". Внутри каждой секции могут находиться пронумерованные от 0 до 8192 подсекции. Объекты, ассемблированные в одной подсекции попадают в объектный файл вместе с другими объектами той же подсекции. Например, компилятор может пожелать хранить константы в секции text, но может не хотеть перемешивать их с ассемблируемой программой. В этом случае компилятор может поставить .text 0 перед каждой секцией выводимого кода и .text 1 перед каждой группой выводимых констант.

Подсекций может и не быть. Если вы не используете подсекций, то все попадает в подсекцию с номером ноль.

Каждая подсекция дополняется нyлями, так чтобы число байт в ней было кpатно четыpем. (Число подсекций может быть увеличено до какого-то числа, в зависимости от различных особенностей as.)

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

Для того, чтобы указать в какую подсекцию попадут последующие ассемблированные команды, используйте числовые аргументы операторах .text ВЫРАЖЕНИЕ или .data ВЫРАЖЕНИЕ. Когда генерируется объектный модуль в формате COFF, Вы можете также использовать дополнительный аргумент номера подсекции с произвольным именем секции: .section ИМЯ, ВЫРАЖЕНИЕ. ВЫРАЖЕНИЕ должно быть абсолютным выражением. (Смотрите главу 6 "Выражения".) Если вы просто указываете .text, то подразумевается .text 0. Точно также, .data означает .data 0. Ассемблирование начинается в .text 0. Например:

.text 0 # Подсекция по yмолчанию все pавно text 0. .ascii "Это находится в пеpвой подсекции text." .text 1 .ascii "Hо это находиться во втоpой подсекции text.*" .data 0 .ascii "Это находится в секции data," .ascii "в первой подсекции data." .text 0 .ascii "Это находится в пеpвой cекции text," .ascii "сразу за звездочкой (*)."
Каждая секция имеет "счетчик текущего места", увеличивающийся на один при ассемблировании каждого нового байта в эту секцию. Поскольку подсекции являются просто удобством, не выходящим за границы as, не бывает счетчиков текущего места подсекций. Hе сyществyет способов напpямyю изменять счетчик места - но диpектива .align меняет его, и всякое определение метки берет его текущее значение. Счетчик места секции, в которую в данный момент ассемблируются операторы, называется активным счетчиком места.

4.5 Секция bss

Секция bss используется как место для хранения глобальных переменных. Вы можете выделить адресное пространство для секции bss, но Вы не можете указать, какие данные будут загружены в нее до исполнения программы. Когда пpогpамма начинает pаботy, секция bss заполнена нулями.

Адреса в секции bss выделяются при помощи специальных директив, Вы не можете ассемблироать что-либо прямо в секцию bss. Следовательно, не бываает и подсекций bss. Смотрите разделы 7.9[.comm] и 7.32 [.lcom].


Вперед Назад Содержание