В первых вычислительных машинах программист писал на машинном языке программу, которая содержала все команды, необходимые для решения конкретной задачи. Даже сложные и в определенном смысле опасные процедуры управления вводом-выводом в каждой программе на машинном языке приходилось кодировать вручную.
В настоящее время программы пользователя зачастую содержат лишь незначительную часть команд и данных, необходимых для решения поставленной задачи. В составе системного программного обеспечения поставляются большие библиотеки подпрограмм, так что программист, которому необходимо выполнять определенные стандартные операции, может воспользоваться для этого готовыми подпрограммами. В частности, операции ввода-вывода обычно выполняются подпрограммами, находящимися вне программы пользователя. Поэтому программу на машинном языке, полученную в результате трансляции, приходится, как правило, комбинировать с другими программами на машинном языке, чтобы сформировать необходимый выполняемый модуль. Эту процедуру объединения программ выполняют связывающие загрузчики и редакторы связей до начала выполнения программы.
Свободное программное обеспечение для любой деятельности
Связывающий загрузчик во время загрузки объединяет необходимые программы и загружает их непосредственно в основную память. Редактор связей также осуществляет подобное объединение программ, однако он создает загрузочный модуль, который записывается во внешнюю память для будущего использования. Редактор связей играет особенно важную роль для производственных систем; когда программу необходимо выполнять, ее загрузочный модуль, сформированный при помощи редактора связей, может быть загружен немедленно — без накладных затрат времени (часто весьма больших) на повторное объединение отдельных частей программы.
Принято считать, что автором концепции микропрограммирования является профессор Морис Уилкс. В своей статье в 1951 г. (Wi 51) он предложил принципы, которые легли в основу современных методов микропрограммирования. Однако начало реального внедрения микропрограммирования связано с появлением System/360 в середине 60-х годов. В течение 60-х годов изготовители компьютеров применяли микропрограммирование для реализации наборов команд машинного языка (Ни 70).
В конце 60-х — начале 70-х годов появилось динамическое микропрограммирование, предусматривающее возможность легкой загрузки новых микропрограммных модулей в управляющую память, служащую для выполнения микропрограмм. Благодаря этому стало возможным динамично и часто менять наборы команд вычислительной машины. И сейчас уже никого не удивит, если в мультипрограммных системах новых поколений будут предусматриваться возможности предоставления различных наборов команд различным пользователям, с тем чтобы в процессе переключения процессора с программы на программу можно было также осуществлять переход с одного набора машинных команд на другой, необходимый следующему пользователю.
Микропрограммирование вводит дополнительный уровень средств программирования, нижележащий по отношению к машинному языку компьютера, и тем самым оно позволяет определять конкретные команды машинного языка. Подобные возможности являются неотъемлемой частью архитектуры современных компьютеров и имеют громадное значение с точки зрения обеспечения высоких скоростных характеристик и защиты операционных систем.
Сделал свой редактор кода. Лучше Visual Studio?
Микропрограммы размещаются в специальной управляющей памяти очень высокого быстродействия. Они состоят из индивидуальных микрокоманд, которые гораздо более элементарны по своей природе и более рассредоточены по функциям, чем обычные команды машинного языка. В компьютерах, где набор команд машинного языка реализуется при помощи микропрограммирования, каждой команде машинного языка соответствует целая и, .быть может, большая микропрограмма,/Тем самым сразу же становится очевидным, что микропрограммирование окажется эффективным только в том случае, если управляющая память будет обладать гораздо большим быстродействием; чем основная.
2.4.1 Горизонтальный и вертикальный микрокод
Команды микрокода можно разделить на горизонтальные и вертикальные. Выполнение вертикальных микрокоманд очень похоже на выполнение обычных команд машинного языка. Типичная вертикальная микрокоманда задает пересылку одного или нескольких элементов данных между регистрами.
Горизонтальный микрокод действует совсем по-другому. Каждая его команда содержит гораздо большее число бит, поскольку может задавать параллельную операцию пересылки данных для многих или даже всех регистров данных устройства управления. Горизонтальные микрокоманды являются более мощными, чем вертикальные, однако может оказаться, что соответствующие микропрограммы гораздо сложнее кодировать и отлаживать.
2.4.2 Выбор функций для микропрограммной реализации
Для разработчика очень важно правильно решить, какие именно функции вычислительной машины реализовать при помощи микрокода. Микрокод предоставляет реальную возможность повысить быстродействие вычислительной машины. Реализуя часто используемые последовательности команд микропрограммно, а не обычным программным способом, разработчики добиваются существенного повышения показателей быстродействия. Читателям, которые будут знакомиться с функциями операционных систем по мере проработки настоящей книги, рекомендуется тщательно анализировать, для реализации каких из этих функций может быть эффективно использован микрокод.
Источник: kazedu.com
Редактор связей
Редактор связей [1] выполняет две функции. Во-первых, как можно заключить по его названию, он комбинирует (компонует, редактирует) различные объектные файлы. Вторая его функция — разрешать адреса вызовов и инструкций загрузки, найденных в редактируемых объектных файлах. Чтобы понять принцип работы редактора связей, рассмотрим подробнее процесс раздельной компиляции.
Раздельная компиляция
Раздельная компиляция — это возможность, позволяющая разбить программу на несколько файлов, скомпилировать каждый из этих файлов отдельно, а потом скомпоновать [2] их, чтобы в конечном итоге создать исполняемый файл [3] . Результатом работы компилятора является объектный файл, а результатом работы редактора связей — исполняемый файл. Редактор связей физически связывает файлы, внесенные в список компоновки, в один программный файл и разрешает внешние ссылки. Внешняя ссылка создается каждый раз, когда программа из одного файла ссылается на код из другого файла. Это происходит при вызове функции и при ссылке на глобальную переменную. Например, при компоновке двух приведенных ниже файлов, должна быть разрешена ссылка в файле 2 на идентификатор count , объявленный в файле 1. Редактор связей сообщает программе из файла 2, где найти count .
Файл 1 Файл 2 int count; #include void display(void); extern int count; int main(void) void display(void) < < count = 10; printf(«%d», count); display(); >return 0; >
Аналогично, редактор связей укажет файлу 1, где находится функция display() , чтобы можно было ее вызвать.
При генерации объектного кода функции display() , компилятор подставляет в негo вместо адреса идентификатора count «заполнитель», т.е. ссылку на внешнее имя, потому что он не располагает информацией о том, где находится count . Нечто подобное происходит при компиляции main() . Адрес функции display() не известен, поэтому вместо него используется «заполнитель», т.е. ссылка на внешнюю программу. При компоновке этих двух файлов содержащиеся в них внешние ссылки заменяются адресами соответствующих элементов. Являются ли эти адреса абсолютными или переместимыми, — зависит от среды [4] .
Переместимые коды и абсолютные коды
В результате работы редактора связей для большинства видов вычислительной среды получается переместимый код . Так называют объектный код, который может работать в любой свободной области памяти, способной его уместить. В переместимом объектном файле адрес каждой инструкции вызова или загрузки является не фиксированным, а относительным. Таким образом, адреса в переместимом коде отсчитываются от адреса начала программы. При загрузке программы в память для выполнения, загрузчик преобразует относительные адреса в физические адреса, соответствующие адресам ячеек памяти, в которую загружается программа.
В некоторых вычислительных средах, таких как специализированные устройства управления, в которых для всех программ используется одно и то же адресное пространство, редактор связей подставляет в конечный результат своей работы физические адреса. В этом случае он генерирует абсолютный код [5] .
Редактирование связей с оверлеями
Хотя в наше время эта возможность применяется редко, следует отметить, что компиляторы С некоторых вычислительных сред в дополнение к обычным компоновщикам предоставляют компоновщики оверлеев. Компоновщик оверлеев работает так же как и обычный, но он также может создавать оверлеи [6] . Оверлей — это фрагмент объектного [7] кода, который хранится в файле на диске и загружается для работы только по мере необходимости. Место в памяти, которое отводится для загрузки оверлеев, называется оверлейной областью памяти . Оверлеи позволяют создавать и запускать программы, которые занимали бы большую область памяти, чем имеющаяся в наличии, потому что в каждый момент времени в памяти находится только та часть программы, которая нужна.
Чтобы понять, как работают оверлеи, представим, что имеется программа, состоящая из семи объектных файлов, которые называются F1, F2, …, F7. Допустим, имеющейся свободной памяти недостаточно для загрузки программы, скомпонованной обычным образом из всех объектных файлов. Есть возможность скомпоновать только первые пять файлов, а при большем количестве наступит переполнение памяти.
Выйти из подобной ситуации можно, дав компоновщику команду создать оверлеи из файлов F5, F6 и F7. При каждом вызове функции, которая содержится в одном из этих, файлов, администратор оверлейной загрузки (программа, предоставляемая компоновщиком или редактором связей) находит необходимый файл и помещает его в оверлейную область памяти, создавая условия для работы программы. Коды, которые получились при компиляции файлов F1 — F4, остаются резидентными. Данная схема проиллюстрирована на рис. 12.1.
+—-+ +—————-+ | F5 |—. | F1 | +—-+ | | . | F5. F7 | | . | загружаются +—-+ | | . | по мере | F6 |-. | | F4 | необходимости +—-+ | | +—————-+ | `—>| Оверлейная | +—-+ `—->| | | F7 |——>| область памяти | +—-+ +—————-+
Рис.12.1 Программа с оверлеями загруженными в память.
Как читатель, возможно, уже догадался, принципиальным преимуществом оверлеев является возможность создавать с их помощью очень большие программы. Основной же их недостаток и причина редкого использования состоит в том, что процесс загрузки занимает определенное время и в значительной мере влияет на быстродействие программы. Поэтому при использовании оверлеев следует взаимосвязанные между собой функции группировать вместе, чтобы свести к минимуму число загрузок оверлеев.
Например, если приложение обрабатывает список рассылки, то имеет смысл поместить все подпрограммы сортировки в один оверлей, подпрограммы печати — в другой и т.д.
Как уже было сказано, в современных вычислительных средах оверлеи применяются редко.
Связывание с динамически подсоединяемыми библиотеками (DLL)
Операционная система Windows предоставляет другой вид связывания, так называемое динамическое связывание . Динамическое связывание — это процесс, при котором объектный код функции остается в отдельном файле на диске до тех пор, пока не запустится использующая его программа. При запуске такой программы динамически загружаются затребованные, связанные с ней функции. Динамически связанный функции помещаются в специальный тип библиотек, которые называются динамически подсоединяемыми библиотеками (DLL — Dynamic-Link Library).
Основным преимуществом таких библиотек является возможность значительно сократить размер исполняемых программ, потому что отпадает необходимость в том, чтобы каждая программа содержала в себе копию используемых библиотечных функций. Другим положительным моментом является то, что при обновлении функций DLL, использующие их программы автоматически используют и все улучшения новых версий.
Стандартная библиотека С не содержится в динамически подсоединяемой библиотеке, но многие другие типы функций там есть. Например, при написании приложений для Windows, в DLL хранится полный набор функций программного интерфейса приложений (API — Application Program Interface). Нужно отметить, что для программы, написанной на языке С, обычно не имеет значения, хранятся ли библиотечные функции в DLL или в обычном файле библиотек.
[1] Иногда называется также компоновщиком . Впрочем, компоновщиками обычно называют программы, обладающие несколько меньшими возможностями, чем развитые редакторы связей.
[2] Этот процесс называется редактированием связей .
[3] Называется также загрузочным модулем .
[4] Редакторы связей обычно располагают широким набором возможностей, и при необходимости пользователь может указать необходимые параметры.
[5] Называется также программой в абсолютных адресах .
[6] Создание оверлейных программ — стандартная функция для редакторов связей. Кроме того редакторы связей обычно могут создавать даже загрузочные модули, загружаемые «вразброс», т.е. в несмежные участки памяти. Все это имеет огромное значение для систем, в которых отсутствует виртуальная память. Но в системах с виртуальной памятью эти возможности часто выглядят как ненужные излишества.
[7] Согласно оригиналу. Все же точнее часть загрузочного модуля .
Источник: t-r-o-n.ru
27. Компоновщики – редакторы связей.
Компон-к – это прога, преодоставляемая проектировщиком системы, которая связывает независ. лог. обл-ти кажд. подр-мы и кажд. модуля в одну единств. лог. обл-ть. Компоновка включает по крайней мере следующие этапы:
1.Сбор всех модулей из библиотек пользователей и системных библиотек.
2.Установка всех внешних ссылок м/д модулями.
3.Собщение о неопределенных ссылках.
4.Конструирование структуры оверлея.
5.Определение и построение загрузочного модуля
Главная задача программы компоновщика создать комплекс объект. модулей, полученных от компиляторов с различных языков в какой-нибудь из разновидностей исполняемых модулей и заменить неопределенные ссылки на внешние имена с соответствующими адресами или информацией доступной для загрузчиков. Классификация типов связей разграничивает 2 класса: управляющие и информационные. Для реализации которых используется единый технический подход, опирающийся на глобально-доступные имена элементов программных модулей. Управляющие связи в современных системах программирования определяются способами передачи управления и действиями, выполняемыми для решения частей общей задачи и представленные в одной из шести форм:
1.Вызов подпрограммы того же загрузочного модуля в процессе его выполнения, реализуемого простыми средствами модульного программирования.
2.Макровызов, как подготовка действий по решению части задачи на этапе компиляции или создания программы, которая реализуется с помощью встроенных макросредств системы программирования.
3.Вызов подпрограммы, копия которой имеется в основной программе и который обычно реализуется в форме обращения к общей системной программе ОС или управляющей надстройке пользователя.
4.Вызов подпрограмм с диска можно подзагрузкой их кодов и управляющих данных, при котором иногда различают оверлейную структуру программ с фиксированным взаимным расположение модулей и фрагментов и динамическую подзагрузку в совершенно произвольном порядке.
5.Динамический вызов параллельных процессов решения подзадач включая выполнение ехе-модули и dll-модули, которые подключаются на этапе выполнения.
6.Передача сообщения и сигналов автономным параллельным процессам и задачам широко применяемым для управления вычислениями в объектно-ориентированных оболочках.
Кроме управляющих необходимо установить и информационные связи между модулями для передачи в подчиненные модули операт. данных или аргументов подпрограмм и возврата результатов в вызывающие программы, а также для передачи универсальных управляющих данных в другие программные модули. К основным способам установления информационных связей относят 3 следующих способа:
1.Передача аргументов при вызове подпрограмм и функций унифицированная стандартами обращения к подпрограммам, общая для компоновщиков и специализированными для языков программирования.
2.Возрат результатов при вызове функций, при котором соблюдают стандарт. связанный с ЯП.
3.Использование глобальных областей памяти для обмена данными между подпрограммами и задачами.
Комбинирование связи чаще всего возникают, когда управляющая или адресная информация рассматриваются как данные в аргументах функций и процедур или адресов подпрограмм, но с другой стороны точки ветвления могут быть рассмотрены как адреса передачи управления для их реализации достаточно использовать типичные средства связывания с незначительными особенностями во входных языках для определения процедурных типов.
Для реализации компоновщика и его эксплуатации необходимо проанализировать форматы его элементов хотя бы на самом общем уровне. При изучении форматов объектных модулей особый интерес представляют такие вопросы:
1. как определяется? Какие внешние подпрограммы и данные нужны объектному модулю и каким образом определяются адреса обращения или точки входа в подпрограммах или данных, которые могут использоваться программами других модулей?
2. как проверить корректность типов данных при обращении к подпрограммам и задачам?
3. как достигается переместимость объект. программы, т.е. возможность размещать ее в любом месте ОП?
4. как и почему компонуются отдельные логические сегменты в единый физический сегмент?
Объединение логических сегментов требует корректировки относительного адреса в уже сформированный коде путем добавления относительного смещения смещения начала логического сегмента для переместимых адресов. В случае использования внешних имен условный код указателя заменяется конкретным адресом соответственного объекта.
Многообразие объектов переместимости, а иногда и использование разных кодов для внутреннего представления типов переместимости делают несовместимыми объектные коды, получаемые от трансляторов разных фирм или даже разных систем программирования одной фирмы. В модульном программировании различают связи по управлению и по данным, реализуемые с помощью адресных указателей или ссылок на данные и коды.
При объедении модулей необходимо определить имена областей памяти и фрагментов программ, используемых в др модулей в списке операндов оператора public, внешние имена из других модулей вместе с их типами описываются в списке операндов оператораextended. Для указателей используются только ключевые словаwordиdword, т.е. указатели в ассемблере нетипизированы.
При обращении к подпрограммам и функциям по прямым адресам используются типыnearиfar. Передача параметров в форме непосредственных значений или адресных указателей осуществляются через стек. Необходимость проверки соответствия типов данных, аргументов, процедур и функций, а также числа аргументов в процедурах, существенно усложняет представления словаря внешних ссылокв объектных файлах. Компоновщики используют программные модули, хранящие информацию об именах исходных модулей программы, типе компилятора породившем этот модуль, а иногда и даже и о модели памяти под которую этот модуль оттранслирован.
Источник: studfile.net