Системное программирование

Автор: Пользователь скрыл имя, 10 Марта 2013 в 15:44, курс лекций

Описание работы

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

Работа содержит 1 файл

Системное программирование 15 лекций.doc

— 946.00 Кб (Скачать)

Используя команду dir, можно проверить наличие ваших  файлов на диске:

DIR C:имя программы.*

В результате на экране появится следующие имена  файлов: имя программы.BAK (если для  корректировки имя программы.ASM использовался редактор EDLIN), имя программы.ASM, имя программы.OBJ, имя программы.LST, имя программы.EXE и имя программы.CRF.

Последовательность  этих файлов может быть иной в зависимости  от того, что уже находится на диске.

Очевидно, что разработка ряда программ приведет к занятию дискового пространства. Для проверки оставшегося свободного места  
на диске полезно использовать команду DOS CHKDSK. Для удаления OBJ-, CRF-, BAK- и LST-файлов с диска следует использовать команду ERASE (или DEL):

ERASE C:имя программы.OBJ, ...

Следует оставить (сохранить) ASM-файл для последующих  изменений и EXE-файл для выполнения.

4

Файл перекрестных ссылок

В процессе трансляции Ассемблер создает таблицу идентификаторов (CRF), которая может быть представлена в виде листинга перекрестных ссылок на метки, идентификаторы и переменные в программе. Для получения данного фала, необходимо на четвертый запрос Ассемблера, oтветить C:, полагая, что файл должен быть создан на диске C:

cross-reference [NUL.CRF]:C: [Enter]

Далее необходимо преобразовать полученный CRF-файл в  отсортиpованную таблицу перекрестных ссылок. Для этого на ассемблерном диске имеется соответствующая  программа.

После успешного  ассемблирования введите команду CREF. На экране появится два запроса:

Cref filename [.CRF]: List filename [cross-ref.REF]:

На первый запрос введите имя CRF-файла, то есть, C:имя  программы. На второй запрос можно ввести только номер дисковода и получить имя по умолчанию.

Такой выбор  приведет к записи CRF в файл перекрестных ссылок по имени имя программы.REF на дисководе C.

Для распечатки файла перекрестных ссылок используйте  команду DOS PRINT.

Важно:

u Ассемблер преобразует исходную программу в OBJ-файл, а компоновщик — OBJ-файл в загрузочный EXE-файл.

u Внимательно проверяйте запросы и ответы на них для программ (M)ASM, LINK и CREF прежде чем нажать клавишу Enter. Будьте особенно внимательны при указании дисковода.

u Программа CREF создает распечатку перекрестных ссылок.

u Удаляйте ненужные файлы с вашего диска. Регулярно пользуйтесь программой CHKDSK для проверки свободного места на диске. Кроме того периодически создавайте резервные копии вашей программы, храните резервную дискету и копируйте ее заново для последующего программирования. 

 

 

  

 

 

  

 

 

  

 

 

 

Лекция 10. 
Алгоритмы работы Ассемблеров

4

Двухпроходный Ассемблер — первый проход

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

Алгоритм работы 1-го прохода двухпроходного Ассемблера показан на рисунке.  

 

 

  

 

F Блок1: Начало 1-го прохода ассемблирования.

F Блок2: Начальные установки:

u установка в 0 счетчика адреса PC;

u создание пустой таблицы символов;

u создание пустой таблицы литералов;

u открытие файла исходного модуля;

u установка в FASLE признака окончания.

F Блок3: Признак окончания TRUE?

F Блок4: Считывание следующей строки исходного модуля. Добавка к счетчику адреса устанавливается равной 0.

F Блок5: При считывании был обнаружен конец файла?

F Блок6: Если конец файла обнаружен до того, как обработана директива END, — ошибка (преждевременный конец файла), при этом также устанавливается признак окончания обработки.

F Блок7: Лексический разбор оператора программы. При этом:

u выделяется метка/имя, если она есть;

u выделяется мнемоника операции;

u выделяется поле операндов;

u удаляются комментарии в операторе;

u распознается строка, содержащая только комментарий.

F Блок8: Строка содержит только комментарий? В этом случае обработка оператора не производится.

F Блок9: Мнемоника операции ищется в таблице директив.

F Блок10: Завершился ли поиск в таблице директив успешно?

F Блок11: Если мнемоника была найдена в таблице директив, происходит ветвление, в зависимости от того, какая директива была опознана.

F Блок12: Обработка директив типа DD (определения данных) включает в себя:

u выделение элементов списка операндов (одной директивой DD может определяться несколько объектов данных);

u определение типа и, следовательно, размера объекта данных, заданного операндом;

u обработка для каждого операнда возможного коэффициента повторения.

F Блок13: Добавка к счетчику адреса устанавливается равной суммарному размеру объектов данных, определяемых директивой.

F Блок14: Обработка директив типа BSS подобна обработке директив типа DD.

F Блок15: Добавка к счетчику адреса устанавливается равной суммарному объему памяти, резервируемому директивой.

F Блок16: Обработка директивы END состоит в установке в TRUE признака окончания обработки.

F Блок17: Обработка директивы включает в себя вычисление значения имени и занесение его в таблицу символов.

F Блок18: Обработка прочих директив ведется по индивидуальным для каждой директивы алгоритмам. Существенно, что никакие директивы, кроме DD и BSS, не изменяют нулевого значения добавки к счетчику адреса.

F Блок19: Если мнемоника операции не найдена в таблице директив, она ищется в таблице команд.

F Блок20: Завершился ли поиск в таблице команд успешно?

F Блок21: Если мнемоника не была найдена в таблице команд, — ошибка (неправильная мнемоника).

F Блок22: Если мнемоника найдена в таблице команд — определение длины команды, она же будет добавкой к счетчику адреса.

F Блок23: Есть ли в операторе литерал?

F Блок24: Занесение литерала в таблицу литералов (если его еще нет в таблице).

F Блок25: Была ли в операторе метка?

F Блок26: Поиск имени в таблице символов.

F Блок27: Имя в таблице символов найдено?

F Блок28: Если имя найдено в таблице символов — ошибка (повторяющееся имя).Если имя не найдено в таблице символов — занесение имени в таблицу символов.

F Блок29: Формирование и печать строки листинга.

F Блок30: Модификация счетчика адреса вычисленной добавкой к счетчику

F Блок31: Печать строки листинга и переход к чтению следующего оператора.

F Блок32: При окончании обработки — закрытие файла исходного модуля.

F Блок33: Были ли ошибки на 1-м проходе ассемблирования?

F Блок34: Формирование литерального пула.

F Блок35: Выполнение 2-го прохода ассемблирования.

F Блок36: Конец работы Ассемблера.

Определение длины команды

Эта задача может  решаться существенно разным образом  для разных языков. В языках некоторых  Ассемблеров мнемоника команды  однозначно определяет ее формат и длину (S/390, все RISC-процессоры). В этом случае длина команды просто выбирается из таблицы команд. В других языках длина и формат зависит от того, с какими операндами употреблена команда (Intel). В этом случае длина вычисляется по некоторому специфическому алгоритму, в который входит выделение отдельных операндов и определение их типов. В последнем случае должна производиться также необходимая проверка правильности кодирования операндов (количество операндов, допустимость типов).

Обнаружение литералов

Требует, как  минимум, выделения операндов команды.

Листинг

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

Ошибки

На первом проходе  выявляются не все ошибки, а только те, которые связаны с выполнением  задачи 1-го прохода. Сообщение об ошибке включает в себя: код ошибки, диагностический текст, номер и текст оператора программы, в котором обнаружена ошибка.

Некоторые структуры данных 1-го прохода

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

Таблица директив содержит одну строку для каждой директивы  Обработка каждой директивы происходит по индивидуальному алгоритму, поэтому  параметры обработки нельзя представить  в виде данных единого для всех директив формата. Для каждой директивы в таблице хранится только идентификация (имя или адрес, или номер) процедуры Ассемблера, выполняющей эту обработку. Некоторые директивы обрабатываются только на 1-м проходе, некоторые — только на 2-м, для некоторых обработка распределяется между двумя проходами.

Таблица символов является основным результатом 1-го прохода  Ассемблера. Каждое имя, определенное в программе, должно быть записано в  таблице символов. Для каждого  имени в таблице хранится его  значение, размер объекта, связанного с этим именем и признак перемещаемости/неперемещаемости. Значением имени является число, в большинстве случаев интерпретируемое как адрес, поэтому разрядность значения равна разрядности адреса.

Перемещаемость  рассматривается в разделе, посвященном  Загрузчикам, здесь укажем только, что  значение перемещаемого имени должно изменяться при загрузке программы  в память. Имена, относящиеся к  командам или к памяти, выделяемой директивами DD, BSS, как правило, являются перемещаемыми (относительными), имена, значения которых определяются директивой EQU, являются неперемещаемыми (абсолютными).  

 

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

 

 

 

4

Структура таблиц Ассемблера

Структура таблиц Ассемблера выбирается таким образом, чтобы обеспечить максимальную скорость поиска в них.

Таблицы команд и директив являются постоянной базой  данных. Они заполняются один раз  — при разработке Ассемблера, а  затем остаются неизменными.

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

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

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

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

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

Эти же соображения  относятся и к другим таблицам, формируемым Ассемблером в процессе работы. При больших размерах таблиц и размещении их на внешней памяти могут применяться и более  сложные (но и более эффективные) методы их организации, например — B+-деревья.

4

Двухпроходный Ассемблер — второй проход

Обычно 2-й проход Ассемблера читает исходный модуль с  самого начала и отчасти повторяет  действия 1-го прохода (лексический  разбор, распознавание команд и директив, подсчет адресов). Это, однако, скорее дань традиции — с тех времен, когда в вычислительных системах ощущалась нехватка (или даже полное отсутствие) внешней памяти. В те далекие времена колода перфокарт или рулон перфоленты, содержащие текст модуля, вставлялись в устройство ввода повторно. В системах с эволюционным развитием сохраняются перфокарты и перфоленты (виртуальные), так что схема работы Ассемблера — та же. В новых системах Ассемблер может создавать промежуточный файл — результат 1-го прохода, который является входом для 2-го прохода. Каждому оператору исходного модуля соответствует одна запись промежуточного файла, и формат этой записи приблизительно такой:  

Информация о работе Системное программирование