Подтвердить что ты не робот

Чем двухпроходный ассемблер отличается от однопроходного ассемблера в разрешении будущих символов?

Это 2 вопроса, которые я не понимаю:

  1. Как One-Pass Assembler решает будущую проблему с символами?

  2. Чем двухпроходный ассемблер отличается от однопроходного ассемблера в этом отношении?

    Это решает это в первом проходе или втором проходе? Если он делает это во втором проходе, где он на самом деле отличается от однопроходного ассемблера? Если он делает это во втором проходе, почему он не делает в первом проходе?

4b9b3361

Ответ 1

Прочтите этот PDF. Он объясняет шаг за шагом, как работают одиночные и многопроходные сборщики. Это также объясняет плюсы и минусы обоих из них и различия между ними.

Что такое однопроходный ассемблер?

Это своего рода тип ассемблера Load-and-go, который обычно генерирует объектный код непосредственно в памяти для немедленного выполнения! Он анализирует ваш исходный код только один раз и ваш результат. Врум...

Прохладный, если он делает это волшебство, почему нам нужны многопроходные сборщики вообще?

Переслать ссылки! т.е. когда однопроходный ассемблер работает по исходному коду, он встречает некоторых незнакомых людей в форме символов undefined и undefined ярлыков (адресов перехода). Ваш ассемблер спрашивает этих незнакомых людей о том, кто они? Посторонние говорят: "Мы скажем вам позже!" (Прямая ссылка) Ваш ассемблер рассердился и говорит вам полностью устранить этих незнакомцев. Но эти незнакомцы - ваши друзья, и вы не можете полностью их устранить. Итак, вы вступаете в компромиссную сделку с ассемблером. Вы обещаете определить все свои переменные перед их использованием. Ассемблер не мог скомпрометировать это, потому что он не может даже зарезервировать временное хранилище для символов данных undefined, поскольку он не знает их размер. Данные могут иметь разный размер.

Если что-то вроде

PAVAN EQU SOMETHING

; Your code here
 mov register, PAVAN


; SOMETHING DB(or DW or DD) 80 ; varying size data, not known before

С его стороны ваш ассемблер соглашается идти на компромисс над метками перехода undefined. Поскольку метки перехода не имеют ничего, кроме адресов и адресов, могут быть известны априори, чтобы ассемблер мог зарезервировать определенное пространство для символа undefined.

Если это похоже на

      jump AHEAD


 AHEAD add reg,#imm

Ассемблер переводит jump AHEAD как 0x45 **0x00 0x00**. 0x45 - это код операции jump и 4 байта, зарезервированный для адреса AHEAD

ОК, теперь скажите, как работает один проход ассемблера

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

Теперь, в конце разбора, если в состоянии undefined есть еще более бедные души, ассемблер кричит фол и ошибки:( Если нет ярлыков undefined, тогда вы уходите!

enter image description here

Один секунда, я забыл, зачем нам нужен ассемблер с 2 или несколькими проходами? И как они работают?

Как объяснено, однопроходный ассемблер не может разрешать прямые ссылки символов данных. Для этого требуется, чтобы все символы данных были определены до их использования. Двухпроходный ассемблер решает эту дилемму, посвящая один проход, чтобы исключительно разрешить все (данные/метки) прямые ссылки, а затем сгенерировать объектный код без каких-либо проблем в следующем проходе.

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

Хм.. Интересно. Есть ли еще два ассемблера с пропускной способностью?

Да. Он может обнаруживать переопределения и тому подобное.

PS. Возможно, я не был на 100% прав. Я хотел бы услышать любые предложения в том, чтобы сделать его лучше.

Ответ 2

Ассемблер с одним проходом генерирует код и для любых символов undefined, оставляет слот, который должен быть заполнен, и запоминает его в таблице или другой структуре данных. Затем, когда символ определен, он заполняет свое значение в нужном месте или местах, используя информацию из таблицы.

Причиной использования двухпроцессорного ассемблера традиционно было то, что целевая программа не вписывается в память, оставляя в покое источник. Гигантская исходная программа считывается по строкам из устройства чтения пунша, а таблица меток хранится во внутренней памяти. (Я на самом деле сделал это, в ISIS, первой системе разработки Intel, с 8080.) Второй раз вокруг исходной ленты снова считывается с начала, но значение всех меток известно, и по мере чтения каждой строки целевая программа выбивается на ленту. На голодающей 16-битной Intel 8086 системе это было по-прежнему полезной техникой, чтобы иметь сильно документированный исходный файл, который может быть намного больше, чем 64 Кбайт, с жестким диском или гибким диском, замененным бумажной лентой.

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

Ответ 3

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

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

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

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

Двухпроцессорный ассемблер пытается вычислить значение каждого выражения, когда он встречает его, в два прохода, называемых "первым" и "вторым" проходами. Во время первого прохода, если в выражении есть символы undefined (предполагается, что это прямые ссылки), ассемблер просто заменяет фиктивное значение (часто равное нулю); в любом случае он вычисляет значение для выражения. Если обрабатывается машинная инструкция или постоянная данных, результаты игнорируются, но размер используется для продвижения счетчика местоположения, чтобы включить присвоение значения меток. Если метка встречается, ее значение устанавливается на текущий счетчик местоположения. Если встречается символьное присвоение "A EQU", значение символа устанавливается на результат выражения; если выражение содержало символ undefined, ассемблер испустит ошибку. Если инструкция происхождения найдена "ORG", ее обрабатывают так, как если бы вы писали "$ EQU". В конце первого прохода всем меткам присвоены значения; любые символы, которые не имеют значений, помечены как "undefined" в таблице символов. Второй проход повторяет оценку выражения первого, но не (re) определяет какие-либо символы; поскольку все символы (как ожидается, будут определены), значения выражения правильны и испускаются в выходной поток. Любые символы undefined, найденные в выражении, вызывают жалобу "undefined".

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

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

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

Одна из моих когорт намного позже построила интересный двухпроходный ассемблер. Вместо того, чтобы обрабатывать текст дважды, он маркировал текст (сохраняя его в памяти) на первом проходе, а также собирал значения символов. Пропустите два обработанных токенированного текста. Это был очень быстрый ассемблер для двух проходов. У него было намного больше доступной памяти.

Ответ 4

Future Symbol Probleam означает, что символ используется до его определения.

  • Это возможно, потому что в программе языка программирования программист может определить символ Anywere, если символ используется до его определения. Он называется "прямой ссылкой"

  • Итак, время от преобразования его в машинный (двоичный) язык, ассемблер получает Opcode-Reg-X2-B2, но он не получает запись D2 (смещение) в таблице символов, поэтому это невозможно Преобразовать в язык машины (двоичный), и он называется "Проблема с прямой ссылкой".

  • Чтобы решить этот 2-х ассемблер, определяющий.

** На первом проходе (первое сканирование) он делает запись символов (ярлыков) в таблицу символов. ** А на ассемблере второго прохода (второй раз) преобразует его в машинный язык (двоичный). Это очень просто:)