Студопедия.Орг Главная | Случайная страница | Контакты | Мы поможем в написании вашей работы!  
 

УНІВЕРСИТЕТ 7 страница



Рассмотрим программу, которую нужно произвести для следующего выражения: for (i=0; i<n: 1++) {операторы}

Если у компилятора нет никакой информации о числе п, он должен применять подход, приведенный в листинге 5.4, чтобы корректно обработать случай п<0. Однако если компилятор может определить, что п>0 (например, узнав, как определено п), он может использовать более удобный код, изложенный в листинге 5.3. Когда-то в стандарте языка FORTRAN требовалось, чтобы все циклы выполнялись один раз. Это позволяло всегда порождать более эффективный код (листинг 5.3). В 1977 году этот дефект был исправлен, поскольку даже приверженцы языка FORTRAN начали осознавать, что плохо иметь оператор цикла с такой странной семантикой, пусть он и позволяет экономить одну команду перехода на каждый цикл.

Команды ввода-вывода

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

1. Программируемый ввод-вывод с активным ожиданием.

2. Ввод-вывод с управлением по прерываниям.

3. Ввод-вывод с прямым доступом к памяти.

Мы рассмотрим каждую из этих схем по очереди.

Самым простым методом ввода-вывода является программируемый ввод-

вывод, который часто используется в дешевых микропроцессорах, например во встроенных системах или в таких системах, которые должны быстро реагировать на внешние изменения (это системы, работающие в режиме реального времени). Эти процессоры обычно имеют одну входную и одну выходную команды. Каждая из этих команд выбирает одно из устройств ввода-вывода. Между фиксированным регистром в процессоре и выбранным устройством ввода-вывода передается один символ. Процессор должен выполнять определенную последовательность команд при каждом считывании и записи символа. В качестве примера данного метода рассмотрим терминал с четырьмя 1-байтными регистрами, как показано на рис. 5.19. Два регистра используются для ввода: регистр состояния устройства и регистр данных. Два регистра используются для вывода: тоже регистр состояния устройства и регистр данных. Каждый из них имеет уникальный адрес. Если используется ввод-вывод с распределением памяти, все 4 регистра являются частью адресного пространства, и будут считываться и записываться с помощью обычных команд. В противном случае для чтения и записи регистров используются специальные команды ввода-вывода, например IN и OUT. В обоих случаях ввод-вывод осуществляется путем передачи данных и информации о состоянии устройства между центральным процессором и этими регистрами.

Регистр состояния клавиатуры содержит 2 бита, которые используются, и 6 битов, которые не используются. Аппаратное обеспечение устанавливает самый левый бит на 1 всякий раз, когда появляется символ. Если программное обеспечение ранее установило на 1 бит 6, то производится прерывание. В противном случае прерывания не происходит. При программируемом вводе-выводе для получения входных данных центральный процессор обычно находится в цикле, периодически считывая регистр состояния клавиатуры, пока бит 7 не примет значение 1. Когда это случается, программное обеспечение считывает буферный регистр клавиатуры, чтобы получить символ. Считывание регистра данных вызывает установку бита CHARACTER AVAILABLE (наличия символа) на 0.

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

программное обеспечение сначала считывает регистр состояния дисплея, чтобы узнать, установлен ли бит READY (бит готовности) на 1. Если он не установлен, программное обеспечение проходит цикл снова и снова до тех пор, пока данный бит не примет значение 1. Это значит, что устройство готово принять символ. Как только терминал приходит в состояние готовности, программное обеспечение записывает символ в буферный регистр дисплея, который переносит символ на экран и дает сигнал устройству установить бит готовности в регистре состояния дисплея на 0. Когда символ уже отображен, а терминал готов к обработке следующего

символа, бит READY снова устанавливается на 1 контроллером.

В качестве примера программируемого ввода-вывода рассмотрим процедуру,

написанную на Java (листинг 5.5). Эта процедура вызывается с двумя параметрами: массивом символов, который нужно вывести, и количеством символов, которые присутствуют в массиве (до 1 К). Тело процедуры представляет собой цикл, который выводит по одному символу. Сначала центральный процессор должен подождать, пока устройство будет готово, и только после этого он выводит символ, и эта последовательность действий повторяется для каждого символа. Процедуры in и out - это обычные процедуры языка ассемблера для чтения и записи регистров устройств, которые определяются по первому параметру, из или в переменную, которая определяется по второму параметру. Деление на 128 убирает младшие 7 битов, при этом бит READY остается в бите 0.

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

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

умножения (И) бита разрешения прерываний и бита готовности устройства. Если программное обеспечение сначала разрешает прерывание (перед запуском устройства ввода-вывода), прерывание произойдет сразу же, поскольку бит готовности будет равен 1. Таким образом, может понадобиться сначала запустить устройство, а затем сразу после этого ввести прерывание. Запись байта в регистр состояния устройства не изменяет бита готовности, который может только считываться.

Ввод-вывод с управлением по прерываниям - это большой шаг вперед по сравнению с программируемым вводом-выводом, но все же он далеко не совершенен. Дело в том, что прерывание требуется для каждого передаваемого символа. Следовательно, нужно каким-то образом избавиться от большинства прерываний. Решение лежит в возвращении к программируемому вводу-выводу. Но только эту работу должен выполнять кто-то другой. Посмотрите на рис. 5.20. Мы добавили новую микросхему - контроллер прямого доступа к памяти (ПДП) с прямым доступом к шине.

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

Чтобы записать блок из 32 байтов из адреса памяти 100 на терминал (напри-

мер, устройство 4), центральный процессор записывает числа 32,100 и 4 в первые три регистра ПДП и код записи (например, 1) в четвертый регистр, как показано на рис. 5.20. Контроллер ПДП, инициализированный таким способом, делает запрос на доступ к шине, чтобы считать байт 100 из памяти, точно так же как если бы центральный процессор считывал этот байт. Получив нужный байт, контроллер ПДП посылает устройству 4 запрос на ввод-вывод, чтобы записать на него байт. После завершения этих двух операций контроллер ПДП увеличивает значение регистра адреса на 1 и уменьшает значение регистра счетчика на 1. Если значение счетчика больше 0, то следующий байт считывается из памяти и записывается на устройство ввода-вывода. Когда значение счетчика доходит до 0, контроллер ПДП останавливает передачу данных и устанавливает линию прерывания на микросхеме процессора. При наличии ПДП центральному процессору нужно только инициализировать несколько регистров. После этого центральный процессор может выполнять какую-либо другую работу до тех пор, пока передача данных не завершится. При завершении передачи данных центральный процессор получает сигнал прерывания от контроллера ПДП. Некоторые контроллеры ПДП содержат два, три и более наборов регистров, так что они могут управлять несколькими процессами передачи одновременно.

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

Последовательный поток управления и переходы

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

Если программа содержит переходы, то это простое соотношение между порядком расположения команд в памяти и порядком их выполнения больше не соответствует действительности. При наличии переходов счетчик команд больше не является монотонно возрастающей функцией от времени, как показано на рис. 5.24, б. В результате последовательность выполнения команд из самой программы уже не видна. Если программисты не знают, в какой последовательности процессор будет выполнять команды, это может привести к ошибкам. Такое наблюдение побудило Дейкстру [31] написать статью под названием «Оператор GOTO нужно считать вредным», в котором он предлагал избегать в программах оператора goto. Эта статья дала толчок революции в программировании, одним из нововведений которой было устранение операторов goto более структурированными формами потока управления, например циклами while. Конечно, эти программы компилируются в программы второго уровня, которые могут содержать

многочисленные переходы, поскольку реализация операторов if, while и структур языков высокого уровня требует совершения переходов.

Процедуры

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

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

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

«Ханойская башня» - это древняя задача, которая имеет простое решение с

использованием рекурсии. В одном монастыре в Ханое есть три золотых колышка. Вокруг первого из них располагались 64 концентрических золотых диска, каждый из них с отверстием посередине для колышка. Диаметр дисков уменьшается снизу вверх. Второй и третий колышки абсолютно пусты. Монахи переносят все диски на колышек 3 по одному диску, но диск большего размера не может находиться сверху на диске меньшего размера. Говорят, что когда они закончат, наступит конец света. Если вы хотите потренироваться, вы можете использовать пластиковые диски, и не 64, а поменьше, но когда вы решите эту задачу, ничего страшного не произойдет. Чтобы произошел конец света, требуется 64 диска, и все они должны быть из золота. На рисунке 5.25 показана начальная конфигурация, где число дисков (п) равно 5.

Чтобы переместить п дисков с колышка 1 на колышек 3, нужно сначала перенести п-1 дисков с колышка 1 на колышек 2, затем перенести один диск с колышка1 на колышек 3, а потом перенести п-1 диск с колышка 2 на колышек 3. Решение этой задачи проиллюстрировано на рис. 5.26.

Для решения задачи нам нужна процедура, которая перемещает п дисков с колышка i на колышек]. Когда эта процедура вызывается, towers (n I j)

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

towers (3. 1 3) порождает еще три вызова

towers (2 1 2)

towers (I 1.3)

towers (2, 2 3)

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

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

Помимо указателя стека, который указывает на вершину стека, удобно иметь

указатель фрейма (FP - Frame Pointer), который указывает на фиксированное

место во фрейме. Он может указывать на связующий указатель, как в IJVM, или на первую локальную переменную. На рис. 5.27 изображен стековый фрейм для машины с 32-битным словом. При первом вызове процедуры towers в стек помещаются n, i и j, а затем выполняется команда CALL, которая помещает в стек адрес возврата, 1012. Вызванная процедура сохраняет в стеке старое значение FP (1000) в ячейке 1016, а затем передвигает указатель стека для обозначения места хранения локальных переменных. При наличии только одной 32-битной локальной переменной (k) SP (Stack Pointer - указатель стека) увеличивается на 4 до 1020. На рис. 5.27, а показан результат всех этих действий. Первое, что должна сделать процедура после того, как ее вызвали, - это сохранить предыдущее значение FP (так, чтобы его можно было восстановить при выходе из процедуры), скопировать значение SP в FP и, возможно, увеличить на одно слово, в зависимости от того, куда указывает FP нового фрейма. В этом примере FP указывает на первую локальную переменную, а в IJVM LV указывает на связующий указатель. Разные машины оперируют с указателем фрейма немного поразному, иногда помещая его в самый низ стекового фрейма, иногда - в вершину, а иногда - в середину, как на рис. 5.27. В этом отношении стоит сравнить рис. 5.27 с рис. 4.12, чтобы увидеть два разных способа обращения со связующим указателем. Возможны и другие способы. Но в любом случае обязательно должна быть возможность выйти из процедуры и восстановить предыдущее состояние стека. Код, который сохраняет старый указатель фрейма, устанавливает новый указатель фрейма и увеличивает указатель стека, чтобы зарезервировать пространство для локальных переменных, называется прологом процедуры. При выходе из процедуры стек должен быть очищен, и этот процесс называется эпилогом процедуры. Одна из важнейших характеристик компьютера - насколько быстро он может совершать пролог и эпилог. Если они очень длинные и выполняются медленно, делать вызовы процедур будет невыгодно. Команды ENTER и LEAVE в машине Pentium II были разработаны для того, чтобы пролог и эпилог процедуры работали эффективно. Конечно, они содержат определенную модель обращения с указателем фрейма, и если компилятор имеет другую модель, их нельзя использовать. А теперь вернемся к задаче «Ханойская башня». Каждый вызов процедуры добавляет новый фрейм к стеку, а каждый выход из процедуры удаляет фрейм из стека. Ниже мы проиллюстрируем, как используется стек при реализации рекурсивных процедур. Начнем с вызова towers (3. 1, 3)

На рис. 5.27, а показано состояние стека сразу после вызова процедуры. Сначала процедура проверяет, равно ли п единице, а установив, что п=3, заполняет к и совершает вызов towers (2. 1. 2)

Состояние стека после завершения этого вызова показано на рис. 5.27, б. После этого процедура начинается с начала (вызванная процедура всегда начинается с начала). На этот раз условие п=1 снова не подтверждается, поэтому процедура снова заполняет к и совершает вызов towers (1. 1, 3)

Состояние стека после этого вызова показано на рис. 5.27, в. Счетчик команд

указывает на начало процедуры. На этот раз условие подтверждается, и на экран выводится строка. Затем совершается выход из процедуры. Для этого удаляется один фрейм, а значения FP и SP переопределяются (см. рис. 5.27, г). Затем процедура продолжает выполняться в адресе возврата:

towers (1. 1. 2) Это добавляет новый фрейм в стек (см. рис. 5.27, д). Печатается еще одна строка. После выхода из процедуры фрейм удаляется из стека. Вызовы процедур продолжаются до тех пор, пока не завершится выполнение первой процедуры и пока фрейм, изображенный на рис. 5.27, а, не будет удален из стека. Чтобы вы лучше смогли понять, как работает рекурсия, вам нужно произвести полное выполнение процедуры towers (3. 1. 3) используя ручку и бумагу.

Сопрограммы

В обычной последовательности вызовов существует четкое различие между вызывающей процедурой и вызываемой процедурой. Рассмотрим процедуру А, которая вызывает процедуру В (рис. 5.28).

Процедура В работает какое-то время, затем возвращается к А. На первый взгляд может показаться, что эти ситуации симметричны, поскольку ни А, ни В не являются главной программой. И А, и В - это процедуры. (Процедуру А можно было бы назвать основной программой, но это в данном случае неуместно.) Более того, сначала управление передается от А к В (при вызове), а затем - от В к А (при возвращении).Различие состоит в том, что когда управление переходит от А к В, процедура В начинает выполняться с самого начала; а при переходе из В обратно в А выполнение начинается не с начала процедуры А, а с того момента, за которым последовал вызов процедуры В. Если А работает некоторое время, а потом снова вызывает

процедуру В, выполнение В снова начинается с самого начала, а не с того места, после которого произошло возвращение к процедуре А. Если процедура А вызывает процедуру В много раз, процедура В каждый раз начинается с начала, а процедура А уже никогда больше с начала не начинается. Это различие отражается в способе передачи управления между А и В. Когда А вызывает В, она использует команду вызова процедуры, которая помещает адрес возврата (то есть адрес того выражения, которое последует за процедурой) в такое место, откуда его потом легко будет вытащить, например в вершину стека. Затем она помещает адрес процедуры В в счетчик команд, чтобы завершить вызов. Для выхода из процедуры В используется не команда вызова процедуры, а команда выхода из процедуры, которая просто выталкивает адрес возврата из стека и помещает его в счетчик команд. Иногда нужно иметь две процедуры А и В, каждая из которых вызывает другую в качестве процедуры, как показано на рис. 5.29. При возврате из В к А процедура В совершает переход к тому оператору, за которым последовал вызов процедуры В. Когда процедура А передает управление процедуре В, она возвращается не к самому началу В (за исключением первого раза), а к тому месту, на котором произошел предыдущий вызов А. Две процедуры, работающие подобным образом,

называются сопрограммами.

Сопрограммы обычно используются для того, чтобы производить параллель-

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

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

Ловушки

Ловушка (trap) - это особый тип вызова процедуры, который происходит при

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

Важно то, что этот вид прерывания вызывается каким-то исключительным условием, вызванным самой программой и обнаруженным аппаратным обеспечением или микропрограммой. Есть и другой способ определения переполнения. Нужно иметь 1-битный регистр, который принимает значение всякий раз, когда происходит переполнение. Программист, который хочет проверить результат на переполнение, должен включить в программу явную команду «переход в случае установки бита переполнения» после каждой арифметической команды. Но это очень неудобно. А ловушки экономят время и память по сравнению с открытой проверкой под контролем программиста. Ловушку можно реализовать путем открытой проверки, выполняемой микропрограммой (или аппаратным обеспечением). Если обнаружено переполнение, адрес ловушки загружается в счетчик команд. То, что является ловушкой на одном уровне, может находиться под контролем программы на более низком уровне. Проверка на уровне микропрограммы требует меньше времени, чем проверка под контролем программиста, поскольку она может выполняться одновременно с каким-либо другим действием. Кроме того, такая проверка экономит память, поскольку она должна присутствовать только в одном месте, например в основном цикле

микропрограммы, независимо от того, сколько арифметических команд встречается в основной программе.

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

Прерывания

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

которое было до прерывания) должно быть восстановлено.

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

Чтобы понять, как происходят прерывания, рассмотрим обычный пример: компьютеру нужно вывести на терминал строку символов. Программное обеспечение сначала собирает в буфер все символы, которые нужно вывести на экран, инициализирует глобальную переменную ptr, которая должна указывать на начало буфера, и устанавливает вторую глобальную переменную count, которая равна числу символов, выводимых на экран. Затем программное обеспечение проверяет, готов ли терминал, и если готов, то выводит на экран первый символ (например, используя регистры, которые показаны на рис. 5.30). Начав процесс ввода-вывода, центральный процессор освобождается и может запустить другую программу или сделать что-либо еще. Через некоторое время символ отображается на экране. Теперь может начаться прерывание. Ниже перечислены основные шаги (в упрощенной форме).

Действия аппаратного обеспечения:

1. Контроллер устройства устанавливает линию прерывания на системной

шине.

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

3. Когда контроллер устройства узнает, что сигнал прерывания был подтвержден, он помещает небольшое целое число на информационные линии, чтобы «представиться» (то есть показать, что это за устройство). Это число называется вектором прерываний.

4. Центральный процессор удаляет вектор прерывания с шины и временно его сохраняет.

5. Центральный процессор помещает в стек счетчик команд и слово состояния

программы.

6. Затем центральный процессор определяет местонахождение нового счетчика команд, используя вектор прерывания в качестве индекса в таблице в нижней части памяти. Если, например, размер счетчика команд составляет 4 байта, тогда вектор прерываний п соответствует адресу 4п. Новый счетчик команд указывает на начало программы обслуживания прерываний для устройства, вызвавшего прерывание. Часто помимо этого загружается или изменяется слово состояния программы (например, чтобы блокировать дальнейшие прерывания).

Действия программного обеспечения:

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





Дата публикования: 2014-10-17; Прочитано: 705 | Нарушение авторского права страницы | Мы поможем в написании вашей работы!



studopedia.org - Студопедия.Орг - 2014-2024 год. Студопедия не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования (0.016 с)...