Вход в систему

Лекции по курсу "Проектирование ассемблеров, компоновщиков, макропроцессоров"

12. Пример работы однопросмотрового ассемблера по схеме 1А / ОП

 

Основная трудность, возникающая при попытке ассемблировать программу за один просмотр, связана со ссылками вперед. Часто в качестве операндов команд используются имена, которые еще не были определены в исходной программе. Поэтому ассемблер не знает, какие адреса занести в транслируемую программу. Довольно легко исключить ссылки вперед на данные; достаточно потребовать, чтобы все области данных определялись в исходной программе раньше, чем появляются команды, которые на них ссылаются. Это не слишком жесткое ограничение. Программист просто размещает все области данных в начало программы, а не в конец. К несчастью, невозможно столь же легко исключить ссылки вперед на метки команд. Логика программы часто требует передачи управления вперед. (Например, выход из цикла после проверки некоторого условия.) Требование исключить все такие передачи управления оказалось бы гораздо более жестким и неудобным. Поэтому ассемблер должен предпринимать специальные меры для обработки ссылок вперед. Однако для того, чтобы облегчить задачу, многие однопросмотровые ассемблеры действительно запрещают (или, по крайней мере, не рекомендуют) ссылки вперед на данные.

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

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

Рассмотрим пример, который поможет прояснить этот процесс. В таблицах, приведенных ниже, показано, как будут выглядеть объектный код и элементы таблицы имен после просмотра строки «jle les_or_eq» (LOC = 16) программы. В данной строке присутствует ссылка вперед. Поскольку операнд (les_or_eq) еще не был определен, то команда ассемблировалась без назначения адреса для этого операнда. Затем имя «les_or_eq» было занесено в таблицу имен как неопределенное имя (обозначено *), а адрес операндного поля команды был занесен в список, связанный с «les_or_eq».

LOC - Location - положение (счетчик размещения).


LOC Исходный текст Адрес ОП Машинный код до коррекции Окончательный машинный код
0 dseg segment seg:00    
  arr dw 3, -5, -7, 92 00 03 00 FB FF ...  
A mes db 'положительных чисел' 0A .......  
23 dseg ends      
0 cseg segment seg1:00    
  assume cs:cseg, ds:dseg      
0 N dw 5 seg1:00 05 00  
02 start: mov ax,dseg 02 B8 seg  
05 mov ds,ax 05 8E D8  
07 mov cx,N 07 2E: 8B 0E 00 00  
0C mov bx,0 0C BB 00 00  
0F mov dx,bx 0F 8B D3  
11 again: cmp arr[bx],0 11 83 BF 00 00 00  
16 jle les_or_eq 16 7E 00 7E 01
18 inc dx 18 42  
19 les_or_eq: add bx,2 19 83 03 02  
  ...      
  int 21h      
  cseg ends      
  end start      



Таблица имен:

Когда было определено имя «les_or_eq» (LOC = 19), ассемблер занес его значение в таблицу имен. Затем он занес это значение в операндное поле команды, как это предписано списком ссылок вперед. С этого момента все ссылки на «les_or_eq» не будут являться ссылками вперед и не будут заноситься в список.

По достижению конца программы ассемблирование завершается. Если не было ошибок, то ассемблер ищет в таблице имен значение имени, указанное в предложении end (в данном случае «les_or_eq»), и передает управление на данный адрес для исполнения ассемблированной программы.

В таблицу псевдоопераций заносятся имена директив и адрес обрабатывающей их программы. А в таблицу Group&Segments заносятся имена используемых сегментов, их характеристики и адреса.


Таблица псевдоопераций (POT):

Имя Адрес обрабатывающей программы
segment  
dw  
db  
ends  
assume  



Таблица сегментов:

Group&Segments Bit Size Align Combine class Address
dseg 16 23 Para   seg
cseg 16   Para   seg1


Group&Segments - имя сегмента;
Bit - разрядность;
Size - размер в байтах;
Align - выравнивание;
Combine class - класс комбинирования;
Address - адрес;
Para - параграф.

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

Введение
Причины использования языка ассемблер
Причины неиспользования языка ассемблер
Синтаксис ассемблера
Системное программное обеспечение и структура ЭВМ
Программная модель процессора Intel 8086
Организация работы памяти
Операнды
Адресация операндов
Формат машинных команд
Команды переходов
Типы ассемблеров. Функции ассемблера
Ассемблер по схеме 1А / ОП
Ассемблер по схеме 1А / МД
Двухпросмотровый ассемблер
Многопросмотровый ассемблер
Загрузчик
Структура объектных файлов. Основные понятия
Идентификация модуля и атрибуты
Концепция привязки
Объектный файл. Последовательность записей
Объектный файл. Формат записей
Формат записей THEADR и LHEADR
Формат записи LNAMES
Формат записи SEGDEF
Формат записи GRPDEF
Формат записи PUBDEF
Формат записи COMDEF
Формат записи LOCSYM
Формат записи EXTDEF
Формат записи LINNUM
Формат записи LEDATA
Формат записи LIDATA
Формат записи FIXUPP
Формат записи MODEND
Формат записи комментариев


исполнялось 0,111241 c, запросов к базе 6