7.4 KiB
7.4 KiB
- 32-битная стековая архитектура
- Главный принцип - команды не имеют операндов в коде. Все данные неявно берутся с веришны стека, результат кладется обратно в стек.
- Небольшая пасхалка на 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>- вызов подпрограммы (адрес возврата кладется на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, то пропускаем, в конце сдвигаем результат - Как использует эта команда данные
- Регистр
A- множитель S(второй элемент стека данных) - множимоеT(первый элемент стека данных) - накапливается ответ, сначала 0
- Регистр
- Теперь эта команда по шагам
- Процессор смотрит на младший бит
A - Если там
1, то прибавляетSкT(T = T + S). Если0- ничего не прибавляет - Сдвигает регистр
Aвправо на 1 бит (A >> 1). Тот бит, который мы только что проверили выбрасывается - Сдвигает результат
Tвправо на 1 бит (T >> 1) - Сдвинутый из
Tбит вставляется в старший битA(A[31])
- Процессор смотрит на младший бит
- После 32 повторений такой команды, в регистре
Aи на вершине стекаTобразуется 64-битное число - полный результат умножения. ВA- младшая половина ответа, а вT- старшая
+/
- Деление в двоичной системе: сдвигаем влево и пытаемся вычесть делитель. Если вычитается - пишем 1, если нет - 0
- Как использует данные команда
- Регистр
A- делимое Mem[B]- делительS- старшая часть числа, здесь будет остатокT- кладем 0, здесь будет частное
- Регистр
- Команда по шагам
- Сдвигаем остаток
Sвлево на 1 бит - Забираем старший бит из
Aи вставляем в младший битS - Сдвигаем
Aвлево - Сдвигаем
Tвлево - Если можно вычесть делитель (
S >= Mem[B]), то ставим в младший бит ответа единицу (T[0]=1), если нельзя - бит ответа оставляем нулем
- Сдвигаем остаток
- После 32 повторений на стеке в
Tбудет лежать частное, вS- остаток от деления.