Сложение с фиксированной запятой

Данный документ рассматривает использование среды ЯОЛС-М для моделирования устройств на примере реализации операции сложения с фиксированной запятой.

Структура

Для целей данного примера нам нужны два регистра, один из которых содержит первый операнд (и после операции будет содержать результат), а второй содержит сумируемое\вычитаемое значение.
Предположим, что наши числа с фиксированной запятой имеют 5 разрядов для целой части и 3 разряда для дробной части (предоставляя минимальную точность в виде 1/8, и общую длину в 8 бит).
Назовем их р0 и р1 соответственно:

объявить р0(8), р1(8)

Ввод

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

ввести р0, р1

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

печать "Введите р0, р1 (целая часть 5 бит, дробная часть 3 бита):"
ввести р0, р1

Вычисления

Сложение с фиксированной запятой программно ничем не отличается от обычного сложения, поэтому эта часть пока остается так же за одну строку:

р0 + р1

После, можно добавить вывод результата,

печать р0

Полный код на данный момент будет таким:

объявить р0(8), р1(8)
печать "Введите р0, р1 (целая часть 5 бит, дробная часть 3 бита):"
ввести р0, р1
р0 + р1
печать р0

В случае запуска, микропрограмма уже способна сложить два беззнаковых числа с фиксированной запятой. К примеру, 3.75 #00011110 + 1.5 #00001100 = 5.25 #00101010.

Знаки и биты

Для обработки знаков в данном случае можно использовать дополнительный код.
Ценой двух лишних битов в числах мы получаем однозначное представление знаков и возможность обработки переполнения, что так же является немаловажной деталью.
Добавление знаковых битов делается простым расширением обоих переменных до 10 бит,

объявить р0(10), р1(10)

И добавлением заметки об этом в запрос ввода, который можно, ради этого случая, разбить на две строки:

печать "Введите р0, р1:"
печать "(2 бита знака, целая часть 5 бит, дробная часть 3 бита)"

Так же нужно обрабатывать переполнение. Переполнение в дополнительном коде определяется комбинациями знаковых разрядов 01 / 10, что можно было бы сделать двумя условиями,

если р0(9:8) = #01 конец "Переполнение!"
если р0(9:8) = #10 конец "Переполнение!"

Или же упростить до одного условия по несовпадению значений разрядов:

если р0(8) <> р0(9) конец "Переполнение!"

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

если р0(8) = 0 идти_к 1
р0(7:0)~~
р0 + 1
1:

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

если р0(9:8) <> #11 идти_к 2
р0(7:0)~~
р0 + 1
2:

Таким образом, после модификаций, код будет выглядеть следующим образом:

объявить р0(10), р1(10)
печать "Введите р0, р1:"
печать "(2 бита знака, целая часть 5 бит, дробная часть 3 бита)"
ввести р0, р1
если р0(9:8) <> #11 идти_к 2
р0(7:0)~~
р0 + 1
2: если р1(9:8) <> #11 идти_к 3
р1(7:0)~~
р1 + 1
3: р0 + р1
если р0(8) <> р0(9) конец "Переполнение!"
если р0(8) = 0 идти_к 1
р0(7:0)~~
р0 + 1
1: печать р0

И работать полностью корректно - так, -3.25 #1100011010 + 1.5 #0000001100 = -1.75 #1100001110.