Э. Таненбаум - Архитектура компьютера (1127755), страница 141
Текст из файла (страница 141)
Предположим, что вам нужно написать моделирующую программу, реализующую виртуальную память со страничной организацией для машины, содержащей 64 страницы по 1 Кбайт. Программа должна поддерживать одну таблицу из 64 элементов, по одному элементу на страницу. Каждый элемент таблицы содержит номер физической страницы, который соответствует данной виртуальной странице. Моделирующая программа должна считывать файл, содержащий виртуальные адреса в десятичной системе счисления, по одному адресу на строку. Если соответствующая страница находится в памяти, просто фиксируйте факт наличия страницы. Если ее нет в памяти, вызовите процедуру замещения страниц, чтобы выбрать страницу, которую можно удалить (то есть переписать элемент таблицы) и зафиксируйте факт отсутствия страницы.
Никакой передачи страниц реализовывать не нужно. Создайте файл, состоящий из непоследовательных адресов, и проверьте производительность двух алгоритмов: ЕЫ.1 и Р1РО. А теперь создайте файл адресов, в котором х?4 адресов находятся на 4 байта выше, чем предыдущие. Проведите тесты для различных значений х и отчитайтесь о полученных результатах. В программе, показанной в листинге 6.1, имеет место фатальная гонка, так как два программных потока бесконтрольно обращаются к общим переменным. При этом не задействуются ни семафоры, ни какие-либо другие методики взаимного исключения. Запустите эту программу, и вы увидите, что через некоторое время она зависнет.
Если она все же не зависнет, попробуйте сделать код более уязвимым, разместив между операторами корректировки значений в.1п и в.сит и операторами их проверки какие-нибудь вычисления. Какой объем вычислений нужно ввести в зту программу, чтобы она зависала, скажем, раз в час? Напишите программу для 1Л~ПХ или %'пи1ов з ХР, которая на входе получает имя каталога. Программа должна печатать список файлов этого каталога, каждый файл на отдельной строке, а после имени файла — его размер. Имена файлов должны располагаться в том порядке, в котором они располагаются в каталоге. Неиспользованные слоты в каталоги должны выводиться с пометкой (не использован).
Глава 7 Уровень ассемблера В главах 4, 5 и 6 мы обсуждали три уровня, которые можно встретить в архитектуре большинства современных компьютеров. В этой главе речь пойдет о еще одном уровне, который также присутствует в архитектуре практически всех современных машин. Это — уровень ассемблера. Этот уровень существенно отличается от трех предыдущих, поскольку он реализуется путем трансляции, а не интерпретации. Для перевода пользовательских программ с одного языка программирования на другой разработаны специальные программы, которые называются трансляторами. Язык, на котором изначально была написана программа, называется входным, или исходиьпм, языком, а язык, на который она транслируется, — выходным, или целевым.
И входной, и выходной языки определяют содержание уровней иерархии. Если имеется процессор, который может выполнять программы, написанные на входном языке, то нет необходимости транслировать исходную программу на другой язык. Трансляция требуется в том случае, если есть процессор (реализованный аппаратно или программно) для выходного языка, но нет процессора для входного языка. Если трансляция выполнена правильно, то оттранслированная программа будет давать точно такие же результаты, что и исходная (если бы существовал подходящий для нее процессор). Следовательно, имеется возможность организовать новый уровень, который сначала будет транслировать программы, написанные для выходного уровня, а затем сам их выполнять.
Важно понимать разницу между трансляцией и интерпретацией'. При трансляции исходная программа на входном языке сразу не выполняется. Сначала она преобразуется в эквивалентную программу, так называемую объектную, или исполняемую двоичную, программу, которая выполняется только после завершения трансляции. То есть при трансляции нужно пройти два шага; 1. Создание эквивалентной программы на выходном языке. 2. Выполнение полученной программы.
Эти два шага выполняются не одновременно. Второй шаг начинается только после завершения первого. В интерпретации есть только один шаг: выполнение исходной программы. Никакой эквивалентной программы порождать не нужно, хотя иногда для упрощения интерпретации исходная программа преобразуется в промежуточную форму (например, в )ауа-код). Во время выполнения объектной программы задействованы только три уровня: микроархитектуры, архитектуры команд и операционной системы.
Следовательно, ' В отечественной литературе принято и интерпретацию, и компиляцию называть трансляцией (именно компиляцию автор здесь называет трансляцией). Другими словами, трансляторы могут быть либо компиляторами, либо интерпретаторами. — Примеч. научи. ред. 558 Глава 7. Уровень ассемблера во время работы программы в памяти компьютера можно найти три программы: пользовательскую объектную программу, операционную систему и микропрограмму (если она есть). Никаких следов исходной программы не остается. То есть число уровней при выполнении программы может не соответствовать числу уровней до трансляции. Следует отметить, в данной книге мы определяем принадлежность к тому или иному уровню по командам и языковым конструкциям, доступным программистам етого уровня (а не по технологии реализации), в то время как некоторые авторы проводят различие между уровнями, реализованными интерпретаторами и трансляторами.
Знакомство с ассемблером Трансляторы можно разделить на две группы в зависимости от отношения между входным и выходным языками. Если входной язык является символическим представлением числового машинного языка, то транслятор называется ассемблером, а входной язык — языком ассемблера, или просто ассемблером. Если входной язык является языком высокого уровня (например, )ауа или С), а выходной язык является либо числовым машинным языком, либо символическим представлением последнего, то транслятор называется компилятором.
Понятие ассемблера Язык ассемблера — зто язык, в котором каждый оператор соответствует ровно одной машинной команде. Иными словами, в программе, написанной на ассемблере, сушествует взаимно однозначное соответствие между машинными командами и операторами. Если каждая строка в ассемблерной программе содержит ровно один оператор, и каждое машинное слово содержит ровно одну команду, то из ассемблерной программы размером в п строк получится программа на машинном языке из л слов. Мы программируем на языке ассемблера, а не на машинном языке (в шестнадцатеричной системе счисления), поскольку это гораздо проще.
Использовать символические имена и адреса вместо двоичных и восьмеричных намного удобнее. Многие могут запомнить, что обозначениями для сложения (аИ), вычитания (зпЬ~гасг), умножения (шп111р1у) и деления (ЙУЫе) служат команды АРР, 50В, М01. н Р1У, но мало кто сможет запомнить соответствующие числовые величины, которые использует для этих команд машина. Программисту, пишущему на языке ассемблера, нужно знать только символические названия, поскольку ассемблер транслирует их в машинные команды. Это утверждение касается и адресов.
Программист, пишущий на языке ассемблера, может давать символические имена ячейкам памяти, и уже ассемблер должен позаботиться о том, чтобы получить из них правильные числовые значения. В то же время программисту, пишущему на машинном языке, всегда приходится работать с числовыми значениями адресов.
Сейчас уже нет программистов, пишущих программы на машинном языке, хотя несколько десятилетий назад до изобретения ассемблеров программы именно так и писались. Знакомство с ассемблером 559 Язык ассемблера имеет несколько особенностей, отличающих его от языков высокого уровня.
Во-первых, это взаимно однозначное соответствие между операторами языка ассемблера и машинными командами (об этом мы уже говорили). Во-вторых, программист, пишущий на ассемблере, имеет доступ ко всем объектам и командам целевой машины. У программистов, пишущих на языках высокого уровня, такого доступа нет.
Например, если целевая машина содержит бит переполнения, ассемблерная программа может проверить его, а 1ача-программа — нет. Ассемблерная программа может выполнить любую команду из набора команд целевой машины, а программа на языке высокого уровня — нет. Короче говоря, все, что можно сделать на машинном языке, можно сделать и на ассемблере, но в то же время программистам, пишущим программы на языках высокого уровня, недоступны многие команды, регистры и другие объекты. Языки для системного программирования (например, С) часто имеют некое промежуточное положение. Они, хотя и обладают синтаксисом, присущим языкам высокого уровня, с точки зрения возможностей доступа ближе к ассемблеру.