Формат объектного файла.

Объектный файл имеет теговую структуру.
    Номинально, порядок блоков не имеет значения. Однако программа создаёт
объектный файл, в котором блоки располагаются в следующей последовательности:
1. Блок идентификатор
2. Блок данных
3. Блок глобальных меток
4. Блок локальных меток (если есть)
5. Блок ссылок на метки

Каждый блок имеет заголовок следующего формата:
{
    OBJTags  nHdrTag;       // Тэг заголовка
    OBJTags  nBlockTag;     // Тэг блока
    uint32_t nBlkLen;       // Размер данных блока в байтах (не включая размер заголовка)
    uint32_t nEntryCount;   // Количество элементов в блоке
    uint32_t nCheckSum;     // Контрольная сумма блока (на данный момент не
                            // используется и == 0)
}

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

Тэг блока
    Константное значение, по которому определяется тип блока. И как
интерпретировать данные блока.

Размер данных блока
    Размер данных блока в байтах, следующих следом за заголовком.

Количество элементов в блоке
    Количество элементов данных блока. Например, количество меток в таблице.

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


    За заголовком блока следуют данные. В каждом блоке они интерпретируются
по своему.

Блок идентификатор
    Имеет данные следующей структуры:
{
    uint32_t nVersion;      // Версия объектного файла
    int16_t nStartAddress;  // Адрес компоновки по умолчанию объектного модуля.
    int16_t nMode;          // Режим компоновки
}
    В заголовке этого блока - количество элементов == 1, а размер данных == 8
(на данный момент)

Версия объектного файла
    На данный момент - число 0x1020

Адрес компоновки по умолчанию объектного модуля
    По умолчанию, это число 01000. Или адрес, заданный псевдокомандой .LA, или
ключом -s.
    Этот адрес используется при линковке командой LI. Для первого объектного
файла, если адрес не задан явно ключом -s, берётся адрес компоновки из заголовка.
Для последующих объектных файлов - берётся текущий адрес компоновки, полученный
после компоновки предыдущего объектного файла, это как правило, адрес первого
слова за концом получающегося скомпонованного массива программы.

Режим компоновки
    Определяет стратегию обработки меток.
    Имеет три значения:
    LINKING_MODE::CL - объектный модуль скомпилирован в режиме CL, т.е. ещё не
скомпонован и полностью перемещаем.
    При линковке такого файла все метки корректируются в соответствии с базовым
адресом линковки модуля.
    LINKING_MODE::CO и LINKING_MODE::FINAL - объектный модуль скомпилирован в
режиме CO. Т.е. он скомпонован с некоего определённого адреса и в него уже 
подставлены значения меток.
    При линковке такого файла, корректировать метки не имеет смысла, т.к. они
при этом станут некорректны. Поэтому они добавляются в результирующую таблицу
меток как есть.
    Вообще смысл линковки таких модулей имеет смысл либо, если этот модуль идёт
первым, либо, если в последствии массив данных этого модуля будет перемещён на
заданный адрес, с которого он был скомпонован, программой пользователя.


Блок данных
    Содержит собственно бинарный массив сформированного кода.
    В заголовке этого блока - количество элементов == 1, а размер данных - 
размер полученного кода.


Блок глобальных меток
    Содержит таблицу глобальных меток объектного модуля.
    В заголовке этого блока - количество элементов - количество меток, а размер
данных - размер всего массива таблицы меток в байтах.

Структура одного элемента метки:
{
    uint32_t OBJTags::OBJ_Label;    // Тэг элемента метки
    uint32_t type                   // Тип метки
    uint32_t value                  // Значение метки
    BKToken  name {                 // Имя метки
        uint32_t OBJTags::OBJ_Token;    // Тэг элемента токена
        uint32_t len                    // Длина строки имени метки
        wchar_t[len] label_text;        // Строка имени метки в unicode
    }
}

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

Тип метки
    Есть три типа глобальных меток:
    * LBL_GLOBAL - глобальная метка.
    * LBL_DEFINE - определение (константа)
    * LBL_WEAKDEFINE - определение (константа), значение которого ещё не вычислено.
Они обрабатываются по разному. Метку можно релоцировать, константу - нет.
При линковке модуля, который был скомпилирован в режиме LINKING_MODE::CL
Все значения глобальных меток корректируются 

Значение метки
    Это адрес, где метка была определена. Фактически - это смещение от начала
кода. И чтобы получить фактическое значение, к нему надо прибавить адрес
компоновки по умолчанию.
    Для определений - 0.

Имя метки
    Имя метки, в виде тэговой структуры:

Тэг элемента токена
    Константное значение, по которому определяется, что далее следует верная
структура строкового значения.

Длина строки имени метки
    Размер строки текста в знаках. Значение может быть от 1 до 2^32-1, т.е.
длина имени может достигать 2 Гб, думаю этого более, чем достаточно.

Строка имени метки в unicode
    Собственно имя метки. Строка не содержит заключающего нуля, т.к. перед ней
имеется размер строки.

Блок локальных меток
    По своей структуре совершенно идентичен блоку глобальных меток. Вся разница
лишь в том, что при определении глобальной метки, вся таблица локальных меток
обнуляется. И в объектный файл либо ничего не записывается, либо записывается 
остаточная таблица на момент окончания компиляции.

    Все метки имеют один тип: LBL_LOCAL - локальная метка.

Блок ссылок на метки
    Каждый аргумент в ассемблерных операторах и в правой части определения
рассматривается как полноценное арифметическое выражение. В простейшем случае,
арифметическое выражение состоит из одного числа, или нескольких чисел. И его
можно вычислить сразу, тогда оно вычисляется и результат подставляется в
формируемый опкод. Если выражение содержит имена, то оно преобразуется в цепочку
обратной польской записи и сохраняется в таблицу.

структура одного элемента таблицы.
{
    uint32_t OBJTags::OBJ_Refs;     // Тэг элемента таблицы ссылок
    uint32_t type;                  // Тип элемента: константа или подставляемое значение
    uint32_t address;               // Смещение, где встретилось арифметическое выражение
    BKToken  define;                // Имя определения
    RPNChain chain;                 // Цепочка арифметического выражения.
}

Тип элемента.
    Есть два типа:
    * ARL_DEFINE - выражение в определении
    * ARL_CMDARG - выражение в ассемблерной команде
    Так же, для выражения а команде, могут быть следующие флаги:
    * ARL_LOCAL - в выражении есть ссылки на локальные метки
    * ARL_BYTEL - байтовый результат, т.е. значение надо сохранять в байт по заданному адресу
    А так же флаги, определяющие стратегию обработки результата арифметического выражения:
    * ARL_BRANCH_LABEL   - арифметическое выражение в команде ветвления и sob
    * ARL_OFFSET_LABEL   - результат - смещение до адреса
    * ARL_RELATIVE_LABEL - результат - значение.

Смещение
    Если выражение встретилось в ассемблерной команде, то это - смещение, относительно
начала данных, куда надо подставлять вычисленный результат выражения.
    Для определений - 0.

Имя определения
    Если выражение встретилось в определении, то тут сохраняется имя определения,
а в таблицу глобальных меток заносится это же имя с типом LBL_WEAKDEFINE. Чтобы потом,
когда выражение сможет быть вычислено, было куда сохранить результат выражения.
    Для выражений в команде - "" (пустая строка)

Цепочка арифметического выражения.

формат цепочки арифметического выражения
{
    uint32_t OBJTags::OBJ_RPNChain;
    uint32_t size                   // Количество элементов цепочки
    {
        uint32_t OBJTags::OBJ_Node;
        uint8_t type;               // Тип элемента
        // далее следуют данные в соответствии с типом элемента
    }[size];
}

Тип элемента
    Есть следующие типы:
    * A_TYPE::NUMBER,		// Число
    * A_TYPE::LABEL,		// Метка
    * A_TYPE::LOC_LABEL,	// Локальная метка
    * A_TYPE::DOT_PC,		// Ссылка на счётчик команд
    * A_TYPE::OPERATION,	// Операция

Структуры данных соответствующих типов:
Число
{
    uint32_t OBJTags::OBJ_NodeNMR;
    uint32_t number;        // значение числа
}

Метка
{
    uint32_t OBJTags::OBJ_NodeLBL;
    BKToken token;          // имя метки
}

Локальная метка
{
    uint32_t OBJTags::OBJ_NodeLBL;
    uint32_t number;        // значение метки. или -1, если метка пока не определена
    BKToken token;          // имя метки
}

Ссылка на счётчик команд
{
    uint32_t OBJTags::OBJ_NodeDotPC;
    uint32_t number;        // значение PC, где встретилось арифметическое выражение
}

Операция
{
    uint32_t OBJTags::OBJ_NodeDotPC;
    uint8_t op;             // тип арифметической операции
}

