Cтраница 2
Для определения значений внутренних имен ассемблер в процессе своей работы использует счетчик размещения: к началу обработки каждого автокодного предложения, определяющего очередной объект программы, текущее значение этого счетчика полагается равным адресу, начиная с которого следует разместить в памяти данный объект. Если это предложение снабжено меткой, то в качестве значения этой метки принимается текущее значение счетчика размещения. [16]
Так как все перемещаемые адреса отсчитываются от начала программы, в счетчик размещения ( или программный счетчик) ( LC) первоначально устанавливается нуль. Затем операторы исходного текста читаются последовательно с устройства ввода. Каждый оператор исследуется в отдельности для того, чтобы приписать некоторую ячейку каждой машинной команде или данным, определяемым псевдооперацией, и таким образом определить значения символов, появляющихся в полях меток исходной программы. Это выполняется следующим образом. Сначала поле операции текущего оператора сопоставляется с таблицей псевдоопераций. В этой таблице перечислены мнемонические коды псевдоопераций, с каждой из которых связывается указатель подпрограммы ассемблера, обрабатывающей эту операцию. Если совпадение обнаружено, выполняется вызов соответствующей подпрограммы. Так как проход 1 связан только с псевдооперациями, которые определяют символы или влияют на счетчик размещения, такие псевдооперации, как USING, DROP или START, сразу приводят к передаче управления в точку, в которой анализируются поля метки ( 1 на рис. 5.2) и обработка продолжается. [17]
При составлении автокодной программы иногда бывает удобно сослаться на текущее значение счетчика размещения. Это имя может фигурировать только в теле ачтокодных предложений ( но не в поле метки), а значением этого имени является текущее значение счетчика размещения в момент трансляции данного автокодного предложения, так что если это предложение является определяющим, то значением имени является адрес программного объекта, определяемого данным предложением. [18]
При составлении автокодной программы удобно иметь возможность ссылаться на текущее значение счетчика размещения. Для этого резервируется символ ( звездочка): этот символ может использоваться в адресных полях команд в любых позициях, где могут использоваться имена. [19]
При этом заметим, что во время использования ассемблером какого-либо из счетчиков размещения значения других счетчиков, организованных по командам ОРГСР ( а также основного счетчика), не меняются. [20]
Разумеется, при употреблении команд ORG программист должен следить за корректностью использования счетчика размещения. [21]
Если в команде ORG адресное выражение не задано, то но такой кома н-де в счетчик размещения заносится максимальное достигнутое ранее его значение. [22]
Самоопределенная величина, значение которой должно быть кратно восьми, принимается транслятором в качестве начального значения счетчика размещения. Если эта компонента в команде отсутствует, то в качестве такого начального значения принимается нуль. [23]
Для достижения подобного рода целей можно воспользоваться командой транслятору CNOP, которая служит для выравнивания значения счетчика размещения в последовательности команд на целочисленную границу полуслова, слова или двойного слова. Заметим, что для достижения стоящей перед нами цели нельзя воспользоваться командами транслятору DC или DS с нулевой кратностью, поскольку по этим командам байты, пропускаемые при выравнивании на целочисленную границу, либо заполняются нулями ( а нулевое полуслово не является пустой машинной командой), либо оставляются неопределенными. [24]
Как уже отмечалось ранее, для размещения в памяти объектов программы, определяемых автокодными предложениями, ассемблер использует счетчик размещения: очередной объект машинной программы, вырабатываемый при трансляции, размещается с ячейки, адрес которой равен текущему значению счетчика размещения, после чего значение счетчика увеличивается на число ячеек, отведенных для размещения этого объекта. Таким образом, объекты программы, определяемые последовательными предложениями авто-кодной программы, обычно размещаются в последовательных ячейках памяти. [25]
Содержимое этих ячеек не определяется ( иначе вместо данной команды ассемблеру были бы записаны предложения, определяющие соответствующие константы), так что трансляция данного предложения сводится просто к продвижению счетчика размещения на / единиц. Значением метки является адрес первой ячейки этой группы. [26]
Как уже отмечалось ранее, для размещения в памяти объектов программы, определяемых автокодными предложениями, ассемблер использует счетчик размещения: очередной объект машинной программы, вырабатываемый при трансляции, размещается с ячейки, адрес которой равен текущему значению счетчика размещения, после чего значение счетчика увеличивается на число ячеек, отведенных для размещения этого объекта. Таким образом, объекты программы, определяемые последовательными предложениями авто-кодной программы, обычно размещаются в последовательных ячейках памяти. [27]
Счетчики размещения сдвигаются к границе четного байта, если они уже на нее не установлены, загружаемый элемент данных, содержащий 8 цифр, помещается в очередные че-тьгре байта, младшие два байта получают смещение относительно начала модуля, и к счетчикам размещения прибавляется длина загруженного объекта. [28]
Счетчик размещения настраивается на границу ближайшего следующего полного слова, и резервируются 4 слова - 16 байт памяти, первый из которых связывается с символом DATATAB. На этой операции счетчик размещения увеличится на 16, 17, 18 или 19 соответственно в зависимости от того, сколько байтов было потеряно при настройке первого элемента на границу первого слова. [29]
Для выполнения всей этой работы транслятор использует счетчик размещения, который продвигается по мере отведения места в памяти под выработанные машинные эквиваленты транслируемых автокодных предложений, так что текущее значение этого счетчика равно адресу байта, начиная с которого размещается очередной вырабатываемый машинный эквивалент. В качестве начального значения счетчика размещения транслятор принимает предполагаемый начальный адрес программы, который может быть задан программистом, а при отсутствии такой информации транслятор принимает в качестве предполагаемого начального адреса нулевой адрес. [30]