Модельные ЭВМ

Трёхадресная ЭВМ

«Классические» операции вида «из A вычесть B, поместить результат в C» работают с тремя элементами данных — уменьшаемым, вычитаемым и разностью. В трёхадресной ЭВМ эта операция выполняется одной командой.

Оперативная память

Представим в виде шестнадцатеричного числа: ККУУУУВВВВРРРР, где

  1. КК — код операции

  2. УУУУ — адрес первого операнда

  3. ВВВВ — адрес второго операнда

  4. РРРР — адрес результата

Например, 0110AE10AF10B0 (01 10AE 10AF 10B0) означает «прибавить содержимое ячейки 10AE к содержимому ячейки 10AF и записать результат в 10B0».

Все коды операция см. в учебном пособии Модельные ЭВМ¹ и на сайте эмуляторов УМ.

FrBrGeorge/MyDict/speech_balloon_question.png Вопрос для обсуждения: почему ячейка такая большая?

Регистры

Устройства ввода-вывода и хранения

Не обязательны, если предоставить возможность заполнять ОЗУ и читать оттуда.

Такт работы учебной машины

  1. Чтение в РК команды из памяти по адресу, находящемуся в СК
  2. Интерпретация команды в РК (для УМ-3 это просто)
  3. Чтение операндов из памяти (от 0 до 2)
  4. Вычисление результата (если необходимо)
    • Заполнение регистра флагов (если необходимо)
  5. Запись результата в память (от 0 до 1)
  6. Вычисление адреса следующей команды в СК

Пример: 01 10AE 10AF 10B0

TODO: нарисовать 6-7 состояний

Представление целых чисел

(вообще-то — школьная информатика)

Двоичные целые без знака: 256-1

Двоичное сложение в столбик

Разбор примера

 11010100
+01100101
 --------
100111001

Проблема переноса — решать ли её?

Предположим, в примере выше для хранения числа используется байт (8 битов). Что делать с девятым, который появился в результате сложения?

Варианты решения:

  1. запомнить, что был перенос единицы, в специальном бите регистра флагов (CF, carrier flag — флаг переноса),
  2. добавить перенос в дополнительную «старшую» ячейку,
  3. объявить нештатную ситуацию и остановить выполнение программы,
  4. забыть про то, что перенос вообще был.

В УМ-3 используется решение №1.

Представление отрицательных чисел

В виде знака и следующего за ним положительного целого числа

Дополнительный код как вычитание из 0 с переполнением:

Формула отрицательного числа в дополнительном коде: -N = ~(N-1), где «~» — операция дополнения (замены битов на противоположные)

В таком представлении можно складывать и вычитать числа с произвольным знаком (FrBrGeorge/MyDict/speech_balloon_question.png проверьте, точно ли это работает для двух отрицательных чисел?).

Более того, одно и то же число со старшим битом, равным 1, может считаться отрицательным в диапазоне -1 … -255, а может — положительным в диапазоне 255 … 256-1, операции сложения и вычитания будут работать над ними совершенно одинаково.

Когда при сложении двух чисел с одинаковым знаком сумма меняет знак, значит, модуль суммы был слишком велик, и результат «налез» на знаковый бит. В этом случае в регистре флагов взводится флаг переполнения (OF, overfuul flag), и если кому-то захотелось считать числа знаковыми, он должен проверить этот флаг.

FrBrGeorge/MyDict/speech_balloon_question.png Может ли так случиться, что в описанной ситуации переполнение произойдёт (полученное число не уместится в диапазон целых), но знаковый бит не изменится?

FrBrGeorge/MyDict/speech_balloon_question.png Сформулируйте аналогичное правило для вычитания.

Умножение и деление целых

Таблица умножения на 1 + умножение в столбик:

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

Деление в столбик — последовательно вычитаем (соответствующий бит частного равен 1) или не вычитаем (=0) делительn, в зависимости от того, больше или меньше это число текущей разности.

Различие беззнаковых и знаковых умножения и деления принципиально:

FrBrGeorge/MyDict/speech_balloon_question.png : Насколько отличается алгоритм умножения беззнаковых и знаковых целых?

Базовые операции трёхадресной УМ-3

Полная таблица команд: «Система команд модельных машин»

Базовые операции (в УМ-3 три поля адреса — ОП1, ОП2 и РЕЗ)

Код операции

Обозначение

Значение

0x00

mov ОП1 РЕЗ

Скопировать ОП1 в РЕЗ

0x01

add ОП1 ОП2 РЕЗ

Сложить ОП1 и ОП2, результат поместить в РЕЗ

0x02

sub ОП1 ОП2 РЕЗ

Вычесть ОП2 из ОП1, результат поместить в РЕЗ

0x03

smul ОП1 ОП2 РЕЗ

Умножить целое ОП1 на целое ОП2, результат поместить в РЕЗ0

0x04

sdiv ОП1 ОП2 РЕЗ

Разделить целое ОП1 на целое ОП2, результат поместить в РЕЗ

0x13

umul ОП1 ОП2 РЕЗ

Умножить беззнаковое целое ОП1 на беззнаковое целое ОП2, результат поместить в РЕЗ0

0x14

udiv ОП1 ОП2 РЕЗ

Разделить беззнаковое целое ОП1 на беззнаковое целое ОП2, результат поместить в РЕЗ

0x99

halt

Остановить работу УМ

Установка эмулятора модельных машин на персональный компьютер

Базовая статья — сайт modelmachine.

Эмуляторы учебных машин написаны на Python3, оформлены в виде модуля и доступны в PyPi.

Эмулятор выполнен как интерпретатор командной строки. Вся работа по установке и и использованию эмулятора также идёт из командной строки.

Проверка работоспособности модуля

Особенности эмулятора:

Обрабатывается так называемый «образ»: текстовый файл, в котором:

При запуске эмулятора в память загружается содержимое, ячейки, перечисленные для ввода, заполняются заданными (или введёнными с клавиатуры) значениями, после чего программа начинает выполнение с адреса 0.

Работа с эмулятором

Формат файла-программы

Пример: сложение двух чисел. Программа add.mmach

Другие примеры

Запуск программы

$ python3 -m modelmachine run add.mmach
4466

Поддерживается пошаговое выполнение программы и просмотр памяти/регистров во время пошагового выполнения.

Рассмотрим более сложную программу discr.mmach, вычисляющую b2-4*a*c, где a, b и c — произвольные числа. Для простоты константу 4 также будем вводить.

.cpu mm-3
; a,b,c и d разместим по адресам 010a, 010b, 010c и 010d
; константу 4 (по адресу 0104) не будем задавать как константу, а тоже введём
.input 0x010a,0x010b,0x010c,0x0104
.output 0x010d

.code
03 010b 010b 0100 ; b*b (умножение со знаком), результат в ячейке 0100
03 010a 010c 0101 ; a*c, результат в 0101
03 0101 0104 0101 ; ac*4, результат в 0101
02 0100 0101 010d ; b²-4ac
99 0000 0000 0000

.enter 5 8 3 4

Обратите внимание: никаких имён в кодах нет, использование a,b,c и d стало возможным только по совпадению.

Используется умножение со знаком (код операции 03). Также обратите внимание на команду 03 0101 0104 0101, в которой результат записывается в одну из ячеек-операндов, то есть одна и та же ячейка выступает в качестве источника и приёмника одновременно.

FrBrGeorge/MyDict/speech_balloon_question.png Почему это возможно?

Отладка программы

В эмулятор modelmachine встроен простой, но достаточно удобный отладчик. Загрузим в него пример с дискриминантом:

Выполним команду step (выполнение одной команды и останов):

Поставим точку останова (breakpoint) по адресу 0x0003, и продолжим выполнение программы с помощью continue:

Посмотрим содержимое памяти:

Продолжим работу:

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

LecturesCMC/ArchitectureAssemblerProject/01_ModelMachines (последним исправлял пользователь FrBrGeorge 2024-08-29 23:03:33)