Реклама:

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

Рассмотрим ситуацию, где первый оператор - переход к адресу L. Ассемблер не может ассемблировать оператор, пока не знает адрес L. Но адрес L может находиться где-нибудь в конце программы, и тогда ассемблер не сможет найти этот адрес, не прочитав всю программу. Эта проблема называется проблемой ссылки вперед (forward reference problem) и заключается она в том, что символ L используется еще до своего определения (то есть выполняется обращение к символу, определение которого появится позднее).

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

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

Еще одна цель первого прохода - сохранять все макроопределения и расширять вызовы по мере их появления. Следовательно, в одном проходе происходит и определение символов, и расширение макросов.

Процесс ассемблирования || Оглавление || Первый проход