- Главный принцип - команды не имеют операндов в коде. Все данные неявно берутся с веришны стека, результат кладется обратно в стек.
- Небольшая пасхалка на [[Evaluate Reverse Polish Notation|вот эту задачу с литкода]]
## Регистры, флаги и стеки
- Имеет два независимых аппаратных стека и два регистра-указателя
### Стеки
-`Data Stack` - место где происходят вычисления
-`T` - вершина стека данных
-`S` - второй элемент на стеке данных
-`Return Stack` - стек возврата
-`R` - вершина стека возвратов
### Регистры
-`A` - указатель адреса памяти с поддержкой автоинкремента
-`B` - второй указатель памяти
### Флаги
-`C` - перенос
-`EAM` - режим расширенной арифметики
> [!info] Все регистры, флаги и стеки можно выводить в отчете: `A:dec`, `stack:dec`, `rstack:hex`, `C`, `EAM` и так далее
> [!info] Получение максимальной глубины стека, которая была достигнута на конкретном шаге через: `f32a:data-stack-max` и `f32a:return-stack-max`
## Система команд
- Комментарии - `\`
- Опкод - 1 байт. Если есть операнд, то еще 4 байта
### 1. Операции со стеком
-`dup` - дублировать вершину (`[X] -> [X, X`])
-`drop` - удалить вершину (`[X, Y] -> [X]`)
-`over` - скопировать второй элемент наверх (`[X, Y] -> [X, Y, X]`)
### 2. Операции над памятью
-`<value>` (или `lit <value>`) - положить константу на `Data Stack` (от слова literal)
-`a!` / `b!` - снять значение со стека и записать в регистр `A` / `B`
-`a` - скопировать значение из регистра `A` на стек
-`@p <addr>` - прочитать из адреса на стек
-`!p <addr>` - снять со стека и записать по адресу
-`@` / `!` - чтение/запись по адресу, который лежит в регистре `A`
-`@+` / `!+` - чтеение/запись по адресу в `A` и инкремент `A`
-`@b` / `!b` - чтение/запись по адресу, который лежит в регистре `B`
### 3. Арифметика
-`+` - сумма, снимает два верхних числа, складывает, кладет на вершину стека. Если в режиме `EAM`, то прибавляет еще и флаг переноса. Устанавливает флаг переноса в любом случае
-`+*` - один шаг умножения
-`+/` - один шаг деления
-`2*` - сдвиг влево вершины стека
-`2/` - сдвиг вправо вершины стека
-`inv` - побитовая инверсия вершины стека
-`eam` - снять число с`Data Stack` и записать его в `EAM`
### 4. Побитовые операции
-`and` - побитовое И над `T` и `S` (снимает их)
-`xor` - исключающее ИЛИ
### 5. Управление вычислительным процессом
-`;` - возврат из подпрограммы (снять адрес с `Return Stack` и прыгнуть)
-`<label> ;` - прыжок (без записи адреса возврата)
-`next <label>` - цикл for, проверяет вершину стека возврата `R`, если `R != 0`, уменьшает его на 1 и прыгает на метку. Если `R==0`, удаляет `R` и выходит из цикла
-`if <label>` - снимает значение с `Data Stack`, если оно ноль, то прыжок
-`-if <label>` - снимает значение с `Data Stack`, если оно `>=0`. то прыгает
-`halt` - стоп
### 6. Взаимодействие со стеком возврата
-`r>` - снять элемент с`Return Stack` и положить на `Data Stack`
-`>r` - снять элемент с`Data Stack` и положить на `Return Stack`
## Подробнее про умножение и деление
### `+*`
- Как работает умноежение чисел в двоичной системе (`A*S`): смотрим на каждый бит числа A, если бит 1, то прибавляем S к результату, если бит 0, то пропускаем, в конце сдвигаем результат
- Как использует эта команда данные
1. Регистр `A` - множитель
2.`S` (второй элемент стека данных) - множимое
3.`T` (первый элемент стека данных) - накапливается ответ, сначала 0
- Теперь эта команда по шагам
1. Процессор смотрит на младший бит `A`
2. Если там `1`, то прибавляет `S` к `T` (`T = T + S`). Если `0` - ничего не прибавляет
3. Сдвигает регистр `A` вправо на 1 бит (`A >> 1`). Тот бит, который мы только что проверили выбрасывается
4. Сдвигает результат `T` вправо на 1 бит (`T >> 1`)
5. Сдвинутый из `T` бит вставляется в старший бит `A` (`A[31]`)
- После 32 повторений такой команды, в регистре `A` и на вершине стека `T` образуется 64-битное число - полный результат умножения. В `A` - младшая половина ответа, а в `T` - старшая
### `+/`
- Деление в двоичной системе: сдвигаем влево и пытаемся вычесть делитель. Если вычитается - пишем 1, если нет - 0
- Как использует данные команда
1. Регистр `A` - делимое
2.`Mem[B]` - делитель
3.`S` - старшая часть числа, здесь будет остаток
4.`T` - кладем 0, здесь будет частное
- Команда по шагам
1. Сдвигаем остаток `S` влево на 1 бит
2. Забираем старший бит из `A` и вставляем в младший бит `S`
3. Сдвигаем `A` влево
4. Сдвигаем `T` влево
5. Если можно вычесть делитель (`S >= Mem[B]`), то ставим в младший бит ответа единицу (`T[0]=1`), если нельзя - бит ответа оставляем нулем
- После 32 повторений на стеке в `T` будет лежать частное, в `S` - остаток от деления.
[[Computer Science]] - лекции и материалы по АК+ОПД+PL и в целом база по CS
[[Computer Science]] - лекции и материалы по АК+ОПД+PL и в целом база по CS
[[Экзамен]] - разбор экзамена по ОПД за 2 семестр
[[Экзамен]] - разбор экзамена по ОПД за 2 семестр
Spring Boot - будет...
Spring Boot - будет...
[[README]] - заметки [LeterZP](https://gitea.aklivtsov.tech/LeterZP) (aka Boris Bosenkob)
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.