Принципы работы компьютера




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

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

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

Microsoft (R) Macro Assembler Version 5.00 10/31/88 22:30:38Фиг. 2.16 Команда перехода Page 1-11 PAGE,1322 TITLE Фиг. 2.16 Команда перехода3 0000 CODE SEGMENT4 ASSUME CS:CODE56 0000 MEMLABEL BYTE78 0000 FIG2_16:9 0000 2E: C6 87 0000 R 00 MOV MEM[BX],010 0006 43 INC BX11 0007 EB F7 JMP FIG2_161213 0009 CODE ENDS14 END

Фиг. 2.16 Команда перехода

Обратите внимание, что в команде JMP для определения следующего выполняемого адреса используется метка, в данном случае "FIG2_16". Это - еще одна из возможностей ассемблера. Хотя в машинном языке требуется абсолютный адрес следующей команды, язык ассемблера требует лишь программно определенную метку. Ассемблер сам определяет абсолютный адрес и ставит правильное значение в команду машинного языка.

Команда перехода не обязательно должна быть безусловной как в приведенном примере. 8088 располагает множством команд перехода, которые выполняются в соответствии с некоторым кодом условия. Значение кода условия устанавливают другие команды при их выполнении процессором. Условие, указанное в команде условного перехода, сравнивается с кодом условия, сохраненного в регистре состояний. Если условия совпадают, то процессор переходит по указанному адресу. В противном случае процессор игнорирует переход, и выполнение программы продолжается в обычном последовательном порядке. На Фиг. 2.17 предыдущий пример изменен. Цикл в этом примере прерывается, когда значение BX становится равным 1000.

На Фиг. 2.17 появляется новая команда сравнения, которая устанавливает коды состояния. Команда условного перехода (JNE (Jump if Not Equal) переход, если не равны) выполняет переход на "FIG2_17", если условие выполнено. Если условие не выполняется, 8088 выполняет команду, следующую за условным переходом, в данном случае команду NOP. Команда условного перехода позволяет проверить

Microsoft (R) Macro Assembler Version 5.00 11/2/88 22:31:33Фиг. 2.17 Команда условного перехода Page1-11 PAGE,1322 TITLE Фиг. 2.17 Команда условного перехода3 0000 CODE SEGMENT4 ASSUME CS:CODE56 0000 MEMLABEL BYTE7 8 0000 FIG2_17:9 0000 2E: C6 87 0000 R 00 MOV MEM[BX],010 0006 43 INC BX11 0007 81 FB 03E8 CMP BX,100012 000B EB F3 JMP FIG2_171314 000D CODE ENDS END

Фиг. 2.17 Команда условного перехода

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

Процедуры

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

Давайте посмотрим, как работает вызов процедуры. Пусть, например, нам надо написать программу, которая складывает в нескольких местах 32-битовые числа. У микропроцессора 8088 нет команд, которые выполняли бы такое сложение. Мы можем написать короткую последовательность команд, которая будет выполнять сложение 32-битовых чисел. Эта часть программы будет процедурой.

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

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

Команды, которые обеспечивают выполнение процедуры - CALL и RETURN. CALL - это переход на процедуру. CALL сохраняет текущее значение указателя команд в специальном месте памяти. Это сохраненное значение указателя команд является адресом возврата. Команда RETURN читает сохраненное значение указателя команд, помещает его в указатель команд процессора и возвращает управление в точку, следующую за командой CALL. Пример на Фиг. 2.18 показывает процедуру, вызываемую из двух различных точек программы.

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

Microsoft (R) Macro Assembler Version 5.00 5/11/80 16:25:59Фиг. 2.18 Использование процедуры Page 1-11 PAGE,1322 TITLE Фиг. 2.18 Использование процедуры3 0000 CODE SEGMENT4 ASSUME CS:CODE5 0000 E8 0008 R A1: CALL SUBROUTINE6 0003 40 A2: INC AX7 0004 E8 0008 R A3: CALL SUBROUTINE8 0007 43 A4: INC BX;----- Здесь программа продолжается...9 0008 SUBROUTINE PROC NEAR10 0008 B8 0000 MOV AX,011 000B BB 0000 MOV BX,012 000E C3 RET13 000F SUBROUTINE ENDP14 000F CODE ENDS15 END

Фиг. 2.18 Использование процедуры

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

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

Стек

Стек - это структура данных, которая используется для временного хранения информации. Программа может поместить данные в стек (PUSH) или забрать их оттуда (POP). Стековая структура данных предполагает упорядочивание помещенных в него данных специальным образом. Во всех случаях первым из стека извлекается то, что было в нем сохранено последним. Такая организация хранения данных сокращенно обозначается LIFO (last in, first out - последний введенный первым выводится). Если мы поместили в стек сначала A, затем B, то первое, что мы извлечем из него будет B. Следующая команда извлечения (POP) вернет A. Информация возвращается из стека в порядке, строго противоположном порядку ее помещения в стек.

Стек противоположен очереди. Очередь - это обычная последовательность, подобная очередям на почте или в магазине. Это структура данных типа "первым вошел - первым вышел" (first in, first out: FIFO). Тот, кто первым встал в очередь, первым и покинет ее. Стек и очередь - очень разные вещи.

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

Фиг. 2.19 дает пример стека. В части (a) изображен стек после того как в него последовательно помещены значения A, B, C. Указатель стека указывает на текущую вершину стека, в данном случае на C. В части (b) в стек помещается еще одно значение: D. Операция PUSH уменьшает указатель стека SP (от Stack Pointer - указатель стека), который теперь указывает на новую вершину D. Указатель стека всегда фиксирует то, что было последним помещено в стек.

Фиг. 2.19(c) показывает состояние стека после операции POP. Этой операцией значение D было извлечено из стека. Команда POP помещает извлеченное из стека значение в указанное место. Если в части (c) выполнялась команда POP AX, то процессор поместил значение D в регистр AX (это уже дополнительный аспект, который мы обсудим в следующей главе). POP увеличивает указатель стека. Теперь он указывает на новую вершину, C. Заметим, что элементы извлекаются из стека по описанному принципу LIFO. Последним помещенным в стек элементом был D и он же первым извлечен из стека. Обратите также внимание, что D так и осталось в памяти, однако теперь уже не является частью стека. Логическая граница стека находится по адресу, хранящемуся в его указателе. В данном случае вершина стека оказывается ниже ячейки со значением D.

На Фиг. 2.19(d) видно, что происходит с D при помещении в сетк нового элемента E. Элемент E записывается на место D и становится новой вершиной стека. Мораль из этой истории такова, что хотя извлеченные из стека значения могут оставаться в памяти, полагаться на это не следует.

Таблица испрочена в оригинале

Фиг. 2.19 Пример работы стека

В приведенном примере подразумевался принцип построения стека процессора 8088. Указатель стека постоянно указывает на текущую вершину стека. Операция PUSH уменьшает указатель стека, POP увеличивает его. Стек растет в направлении уменьшения адресов в памяти. Основание стека располагается в памяти по большему адресу, чем его вершина. Если вы нарисуете изображения стека с наименьшим адресом сверху, как на Фиг. 2.19, то вершина стека окажется в верхней части рисунка.

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

Каждая команда CALL вызывает как бы выполнению команды PUSH для стека - сохраняет в стеке адрес возврата. Команда RET извлекает из стека, подобно команде POP, адрес возврата и помещает его в указатель команд. 8088 использует стек для хранения адресов возврата потому, что это позволяет вкладывать процедуры одна в другую. Что такое вложение? На Фиг. 2.20 показан пример вложенных процедур.

На Фиг. 2.20 показана абсурдная программа, которую мы используем как пример вложения процедур. Часть (a) показывает стек перед выполнением программы. Как только начинает выполняться процедура MAIN, она вызывает процедуру SUBROUTINE_A. В это время процессор сохраняет в стек адрес возврата. Часть (b) показывает адрес возврата 103 помещенным в стек. SUBROUTINE_A в процессе своего выполнения вызывает SUBROUNINE_B. Команда этого вызова сохраняет адрес возврата 108 в SUBROUNINE_A. Когда SUBROUNINE_B заканчивается, команда возврата извлекает из стека значение 108, как показано в части (d). Процессор помещает это значение в указатель команд, как требуется при команде возврата. Как видно на листинге ассемблера, адрес 108 относится к SUBROUNINE_A и следует сразу за вызовом SUBROUNINE_B. Затем SUBROUNINE_A заканчивается. Команда возврата извлекает из стека значение 103 для указателя команд. Адрес 103 относится к процедуре MAIN и следует сразу за вызовом SUBROUNINE_A.

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

Microsoft (R) Macro Assembler Version 5.00 11/10/88 23:18:17Фиг. 2.20 Вызов вложенных процедур Page 1-11 PAGE,1322 TITLE Фиг. 2.20 Вызов вложенных процедур34 0000 CODE SEGMENT5 ASSUME CS:CODE6 0100 ORG 100H7 0100 E8 0104 R MAIN: CALL SUBROUTINE_A8 0103 40 INC AX;----- Здесь главная процедура продолжается9 0104 SUBROUTINE_A PROC NEAR10 0104 43 INC BX11 0105 E8 0109 R CALL SUBROUTINE_B12 0108 C3 RET13 0109 SUBROUTINE_A ENDP14 0109 SUBROUTINE_B PROC NEAR15 0109 41 INC CX16 010A C3 RET17 010B SUBROUTINE_B ENDP18 010B CODE ENDS19 END
IP SP top+0 SP top+4 SP==> execute command
  xxx xxx xxx call SUBROUTINE_A
    xxx   inc bx
        inc cx
    xxx   ret
  xxx xxx xxx inc ax

Фиг. 2.20 Вызов вложенных процедур

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

Пример программы на Фиг. 2.20 показывает также использование еще одной псевдооперации ассемблера - PROC. Оператор PROC используется ассемблером для идентификации процедур. Как мы дальше увидим, ассемблер должен знать, как далеко располагается процедура и как возвращаться к точке ее вызова. Операнд NEAR определяет процедуру как расположенную в пределах легкой досигаемости вызывающей программы. Мы еще вернемся к оператору PROC, когда будем обсуждать реальное действие команд CALL и JMP.

Прерывания

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

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

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

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

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

В ходе прерывания 8088 автоматически сохраняет некоторые установленные программой значения в стек. В свою очередь, программа обработки прерываний отвечает за сохранение любых других данных, которые она может изменить во время своего выполнения. Эти данные обычно сохраняются в стеке. Затем, перед возвращением управления в прерванную программу, программа обработки прерывания должна вернуть измененным данным те значения, которые они имели в момент прерывания. Факт возникновения прерывания должен остаться "невидимым" для выполняемой программы.

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

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

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



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-02-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: