Files
ITMO/OPD/OPDLab4/guide.md
T

22 KiB

Гайд по 4 лабораторной работе по ОПД


Содержание


Введение

Здесь вкратце описана инфрмация, необходимая для защиты 4 лабы по ОПД.

Стек

Основные понятия

Стек - это структура данных, рабтающая по принципу LIFO (Last-In-First-Out), или "последним зашёл, первым вышел".

Стек можно представить как стопку книг. Книги можно ставить друг на друга только сверху, и чтобы достать какую-то определённую книгу, придётся сначала снять все остальные.

В основном для взаимодействия со стеком используются два действия: положить на стек и снять со стека.

Базовая ЭВМ

Всё, что описано ниже, верно для актуальной версии эмулятора базовой ЭВМ (bcomp-ng v1.45.09).

Для взаимодействия со стеком используется ряд команд, среди которых POP, POPF, PUSH, PUSHF и SWAP. Все они подробно рассмотрены ниже.

Сам стек распологается в последних ячейках памяти БЭВМ (точнее, он заполняется, начиная с последней ячейки памяти). Для управления стеком используется 11-разрядный регистр указателя стека (Stack Pointer - SP), который показывает последнюю заполненную ячейку стека. По умолчанию значение SP равно 0, что означает, что стек пуст (также это можно рассматривать и с другой стороны: указатель стека ставится на одну ячейку ниже той, в которую будет записано следующее его значение, и тогда 0 в SP будет образовываться из-за переполнения, а точнее добавления 1 к номеру последней ячейки памяти, то есть 7FF).

Подпрограммы

Всё, что описано ниже, верно для актуальной версии эмулятора базовой ЭВМ (bcomp-ng v1.45.09).

В актуальной версии БЭВМ подпрограммы являются некой мини-программой, которую удобно применять в случае, если какие-либо однотипные действия в основной программе выполняются по несколько раз.

Для вызова подпрограммы и возврата из неё предусмотрен ряд команд, среди которых CALL, RET, IRET.

В БЭВМ использование подпрограмм сильно переплетено с использованием стека. В основном стек используется для временного хранения каких-либо данных, необходимых для выполнения подпрограммы. В частности, в стек записываются адрес возварщения подпрограммы (то есть место, где программа должна будет продолжить выполнение после выполнения подпрограммы), аргументы подпрограммы и результаты выполнения подпрограммы.

Для передачи аргументов для подпрограммы существует три способа.

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

  • Также можно передавать аргументы для подпрограммы и используя регистры общего назначения (к сожалению, в БЭВМ он только один, и это AC).

  • Третьим способом будет использование косвенной адресации. Для этого сразу под командой CALL можно указать заранее определённое подпрограммой количество аргументов. При этом в самой подпрограмме можно выгрузить вершину стека (которая в тот момент времени будет являться адресом первого аргумента), а после косвенной адресацией (а точнее, косвенной постинкрементацией) загрузить и использовать эти аргументы в подпрограмме. Далле остаётся только обратно загрузить уже увеличенное значение возврата подпрограммы, и программа начнет выполнение команд, которые идут уже после аргументов.

Команды

Косвенная относительная адресация со смещением относительно SP

В третем ниббле имеет код C (в двоичной системе соответственно 1100), то есть имеет вид XCXX.

В ассемблере БЭВМ обозначается как &M или (SP+M), никакой разницы между данными обозначениями нет.

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

Цикл выборки адреса

  • 1 такт: SXT_CR(0..7) -> BR

    • По фронту происходит дополнение знака в АЛУ (то есть значения битов 15..8 становятся равными биту 7, где отсчет битов ведётся справа налево начиная с 0).
    • По спаду результат записывается в буферный регистр.
  • 2 такт: BR + SP -> DR

    • По фронту начение буферного регистра суммируется со значением указателя стека в АЛУ.
    • По спаду результат записывается в регистр данных.

Цикл выборки операнда

  • 1 такт: DR -> AR

    • По фронту пускает значение из регистра данных через АЛУ.
    • По спаду записывает это значение в адресный регистр.
  • 2 такт: MEM(AR) -> DR

    • По фронту находит ячейку в памяти по адресу.
    • По спаду записывает значение этой ячейки в регистр данных.

POP

Код: 0800.

Выгружает верхнее значение стека в аккумулятор.

Безадресная команда.

Цикл исполнения

  • 1 такт: SP -> AR

    • По фронту пускает значение регистра через АЛУ.

    • По спаду записывает его в адрсный регистр.

  • 2 такт: MEM(AR) -> DR

    • По фронту находит по адресу ячейку.

    • По спаду записывает значение этой ячейки в регистр данных.

  • 3 такт: DR -> AC

    • По фронту пускает значение регистра данных через АЛУ.

    • По спаду запишет его в аккумулятор.

  • 4 такт: SP + 1 -> SP

    • По фронту пустит значение указателя стека в АЛУ и прибавит 1.

    • По спаду запишет полученное значение в указатель стека.

После выполнения поставит флаги в соответствии с выгруженным значением, при этом не изменив флаг переноса и обнулив флаг переполнения.

Циклы выборки адреса и выборки операнда выполняться не будут, так как команда безадресная.

POPF

Код: 0900.

Выгружает верхнее значение стека в регистр состояния.

Безадресная команда.

Цикл исполнения

  • 1 такт: SP -> AR

    • По фронту пускает значение регистра через АЛУ.
    • По спаду записывает его в адрсный регистр.
  • 2 такт: MEM(AR) -> DR

    • По фронту находит по адресу ячейку.
    • По спаду записывает значение этой ячейки в регистр данных.
  • 3 такт: DR -> PS

    • По фронту пустит значение регистра данных в АЛУ.

    • По спаду запишет это значение в регистр состояния.

  • 4 такт: MEM(AR) -> DR

    • По фронту находит по адресу ячейку.
    • По спаду записывает значение этой ячейки в регистр данных.

Флаги, соответственно, возьмутся из регистра состояния.

Циклы выборки адреса и выборки операнда выполняться не будут, так как команда безадресная.

PUSH

Код: 0C00.

Загружает значение аккумулятора на вершину стека.

Безадресная команда.

Цикл исполнения

  • 1 такт: AC -> DR

    • По фронту пустит значение аккумулятора через АЛУ.

    • По спаду запишет его в регистр данных.

  • 2 такт: ~0 + SP -> SP, AR

    • По фронту прибавит в АЛУ к значению указателя стека ~0 (то есть -1).

    • По спаду запишет это значение в указатель стека и адресный регистр.

  • 3 такт: DR -> MEM(AR)

    • По фронту найдёт ячейку по адресу.

    • По спаду запишет значение регистра данных в эту ячейку.

Не меняет флаги.

Циклы выборки адреса и выборки операнда выполняться не будут, так как команда безадресная.

PUSHF

Код: 0D00.

Загружает значение регистра состояния на вершину стека.

Безадресная команда.

Цикл исполнения

  • 1 такт: PS -> DR

    • По фронту пустит значение регистра состояния через АЛУ.

    • По спаду запишет это значение в регистр данных.

  • 2 такт: ~0 + SP -> SP, AR

    • По фронту прибавит в АЛУ к значению указателя стека ~0 (то есть -1).
    • По спаду запишет это значение в указатель стека и адресный регистр.
  • 3 такт: DR -> MEM(AR)

    • По фронту найдёт ячейку по адресу.
    • По спаду запишет в эту ячейку значение регистра данных.

Не меняет флаги.

Циклы выборки адреса и выборки операнда выполняться не будут, так как команда безадресная.

SWAP

Код: 0E00.

Меняет местами значение аккумулятора и верхнее значение стека.

Безадресная команда.

Цикл исполнения

  • 1 такт: SP -> AR

    • По фронту пустит значение указателя стека через АЛУ.

    • По спаду запишет это значение в адресный регистр.

  • 2 такт: MEM(AR) -> DR

    • По фронту найдёт ячейку по адресу.

    • По спаду запишет значение этой ячейки в регистр данных.

  • 3 такт: DR -> BR

    • По фронту пустит значение регистра данных через АЛУ.

    • По спаду запишет это значение в буферный регистр.

  • 4 такт: AC -> DR

    • По фронту пустит значение аккумулятора через АЛУ.

    • По спаду запишет это значение в регистр данных.

  • 5 такт: BR -> AC; DR -> MEM(AR)

    • По фронту пустит значение буферного регистра через АЛУ, а также найдет ячейку по адресу.

    • По спаду запишет значение из АЛУ в аккумулятор, а также запишет значение регистра данных в ячейку памяти.

Ставит флаги по загруженному значению, не меняя флаг переноса и обнуляя флаг переполнения.

Циклы выборки адреса и выборки операнда выполняться не будут, так как команда безадресная.

CALL

Код: DXXX.

Вызывает подпрограмму по заданному адресу.

Адресная команда.

Цикл выборки адреса и цикл выборки операнда зависят от типа адресации.

Цикл исполнения

  • 1 такт: DR -> BR

    • По фронту пустит значение регистра данных через АЛУ.

    • По спаду запишет это значение в буферный регистр.

  • 2 такт: IP -> DR

    • По фронту пустит значение счетчика команд через АЛУ.

    • По спаду запишет это значение в регистр данных.

  • 3 такт: BR -> IP

    • По фронту пустит значение буферного регистра через АЛУ.

    • По спаду запишет это значение в счетчик команд.

  • 4 такт: ~0 + SP -> SP, AR

    • По фронту прибавит в АЛУ к значению указателя стека ~0 (то есть -1).

    • По спаду запишет это значение в указатель стека и адресный регистр.

  • 5 такт: DR -> MEM(AR)

    • По фронту найдёт ячейку по адресу.

    • По спаду запишет в эту ячейку значение регистра данных.

Не меняет флаги.

RET

Код: 0A00.

Прекращает выполнение подпрограммы.

Безадресная команда.

Цикл исполнения

  • 1 такт: SP -> AR

    • По фронту пустит значение указателя стека через АЛУ.

    • По спаду запишет это значение в адресный регистр.

  • 2 такт: MEM(AR) -> DR

    • По фронту найдёт ячейку по адресу.

    • По спаду запишет значение этой ячейки в регистр данных.

  • 3 такт: DR -> IP

    • По фронту пустит значение регистра данных в АЛУ.

    • По спаду запишет это значение в счетчик команд.

  • 4 такт: SP + 1 -> SP

    • По фронту пустит значение указателя стека в АЛУ и прибавит 1.

    • По спаду запишет полученное значение в указатель стека.

Не меняет флаги.

Циклы выборки адреса и выборки операнда выполняться не будут, так как команда безадресная.

IRET

Код: 0B00.

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

Безадресная команда.

Цикл выборки операнда

  • Цикл исполнения

  • 1 такт: SP -> AR

    • По фронту пустит значение указателя стека через АЛУ.

    • По спаду запишет это значение в адресный регистр.

  • 2 такт: MEM(AR) -> DR

    • По фронту найдёт ячейку по адресу.

    • По спаду запишет значение этой ячейки в регистр данных.

  • 3 такт: DR -> PS

    • По фронту пустит значение регистра данных в АЛУ.

    • По спаду запишет это значение в регистр состояния.

  • 4 такт: SP + 1 -> SP, AR

    • По фронту пустит значение указателя стека в АЛУ и прибавит 1.

    • По спаду запишет полученное значение в указатель стека и в адресный регистр.

  • 5 такт: MEM(AR) -> DR

    • По фронту найдёт ячейку по адресу.

    • По спаду запишет значение этой ячейки в регистр данных.

  • 6 такт: DR -> IP

    • По фронту пустит значение регистра данных в АЛУ.

    • По спаду запишет это значение в счетчик команд.

  • 7 такт: SP + 1 -> SP

    • По фронту пустит значение указателя стека в АЛУ и прибавит 1.

    • По спаду запишет полученное значение в указатель стека.

Флаги, соответственно, возьмутся из регистра состояния.

Циклы выборки адреса и выборки операнда выполняться не будут, так как команда безадресная.


Источники

Методические указания к предмету

Подсказка от моего друга и одногруппника

И конечно всеми любый гугл (вообще, яндекс поисковик, но это не важно).