Адресация по указателю стека
Стек – память с определенной (упрощенной) формой адресации. В микропроцессорной системе на МПК КР580 стек организуется следующим образом. В ОЗУ команды размещаются в ячейках с младшими, последовательно нарастающими адресами. Стек использует ячейки со старшими адресами, и по мере заполнения стека занимаются ячейки с адресами, последовательно убывающими (рисунке 8.2.3.1,а). Особенность организации стека состоит в следующем. Указатель стека SP содержит так называемый адрес входа в стек; при чтении из стека производится выборка содержимого ячейки по адресу входа в стек (адресу, хранящемуся в SP); при записи в стек вводимое в стек число помещается в ячейку с адресом, на единицу меньшим содержимого SP; одновременно с записью и чтением изменяется содержимое SP: при записи уменьшается, а при чтении увеличивается на единицу.
Рисунок 8.2.3.1.
Обмен со стеком производится двухбайтовыми словами, занимающими две ячейки памяти. Пусть указатель стека хранит адрес А.. При вводе нового слова его байты должны быть помещены в пару соседних со входом в стек ячеек, имеющих адреса А – 1 и А – 2. Таким образом, ввод в стек сводится к следующей последовательности действий: содержимое SP уменьшается на единицу и по образующемуся адресу помещается старший байт вводимого двухбайтового слова; затем содержимое SP вновь уменьшается на единицу и по образующемуся адресу помещается младший байт вводимого слова (рисунок 8.2.3.1.б). Мы видим, что SP каждый раз указывает адрес ячейки, являющейся входом в стек.
Вывод данных из стека производится также двухбайтовыми словами. При этом каждый раз доступна для чтения лишь ячейка, адрес которой содержится в SP. Если указатель стека хранит адрес А, то байты выводимого из стека слова выбираются из ячеек памяти, имеющих адреса А и А + 1. Таким образом, выбор слова из стека сводится к такой последовательности действий: чтение младшего байта выводимого слова из ячейки, адресом которой служит содержимое SP, и увеличение содержимого SP на единицу; затем чтение старшего байта выводимого слова по адресу, хранящемуся в SP, и увеличение содержимого SP на единицу (рис. 5.6, в).
О таком принципе функционирования, когда читается последняя помещенная в память информация, говорят как о принципе "последним вошел – первым вышел". Как видим, при записи и чтении производится обращение в ячейку, адрес которой связан с содержимым SP. Это упрощает адресацию памяти, но исключает возможность обращения в произвольную ячейку памяти.
Рассмотрим некоторые команды операций со стеком.
Установка в SP некоторого начального значения производится по команде пересылки SPHL (11 111 001), по которой в SP пересылается содержимое пары регистров HL.
Команда ввода из пары регистров DE в стек: PUSH D (11 010 101). В разрядах D5 D4 D3 кодовой комбинации команды указан адрес 010 старшего регистра пары DE. По этой команде выполняются следующие действия:
SP ← (SP) - 1, [(SP)] ← (D), SP ← (SP) - 1, [(SP)] ← (Е).
Команда пересылки из стека в пару регистров DE: POP D (11 010 001). Здесь в разрядах D5 D4 D3 кодовой комбинации команды указан адрес 010 старшего регистра пары DE. По данной команде выполняются действия:
Е ← [(SP)], SP ← (SP) + 1, D ← [(SP)], SP ← (SP) + 1.
8.2.4. Система команд
Микропроцессоры выполняют набор команд, которые реализуют следующие основные группы операций:
1. операции пересылки;
2. арифметические операции;
3. логические операции;
4. операции сдвига;
5. операции сравнения и тестирования;
6. битовые операции;
7. операции управления программой;
8. операции управления процессором.
При описании команд обычно используются их мнемонические обозначения (мнемокоды), которые служат для задания команды при программировании на языке ассемблера. Мнемокоды являются сокращениями соответствующих английских слов, определяющих выполняемую операцию.
Команды пересылки. Основной командой этой группы является команда MOV, которая обеспечивает пересылку данных между двумя регистрами или между регистром и ячейкой памяти.
Команды ввода IN и вывода OUT реализуют пересылку данных из регистра процессора во внешнее устройство или прием данных из внешнего устройства в регистр. В этих командах задается номер интерфейсного устройства (порта ввода-вывода), через которое производится передача данных.
Команды арифметических операций. Основными в этой группе являются команды сложения, вычитания, умножения и деления, которые имеют ряд вариантов. Команды сложения ADD и вычитания SUB выполняют соответствующие операции с содержимым двух регистров, регистра и ячейки памяти или с использованием непосредственного операнда. Команды ADC, SBB производят сложение и вычитание с учетом значения признака С, устанавливаемого при формировании переноса или заема в процессе выполнения предыдущей операции. С помощью этих команд реализуется последовательное сложение операндов, число разрядов которых превышает разрядность процессора. Команда NEG изменяет знак операнда, переводя его в дополнительный код.
Операции умножения и деления могут выполняться над числами со знаком (команды IMUL, IDIV) или без знака (команды MUL, DIV). Один из операндов всегда размещается в регистре, второй может находиться в регистре, ячейке памяти или быть непосредственным операндом. Результат операции располагается в регистре. При умножении (команды MUL, IMUL) получается результат удвоенной разрядности, для размещения которого используется два регистра. При делении (команды DIV, IDIV) в качестве делимого используется операнд удвоенной разрядности, размещаемый в двух регистрах, а в качестве результата в два регистра записывается частное и остаток.
Команды логических операций. Практически все микропроцессоры производят логические операции И, ИЛИ, Исключающее ИЛИ, которые выполняются над одноименными разрядами операндов с помощью команд AND, OR, XOR. Операции выполняются над содержимым двух регистров, регистра и ячейки памяти или с использованием непосредственного операнда. Команда NOT инвертирует значение каждого разряда операнда.
Команды сдвига. Микропроцессоры осуществляют арифметические, логические и циклические сдвиги адресуемых операндов на один или несколько разрядов. Сдвигаемый операнд может находиться в регистре или ячейке памяти, а число разрядов сдвига задается с помощью непосредственного операнда, содержащегося в команде, или определяется содержимым заданного регистра. В реализации сдвига обычно участвует признак переноса С в регистре состояний (SR или EFLAGS), в котором располагается последний разряд операнда, выдвигаемый из регистра или ячейки памяти.
Выполнение основных команд сдвига показано на рисунке 8.2.4.1.:
– логические сдвиги влево (команда SHL) и вправо (команда SHR),
– арифметический сдвиг влево (команда SAL),
– циклические сдвиги выполняются с включением признака С в цепь переноса (команды RCL, RCR),
– циклические сдвиги выполняются с использованием признака С для хранения последнего выдвигаемого разряда операнда (команды ROL, ROR)
Рисунок 8.2.4.1. Выполнение основных команд сдвига.
Команды сравнения и тестирования. Сравнение операндов обычно осуществляется с помощью команды СМР, которая производит вычитание операндов с установкой значений признаков N, Z, V, С в регистре состояния в соответствии с полученным результатом. При этом результат вычитания не сохраняется и значения операндов не изменяются. Последующий анализ полученных значений признаков позволяет определить относительное значение (>,<, = ) операндов со знаком или без знака. Использование различных способов адресации позволяет производить сравнение содержимого двух регистров, регистра и ячейки памяти, непосредственно заданного операнда с содержимым регистра или ячейки памяти.
Некоторые микропроцессоры выполняют команду тестирования TST, которая является однооперандным вариантом команды сравнения. При выполнении этой команды устанавливаются признаки N, Z в соответствии со знаком и значением (равно или не равно нулю) адресуемого операнда.
Команды битовых операций. Эти команды производят установку значения признака С в регистре состояний в соответствии со значением тестируемого бита bn в адресуемом операнде. В некоторых микропроцессорах по результату тестирования бита производится установка признака Z. Номер тестируемого бита n задается либо содержимым указанного в команде регистра, либо непосредственным операндом.
Команды данной группы реализуют разные варианты изменения тестируемого бита. Команда ВТ сохраняет значение этого бита неизменным. Команда BTS после тестирования устанавливает значение bn = 1, а команда ВТС - значение bn = 0. Команда ВТС инвертирует значение бита bn после его тестирования.
Команды управления программой можно разделить на несколько групп:
– команды безусловной передачи управления;
– команды условных переходов;
– команды организации программных циклов;
– команды прерывания;
– команды изменения признаков.
Безусловная передача управления производится командой JMP, которая загружает в программный счетчик PC новое содержимое, являющееся адресом следующей выполняемой команды. Этот адрес либо непосредственно указывается в команде JMP (прямая адресация), либо вычисляется как сумма текущего содержимого PC и заданного в команде смещения, которое является числом со знаком (относительная адресация). Так как PC содержит адрес очередной команды программы, то последний способ задает адрес перехода, смещенный относительно очередного адреса на заданное число байтов. При положительном смещении производится переход к последующим командам программы, при отрицательном смещении – к предыдущим.
Вызов подпрограммы также производится путем безусловной передачи управления с помощью команды CALL (или JSR). Однако в этом случае перед загрузкой в PC нового содержимого, задающего адрес первой команды подпрограммы, необходимо сохранить его текущее значение (адрес очередной команды), чтобы после выполнения подпрограммы обеспечить возвращение к основной программе (или к предыдущей подпрограмме при вложении подпрограмм). Текущее содержимое PC обычно сохраняется в стеке, который организуется в ОЗУ. После выполнения подпрограммы выполняется безусловная передача управления исходной программе с помощью команды возврата из подпрограммы RET, которая выбирает из стека и загружает в PC его старое содержимое.
Команды условных переходов (ветвлений программы) производят загрузку в PC нового содержимого, если выполняются определенные условия, которые обычно задаются в соответствии с текущим значением различных признаков в регистре состояния. Если условие не реализуется, то выполняется следующая команда программы. В таблице 8.2.3.1 приведены типовые команды условных переходов, которые реализуются в большинстве микропроцессоров (мнемокоды команд даны для процессоров Pentium).
Таблица 8.2.3.1. Типовые команды условных переходов
Мнемокод | Условие | Мнемокод | Условие |
JO | Переполнение V= 1 | JNO | Нет переполнения V = 0 |
JB | Ниже (не выше и не равно) С= 1 | JNB | Не ниже (выше или равно) С = 0 |
JE | Равно (нуль) ZF= 1 | JNE | Не равно (не нуль) Z = 0 |
JBE | Ниже или равно (не выше) C + Z= 1 | JNBE | Не ниже и не равно (выше) C + Z = 0 |
JS | Отрицательный знак N= 1 | JNS | Положительный знак N = 0 |
JL | Меньше (не больше и не равно) | JNL | Не меньше (больше или равно) |
JLE | Меньше или равно (не больше) | JNLE | Не меньше и не равно (больше) |
В качестве условия часто используется относительное значение двух операндов, определяемое с помощью команды сравнения СМР. Например, равенство операндов определяется значением признака нуля Z после команды СМР: операнды равны, есл Z = 1 (результат равен 0); не равны, если Z = 0 (результат не равен 0.
Команды организации программных циклов осуществляют условный переход в зависимости от значения содержимого заданного регистра, который используется как счетчик циклов. Например, в процессорах Pentium для организации циклов используется команда LOOP и регистр ЕСХ. Команда LOOP уменьшает содержимое ЕСХ на 1 (декремент) и проверяет полученное значение. Если содержимое ЕСХ = 0, то выполняется переход к команде, адрес которой определяется с помощью относительной адресации (смещение задано в команде LOOP). Если ЕСХ=0, то выполняется следующая команда программы. Команда LOOP обычно ставится в конце цикла, обеспечивая его выполнение n раз, где n задается начальным значением ЕСХ.
Команды прерываний INT обеспечивают переход к одной из программ обслуживания исключений и прерываний (обработчику прерываний О). При этом текущее содержимое PC и регистра состояния заносится в стек. Каждая из программ обработки соответствует определенному типу исключения или прерывания. Например, в процессорах Pentium выбор программы обработки определяется 8-разрядным операндом, задаваемым во втором байте команды INT. Вызов соответствующей программы обслуживания производится с помощью таблицы, в которой содержатся векторы исключений (прерываний) – адреса первых команд программ обслуживания. Каждый вектор задает необходимое содержимое PC, загрузка которого обеспечивает переход к выполнению первой команды программы обслуживания. Команда IRET обеспечивает возврат из подпрограммы обслуживания прерывания путем извлечения из стека и восстановления содержимого программного счетчика и регистра состояния, соответствующих прерванной процедуре.
Команды управления признаками обеспечивают запись-чтение содержимого регистра состояния, в котором хранятся признаки, а также изменение значений отдельных признаков. Например, в процессорах Pentium реализуются команды LAHF и SAHF, которые выполняют загрузку младшего байта, где содержатся признаки, из регистра состояния EFLAG в младший байт регистра ЕАХ и заполнение младшего байта EFLAGS из регистра ЕАХ. Команды CLC, STC осуществляют установку значений признака переноса CF = 0, CF = 1, а команда CMC вызывает инвертирование значения этого признака. Так как признаки определяют ход выполнения программы при условных переходах, то команды изменения признаков обычно используются для управления программой.
Команды управления процессором. К этой группе относятся команды останова, отсутствия операции и ряд команд, определяющих режим работы процессора или его отдельных блоков. Команда HLT прекращает выполнение программы и переводит процессор в состояние останова, выход из которого происходит при поступлении сигналов прерывания или перезапуска (Reset). Команда NOP («пустая» команда), которая не вызывает выполнения каких-либо операций, служит для реализации программных задержек или заполнения пропусков, образовавшихся в программе.
Специальные команды CLI, STI запрещают и разрешают обслуживание запросов прерывания, устанавливая соответствующее значение бита управления I в регистре состояния процессора. В процессорах Pentium для этого используется бит управления (флаг) IF в регистре EFLAGS.
Многие современные микропроцессоры выполняют команду идентификации, которая позволяет пользователю или другим устройствам получить информацию о типе процессора, используемого в данной системе. В процессорах Pentuim для этого служит команда CPUID, при выполнении которой необходимые данные о процессоре поступают в регистры ЕАХ, ЕВХ, ЕСХ, EDX и могут затем считываться пользователем или операционной системой.
В процессорах, которые имеют внутреннюю кэш-память, реализуются специальные команды, управляющие ее работой. При поступлении этих команд производится очистка (аннулирование содержимого) кэш-памяти, обеспечивается запись в ОЗУ определенных строк кэш-памяти и некоторые другие операции.