Скачиваний:
98
Добавлен:
03.06.2014
Размер:
5.64 Mб
Скачать

Вопросы и задания

513

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

10.Операционные системы, в которых допускаются проецируемые в память файлы, всегда требуют, чтобы файлы были отображены в границах страниц. Например, если у нас есть страницы по 4 К, файл может быть отображен, начиная с виртуального адреса 4096, но не с виртуального адреса 5000. Зачем это нужно?

11.При загрузке сегментного регистра в Pentium II вызывается соответствующий дескриптор, который загружается в невидимую часть сегментного регистра. Как вы думаете, почему разработчики Intel решили это сделать?

12.Программа в компьютере Pentium II обращается к локальному сегменту 10 со смещением 8000. Поле BASE сегмента 10 в локальной таблице дескрипторов содержит число 10000. Какой элемент таблицы страниц использует Pentium II? Каков номер страницы? Каково смещение?

13.Рассмотрите возможные алгоритмы для удаления сегментов в сегментированной памяти без страничной организации.

14.Сравните внутреннюю фрагментацию с внешней фрагментацией. Что можно сделать, чтобы улучшить каждую из них?

15.Супермаркеты часто сталкиваются с проблемой, сходной с замещением страниц в системах с виртуальной памятью. В супермаркетах есть фиксированная площадь пространства на полках, куда требуется помещать все больше и больше различных товаров. Если поступил новый важный продукт, например питание для собак очень высокого качества, какой-либо другой продукт нужно убрать, чтобы освободить место для нового продукта. Мы знаем два алгоритма: LRU и FIFO. Какой из них вы бы предпочли?

16.Почему блоки кэш-памяти всегда намного меньше, чем страницы в виртуальной памяти (бывает даже, что в 100 раз меньше)?

17.Почему многие системы файлов требуют, чтобы файл перед прочтением явным образом открывался с помощью системного вызова open?

18.Сравните применение битового отображения и списка неиспользованных пространств для слежения за свободным пространством на диске. Диск состоит из 800 цилиндров, на каждом из которых расположено 5 дорожек по 32 сектора. Сколько понадобится «дырок», чтобы список «дырок» (список свободной памяти) стал больше, чем битовое отображение? Предполагается, что единичный блок — это сектор и что для «дырки» требуется 32-бит- ный элемент таблицы.

19.Чтобы сделать некоторые прогнозы относительно производительности диска, нужно иметь модель распределения памяти. Предположим, что диск рассматривается как линейное адресное пространство из N» 1 секторов. Здесь сначала идет последовательность блоков данных, затем неиспользованное пространство, затем другая последовательность блоков данных и т. д. Эмпирические измерения показывают, что вероятностные распределения для

5 1 4 Глава 6. Уровень операционной системы

длин данных и неиспользованных пространств одинаковы, причем для каждого из них вероятность быть i секторов составляет 2''. Каково при этом ожидаемое число «дырок» на диске?

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

21.Рассмотрим один метод реализации команд для работы с семафорами. Всякийраз, когдацентральный процессор собирается совершить команду upили down над семафором (семафор — это целочисленная переменная в памяти), сначала он устанавливает приоритет центрального процессора таким образом, чтобы блокировать все прерывания. Затем он вызывает из памяти семафор, изменяет его и в соответствии с этим совершает переход. После этого он снова снимает запрет с прерываний. Будет ли этот метод работать, если:

а.Существует один центральный процессор, который переключается между процессами каждые 100 миллисекунд?

б.Два центральных процессора разделяют общую память, в которой расположен семафор?

22.Компания, разрабатывающая операционные системы, получает жалобы от своих клиентов по поводу последней разработки, которая поддерживает операции с семафорами. Клиенты решили, что аморально со стороны процессов приостанавливать свою работу (то есть спать на работе). Чтобы угодить своим клиентам, компания решила добавить третью операцию, peek. Эта операция просто проверяет семафор, но не изменяет его и не блокирует процесс. Таким образом, программы сначала проверяют, можно ли делать над семафором операцию down. Будет ли эта идея работать, если семафор используют три и более процессов? А если два процесса?

23.Составьте таблицу, в которой в виде функции от времени от 0 до 1000 миллисекунд показано, какие из трех процессов PI, P2 и РЗ работают, а какие блокированы. Все три процесса выполняют команды up и down над одним и тем же семафором. Если два процесса блокированы и совершается команда up, то запускается процесс с меньшим номером, то есть Р1 имеет преимущество над Р2 и РЗ и т. д. Изначально все три процесса работают, а значение семафора равно 1.

При t=100 P1 совершает down. При t=200 PI совершает down. При t=300 PI совершает up.

При t=400 PI совершает down. При t=500 PI совершает down. При t=600 PI совершает up.

При t=700 PI совершает down. При t=800 PI совершает up. При t=900 PI совершает up.

Вопросы и задания

515

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

25.Чтобы сделать возможной реализацию семафоров на компьютере с несколькими процессорами, которые разделяют общую память, разработчики включают в машину командудля проверки и блокирования. КомандаTSL X проверяет ячейку X. Если содержание равно 0, семафоры устанавливаются на 1 за один неделимый цикл памяти, а следующая команда пропускается. Если содержание ячейки не равно О, TSL работает как пустая операция. Используя TSL, можно написать процедуры lock и unlock со следующими свойствами: lock{x) проверяет, заперт ли х. Если нет, эта процедура запирает х и возвращает управление; unlock отменяет существующую блокировку. Если х уже заперт, процедура просто ждет, пока он не освободится, и только после этого запирает х и возвращает управление. Если все процессы запирают таблицу семафоров перед ее использованием, то в определенный момент времени только один процесс может производить операции с переменными и указателями, что предотвращает состояние гонок. Напишите процедуры lock и unlockнаассемблере.

26.Каково будет значение in и out для кольцевого буфера длиной в 65 слов после каждой из следующих операций? Изначально значения in и out равны 0. а. 22 слова помещаются в буфер; б. 9 слов удаляются из буфера;

в. 40 слов помещаются в буфер; г. 17 слов удаляются из буфера; д. 12 слов помещаются в буфер; е. 45 слов удаляются из буфера; ж. 8 слов помещаются в буфер;

з. 11 слов удаляются из буфера.

27.Предположим, что одна из версий UNIX использует 2 К блоков на диске и хранит 512 адресов диска на каждый блок косвенной адресации (обычной косвенной адресации, двойной и тройной). Каков будет максимальный размер файла? Предполагается, что размер указателей файла составляет 64 бита.

28.Предположим, что системный вызов UNIX unlink("/usr/ast/bin/game3")

был выполнен в контексте рис. 6.27. Опишите подробно, какие изменения произойдут в системе директорий.

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

5 1 6 Глава 6. Уровень операционной системы

пожертвовать им для общего блага. Вы выбрали системный вызов pipe, который создает каналы для передачи потоков байтов от одного процесса к другому. Возможно ли после этого как-то изменить ввод-вывод? Что вы можете сказать о конвейерах? Рассмотрите проблемы и возможные решения.

30.Комиссия по защите дескрипторов файлов выдвинула протест против системы UNIX, потому что когда эта система возвращает дескриптор файла, она всегда возвращает самый маленький номер, который в данный момент не используется. Следовательно, едва ли когда-нибудь будут использоватьсядескрипторы файлов с большими номерами. Комиссия настаивает на том, чтобы система возвращала дескриптор с самым маленьким номером из тех, которые еще не использовались программой, а не из тех, которые не используются в данный момент. Комиссия утверждает, что эту идею легко реализовать, это не повлияет на существующие программы и, кроме того, это будет гораздо справедливее по отношению к дескрипторам. А что вы думаете по этому поводу?

31.В системе NT можно составить список управления доступом таким образом, чтобы один пользователь не имел доступа ни к одному из файлов, а все остальные имели полный доступ к ним. Как это можно реализовать?

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

33.Работу алгоритмов замещения страниц обычно проверяют путем моделирования. Предположим, что вам нужно написать моделирующую программу для виртуальной памяти со страничной организацией для машины, содержащей 64 страницы по 1 Кбайт. Программа должна поддерживать одну таблицу из 64 элементов, один элемент на страницу. Каждый элемент таблицы содержит номер физической страницы, который соответствует данной виртуальной странице. Моделирующая программа должна считывать файл, содержащий виртуальные адреса в десятичной системе счисления, по одному адресу на строку. Если соответствующая страница находится в памяти, просто записывайте наличие страницы. Если ее нет в памяти, вызовите процедуру замещения страниц, чтобы выбрать страницу, которую можно выкинуть (то есть элемент таблицы, который нужно переписать), и записывайте отсутствие страницы. Никакой передачи страниц не происходит. Создайте файл, состоящий из непоследовательных адресов, и проверьте производительность работы двух алгоритмов: LRU и FIFO. А теперь создайте файл адресов, в котором х процентов адресов находятся на 4 байта выше, чем предыдущие. Проведите тесты для различных значений х и сообщите о полученных результатах.

34.Напишите программу для UNIX или NT, которая на входе получает имя директории. Программа должна печатать список файлов этой директории, каждый файл на отдельной строке, а после имени файла должен печататься размер файла. Имена файлов должны располагаться в том порядке, в котором они появляются в директории. Неиспользованные слоты в директории должны выводиться с пометой (неиспользованный).

Глава 7

Уровень языка ассемблера

В четвертой, пятой и шестой главах мы обсуждали три уровня, которые имеются

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

спомощью интерпретации.

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

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

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

1.Создание эквивалентной программы на выходном языке.

2.Выполнение полученной программы.

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

В отечественной литературе принято и интерпретацию, и компиляцию (именно компиляцию автор здесь называет трансляцией) называть трансляцией. Другими словами, трансляторы могут быть либо компиляторами, либо интерпретаторами. — Примеч. научн. ред.

5 1 8 Глава 7. Уровень языка ассемблера

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

Введение в язык ассемблера

Трансляторы можно разделить на две группы в зависимости от отношения между входным и выходным языком. Если входной язык является символической репрезентацией числового машинного языка, то транслятор называется ассемблером, а входной язык называется языком ассемблера. Если входной язык является языком высокого уровня (например, Java или С), а выходной язык является либо числовым машинным языком, либо символической репрезентацией последнего, то транслятор называется компилятором.

Что такое язык ассемблера?

Язык ассемблера — это язык, в котором каждое высказывание соответствует ровно одной машинной команде. Иными словами, существует взаимно однозначное соответствие между машинными командами и операторами в программе на языке ассемблера. Если каждая строка в программе на языке ассемблера содержит ровно один оператор и каждое машинное слово содержит ровно одну команду, то программа на языке ассемблера в п строк произведет программу на машинном языке из п слов.

Мы используем язык ассемблера, а не программируем на машинном языке (в шестнадцатеричной системе счисления), поскольку наязыке ассемблера программировать гораздо проще. Использовать символьные имена и адреса вместо двоичных и восьмеричных намного удобнее. Многие могут запомнить, что обозначениями для сложения (add), вычитания (subtract), умножения (multiply) и деления (divide) служат команды ADD, SUB, MUL и DIV, но мало кто может запомнить соответствующие числа, которые использует машина. Программисту на языке ассемблера нужно знать только символические названия, поскольку ассемблер транслирует их в машинные команды.

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

Введение в язык ассемблера

519

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

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

Зачем нужен язык ассемблера?

Язык ассемблера довольно труден. Написание программы на языке ассемблера занимает гораздо больше времени, чем написание той же программы на языке высокого уровня. Кроме того, очень много времени занимает отладка.

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

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

Первая причина (достижение высокой производительности) является более важной, поэтому мы рассмотрим ее подробнее. В большинстве программ лишь небольшой процент всего кода отвечает за большой процент времени выполнения программы. Обычно 1% программы отвечает за 50% времени выполнения, а 10% программы отвечает за 90% времени выполнения.

Предположим, что для написания программы на языке высокого уровня требуется 10 человеко-лет и что полученной программе требуется 100 секунд, чтобы

5 2 0 Глава 7. Уровень языка ассемблера

выполнить некоторуютипичную контрольнуюзадачу. (Контрольнаязадача — это программа проверки, которая используется для сравнения компьютеров, компиляторов и т. п.). Написание всей программы на языке ассемблера может занять 50 человеко-лет. Полученная в результате программа будет выполнять контрольную задачу примерно за 33 секунды, поскольку хороший программист может оказаться в три раза умнее компилятора (хотя об этом можно спорить бесконечно). Ситуация проиллюстрирована в табл. 7.1.

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

Предположим, что 10% программы отвечает за 90% времени ее выполнения. Это значит, что из всех 100 секунд работы 90 секунд проводится в этих 10%, а 10 секунд — в оставшихся 90% программы. Эти 10% программы можно усовершенствовать, переписав их на язык ассемблера. Этот процесс называется настройкой (tuning). Он проиллюстрирован в табл. 7.1. На переделку основных процедур потребуется еще 5 лет, но время выполнения программы сократится с 90 секунд до 30 секунд.

Таблица 7 . 1 . Сравнение программирования на языке ассемблера и на языке высокого уровня (с настройкой и без настройки)

 

Количество человеко-лет,

Время выполнения

 

затрачиваемых

программы в секундах

 

на написание программы

 

Язык ассемблера

50

33

Язык высокого уровня

10

100

Смешанный подход до настройки

 

 

Критические 10%

1

90

Остальные90%

9

10

Всего

10

100

Смешанный подход после настройки

 

 

Критические 10%

6

30

Остальные 90%

9

10

Всего

15

40

Сравним этот смешанный подход, в котором используется и язык ассемблера, и язык высокого уровня, с подходом, в котором применяется только язык ассемблера (табл. 7.1). При втором подходе программа работает примерно на 20% быстрее (33 секунды против 40 секунд), но более чем за тройную цену (50 челове- ко-лет против 15). Более того, у смешанного подхода есть еще одно преимущество: гораздо проще переделать в код ассемблера уже отлаженную процедуру, написанную на языке высокого уровня, чем писать процедуру на языке ассемблера с нуля.

Введение в язык ассемблера

521

Отметим, что если бы написание программы занимало только 1 год, соотношение между смешанным подходом и подходом, при котором используется только язык ассемблера, составляло бы 4:1 в пользу смешанного подхода.

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

Расскажем о двух экспериментах, проведенных во время разработки системы MULTICS. Грехем [49] описал процедуру PL/I, за три месяца переделанную в новую версию, которая была в 26 раз меньше и работала в 50 раз быстрее, чем исходная. Он описал еще одну процедуру PL/L, которая получилась в 20 раз меньше исходной и работала в 40 раз быстрее, чем исходная, после двух месяцев работы. Корбато [27] описал процедуру PL/I, размер кода которой был сокращен с 50 000 слов до 1000 слов менее чем за месяц, а контроллер уменьшен с 65 000 до 30 000 слов с увеличением производительности в 8 раз за 4 месяца. Здесь важно понимать, что у программистов языков высокого уровня глобальный подход к тому, что они делают, поэтому они гораздо быстрее могут разработать лучший алгоритм.

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

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

В-третьих, компилятор должен либо давать на выходе программу, которая используется ассемблером, либо самостоятельно выполнять процесс ассемблирования. Таким образом, понимание языка ассемблера существенно для понимания того, как работает компьютер. И вообще, кто-то ведь должен писать компилятор и его ассемблер.

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

Формат оператора в языке ассемблера

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

5 2 2 Глава 7. Уровень языка ассемблера

ще. В таблицах 7.2-7.4 показаны фрагменты программ на языке ассемблера для Pentium II, Motorola 680x0 и (Ultra)SPARC. Все эти программы выполняют вычисление N=I+J. Во всех трех примерах операторы над пропуском в таблице выполняют вычисление. Операторы под пропуском — это указания ассемблеру зарезервировать память для переменных I, J и N. Последние не являются символьными репрезентациями машинных команд.

Таблица 7.2. Вычисление выражения N=l+J в Pentium II

Метка

Код операции Операнды Комментарии

FORMULA:

MOV

EAX.I

; регистр ЕАХ=1

 

ADD

EAX.J

; регистр EAX=I+J

 

MOV

N.EAX

; N=l+J

1

DW

3

; резервируем 4 байта и устанавливаем значение 3

J

DW

4

; резервируем 4 байта и устанавливаем значение 4

N

DW

О

; резервируем 4 байта и устанавливаем значение О

Таблица 7.3. Вычисление выражения N=l+J в Motorola 680x0

Метка

Код операции Операнды Комментарии

FORMULA:

MOVE.L

I,DO

; регистр D0=l

 

ADD.L

J,D0

; регистр D0=l+J

 

MOVE.L

D0,N

; N=l+J

I

DC.L

 

; резервируем 4 байта и устанавливаем значение 3

J

DC.L

 

; резервируем 4 байта и устанавливаем значение 4

N

DC.L

 

; резервируем 4 байта и устанавливаем значение 0

Таблица 7.4. Вычисление выражения N=l+J в SPARC

Метка

Код

Операнды

Комментарии

 

операции

 

 

FORMULA:

SETHI

%HI(I),%R1

! R1 = старшие биты адреса I

 

LD

[%R1+%LO(I)],%R1

! R1=l

 

SETHI

%HI(J),%R2

! R2 = старшие биты адреса J

 

LD

[%R2+%LO(J)],%R2

!R2=J

 

NOP

 

! ждем прибытия J из памяти

 

ADD

%R1,%R2,%R2

!R2=R1+R2

 

SETHI

%HI(N),%R1

! R1 = старшие биты адреса N

 

ST

%R2, [%R1+%LO(N)]

 

1:

.WORD3

3

! резервируем 4 байта и устанавливаем знач. 3

J:

.WORD 4

4

! резервируем 4 байта и устанавливаем знач. 4

N:

.WORD 0

0

! резервируем 4 байта и устанавливаем знач. 0