- Барсуков Максим Андреевич, P3215
- Вариант:
alg -> asm | stack | harv | hw | tick -> instr | struct | stream | port | pstr | prob2 | cache
- Упрощённый вариант:
asm | stack | harv | hw | instr | struct | stream | port | pstr | prob2
Расширенная форма Бэкуса —Наура:
<program> ::= <section_data> <section_text> | <section_text> <section_data> | <section_text>
<section_data> ::= ".data\n" <declaration>*
<section_text> ::= ".text\n" (<label_def> | <instruction> | <label_def> <instruction>)*
<declaration> ::= <label_def> (<array> | <reserve>)
<instruction> ::= <label_arg_command> | <number_arg_command> | <without_arg_command>
<label_def> ::= (<name> ":" (" ")*) | (<name> ":" (" ")* "\n")
<array> ::= (<array_element> "," (" ")*)* <array_element>+
<reserve> ::= "res" (" ")+ <number>
<array_element> ::= ("\"" <any_ascii> "\"" | <number>)
<label_arg_command> ::= ("push" | "jump" | "jz" | "jnz" | "js" | "jns" | "call") (" ")+ <name>
<number_arg_command> ::= ("push" | "input" | "output") (" ")+ <number>
<without_arg_command> ::= ("nop" | "halt" | "add" | "sub" | "mul" | "div" | "mod"
| "cmp" | "and" | "or" | "xor" | "inc" | "dec" | "neg" | "not" | "ret" | "pop"
| "swap" | "dup" | "over" | "over3" | "load" | "store" | "debug")
<number> ::= [-2^31; 2^31 - 1]
<name> ::= (<letter_or_>)+
<letter_or_> ::= <letter> | ("_")
<letter> ::= [a-z] | [A-Z]
.text
-- секция, в которой все последующие слова (до конца файла или объявления.data
) интерпретируются, как инструкции или их аргументы или комментарии или метки;.data
-- секция, в которой все последующие слова (до конца файла или объявления.data
) интерпретируются как инициализация или резервация сегментов памяти для пользовательских данных;label
-- метка, которая является указателем на адрес памяти инструкции за ней (если метка в section.text
) или является указателем на первый элемент зарезервированого сегмента памяти (если метка в section.data
);res n
-- оператор, который может писаться после объявления метки в секции данных, обозначающий, что необходимо зарезервироватьn
слов памяти под эту метку;push n
-- кладет значениеn
на вершину стэка. Еслиn
- метка, то кладет адрес, который она описывает, еслиn
- число, то кладет само значениеn
. ВАЖНО: так как у меня гарвардская архитектура,push label
я могу выполнять только для label из Data Memory;pop
-- удаляет верхний элемент со стэка;jump label
-- команда безусловного перехода. Устанавливает следующую команду, как ту, на которую указывает label - из Program Memory;jz label
-- если на вершине стэка 0, то выполняетjump
, иначе переход к следующей команде;jnz label
-- если на вершине стэка не 0, то выполняетjump
, иначе переход к следующей команде;js label
-- если на вершине стэка отрицательное число, то выполняетjump
, иначе переход к следующей команде;jns label
-- если на вершине стэка не отрицательное число, то выполняетjump
, иначе переход к следующей команде;call label
-- сохраняет на стэке вызывов адрес следующей команды и переходит к выполнению инструкции за label;ret
-- устанавливает следующую команду, как ту, что лежит на верху стэка вызовов и удаляет элемент с верхушки стэка вызовов;input n
-- считывает один символ из порта n и записывает его на верх стэка;output n
-- записывает в порт n значение из верхушки стэка;halt
-- завершение программы;add
-- складывает значение на вершине стэка и значение следующее после вершины стэка, результат помещает на вершину стэка, операнды убираются со стэка;sub
-- вычитает значение на вершине стэка и значение следующее после вершины стэка, результат помещает на вершину стэка, операнды убираются со стэка;mul
-- перемножает значение на вершине стэка и значение следующее после вершины стэка, результат помещает на вершину стэка, операнды убираются со стэка;div
-- делит значение на вершине стэка и значение следующее после вершины стэка нацело, результат помещает на вершину стэка, операнды убираются со стэка;mod
-- берёт остаток от деления значения на вершине стэка на значение следующего после вершины стэка, результат помещает на вершину стэка, операнды убираются со стэка;cmp
-- вычитает значение на вершине стэка и значение следующее после вершины стэка, результат помещает на вершину стэка, операнды НЕ убираются со стэка;and
-- битовое И значения на вершине стэка и значения следующего после вершины стэка, результат помещает на вершину стэка, операнды убираются со стэка;or
-- битовое ИЛИ значения на вершине стэка и значения следующего после вершины стэка, результат помещает на вершину стэка, операнды убираются со стэка;xor
-- битовое исключающее ИЛИ значения на вершине стэка и значения следующего после вершины стэка, результат помещает на вершину стэка, операнды убираются со стэка;not
-- битовое НЕ значения на вершине стэка;swap
-- меняет местами значение на вершине стэка и значение следующее после вершины стэка;dup
-- кладёт на вершину стэка значение с вершине стэка;over
-- кладёт на вершину стэка значение следующее после вершины стэка;over3
-- кладёт на вершину стэка значение следующее после значения, следующего после вершины стэка;inc
-- увеличивает значение верхушки стэка на 1;dec
-- уменьшает значение верхушки стэка на 1;neg
-- устанавливает значение верхушки стэка на отрицательное (* (-1));load
-- интерпретирует значение на вершине стэка, как адрес по которому из памяти загружает значение на вершину стэка.store
-- интерпретирует значение следующее после вершины стэка, как адрес по которому нужно записать значение на вершине стэка.debug
-- команда отладки. Вывод в устройство ввода-вывода 1 отладочную информацию о текущем значении процессора и останавливает программу до нажатия пользователем любой клавиши.nop
-- пустая команда. Совершается тик, переходят к следующей инструкции.
Начинаются со знака ;
и идут до конца строки.
-
В программе не может быть дублирующихся меток.
-
Метка памяти данных задается на той же строке, что и данные:
hello_world: "Hello, world!"
-
Так как строки Pascal-string, компилятор сам упаковывает их во время компиляции (ставит первым словом строки длину строки).
-
Метка памяти команд задается на строке предшествующей инструкции, на которую указывает метка, либо на той же самой строке:
foo:
push 10
...
bar: nop
...
Программа выполняется последовательно, одна инструкция за другой.
- Распределяется статически на этапе трансляции
- Строковые литералы помещаются в память в начале работы программы в формате Pascal-string.
- Под динамически считываемые строки пользователь сам определяет, как будет считываться строка. Он может выделить некоторый буфер через
res n
, или расположить строку в конце памяти и считывать сколько необходимо (или пока хватает памяти).
В любом месте секции .text
доступен стэк и операции над его верхними значениями. Видимость меток глобальная.
Литералы могут быть представлены в виде чисел и меток (в последствии интерпретируются как числа), в секции .data
можно объявлять строки. Типизация отсутсвует, так как пользователь языка может интерпретировать любые данные как захочет и может с ними выполнить любые из возможных операций.
- Гарвардская архитектура
- Резмер машинного слова:
- Память данных - 32 бит;
- Память команд - 32 бит.
- Имеет линейное адресное пространство.
- В памяти данных хранятся статические строки и переменных
- В памяти команд хранятся инструкции для выполнения
- Взаимодействие с памятью данных происходит при помощи инструкций
load
иstore
. - Адресации:
- Прямая абсолютная (например,
push label
) - Косвенная (у команд
load
,store
один из операндов является указателем на ячейку памяти)
- Прямая абсолютная (например,
Program memory
+------------------------------+
| 00 : jump n |
| ... |
| n : _start: instruction1 |
| ... |
+------------------------------+
Data memory
+------------------------------+
| 00 : array 1 |
| ... |
| n : array 2 |
| ... |
+------------------------------+
- Для работы с регистрами отведена память, организованная в виде стека. Программист напрямую имеет доступ к
TOS
, верхушкеStack Registers
, заранее инициализированной памяти вData Memory
, а также, используя различные условные и безусловный переходы, может изменятьPC
; - Память данных разделена на массивы - разделение определяет пользователь, именуя каждый массив лейблом;
- Массив может состоять из строк, чисел и свободного места (заполнено нулями), зарезервированного на определенное количество байт. Все данные в массивах и все массивы идут последовательно;
- Инструкции хранятся в
Program Memory
; - Для операндов пользователю отводится 24 бита, т.к. предполагается, что оставшиеся 8 бит будет занимать информация о инструкции (например опкод);
- Используя команду
push number
литерал используется при помощи непосредственной адресации; - Используя команду
store
литерал будет загружен в статическую память;
- Имеются стек данных и стек возвратов.
- Оба поддерживают операции
push
иpop
- Стек данных поддерживает операции
dup
иswap
, а также чтение из второй от вершины ячейки (предполагается реализация на уровне схемотехники).
Регистры:
- PC - счетчик команд
- AR - регистр адреса
Особенности процессора:
- Машинное слово -- знаковое 32-ух битное число;
- Доступ памяти осуществляется через указатель на вершине
Stack Register
. Установить можно при помощиpush label
; - Устройство ввода-вывод: port-mapped
- Поток управления:
- Инкрементирование
PC
; - Условный/безусловный переход;
- Адрес из вершины
Call Stack
.
- Инкрементирование
Команда | Число тактов | Стек ДО | Стек ПОСЛЕ | Описание | ||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
PUSH [value] | 1 |
|
|
пушит на вершину стека свой аргумент, выставляет флаги N (negative) и Z (zero) для верхушки стека |
||||||||
PUSH [label] | 1 |
|
|
пушит на вершину стека свой адрес своего аргумента, выставляет флаги N (negative) и Z (zero) для верхушки стека |
||||||||
LOAD | 2 |
|
|
загружает значение из памяти, адрес берется из вершины стека, выставляет флаги N (negative) и Z (zero) для верхушки стека |
||||||||
STORE | 2 |
|
|
сохраняет значение из вершины стека, адрес берется из второй ячейки | ||||||||
POP | 1 |
|
|
удаляет вершину стека, выставляет флаги N (negative) и Z (zero) для верхушки стека |
||||||||
ADD SUB MUL DIV MOD AND OR XOR MOD MOD MOD |
1 |
|
|
выполняет арифметическую операцию, выставляет флаги N (negative) и Z (zero) для верхушки стека |
||||||||
CMP | 1 |
|
|
выполняет a - b, сохраняет операнды, выставляет флаги N (negative) и Z (zero) для верхушки стека |
||||||||
INC DEC |
1 |
|
|
выполняет инкремент или декремент, выставляет флаги N (negative) и Z (zero) для верхушки стека |
||||||||
INPUT [port] | 1 |
|
|
читает из устройства ввода-вывода с порта один символ, выставляет флаги N (negative) и Z (zero) для верхушки стека |
||||||||
OUTPUT [port] | 1 |
|
|
записывает вершину стека в порт | ||||||||
DUP | 1 |
|
|
дублирует значение с вершины стека | ||||||||
SWAP | 1 |
|
|
меняет местами верхние 2 значения в стеке, выставляет флаги N (negative) и Z (zero) для верхушки стека |
||||||||
OVER | 1 |
|
|
кладёт на вершину стэка значение следующее после вершины стэка, выставляет флаги N (negative) и Z (zero) для верхушки стека |
||||||||
OVER3 | 1 |
|
|
кладёт на вершину стэка значение второе после вершины стэка, выставляет флаги N (negative) и Z (zero) для верхушки стека |
||||||||
JUMP [addr] JZ [addr] JNZ [addr] JS [addr] JNS [addr] |
1 | - | - | прыжок на инструкцию на основании выставленных флагов. JUMP - безусловный, JZ - прыжок, если ноль, JNZ - прыжок, если не ноль, JS /JNS - прыжок, если отрицательное/не отрицательное |
||||||||
CALL [addr] | 1 | - | - | вызов функции по адресу addr | ||||||||
RET | 1 | - | - | возврат из функции | ||||||||
DEBUG | 1 | - | - | вывод отладочной информации на устройство на порту 1, остановка программы до действий пользователя | ||||||||
NOP | 1 | - | - | пустая инструкция | ||||||||
HALT | 1 | - | - | остановить выполнение |
Инструкции представлены в формате JSON:
{
"opcode": "jump",
"operand": 123,
"address": 10
}
где:
opcode
- код операции (Opcode - тип данных, определенный в isa)operand
- аргумент инструкцииaddress
- указывает адрес инструкции в памяти инструкций.
Реализация транслятора: translator
Интерфейс командной строки:
- Получить справку:
poetry run translator --help
usage: translator [-h] source_file target_instrs_file target_data_file
CSA Lab 3 translator.
positional arguments:
source_file File with asm code
target_instrs_file File to write instructions after compilation
target_data_file File to write data after compilation
options:
-h, --help show this help message and exit
poetry run translator [-h] <source_file> <target_instrs_file> <target_data_file>
- Первый аргумент - путь до файла с исходным кодом,
- второй аргумент - путь до файла, куда будут записаны инструкции, сохраненные в
json
. - третий аргумент - путь до файла, куда будут записаны массивы данных, инициализированные в пользовательской программе, сохраненные в
json
.
Трансляция секции .data
:
- Реализована в
get_data
; - Сначала определяется место в коде, где объявлена секция
.data
; - Потом лейбл отделяется от данных;
- В
get_codes_from_data
данные преобразуются в последовательность чисел:- Функция
str2list_int
возвращает массив, в котором строка представляется как массив байт, на позициях одиночных чисел и резервирования - пустые массивы; - Функция
get_integers
удалят из данных строки, возвращает массив одиночных чисел и резервированной памяти; - Далее на пустые места вставляются одиночные числа и массивы резервирования;
- В конце все данные выпрямляются в один итоговый массив.
- Функция
Трансляция секции .text
:
translate_without_operands
: инструкции разбиваются на токены, запоминаются номера меток. Возвращается высокоуровневая структура, описывающая инструкции;translate_operands
: в джампы подставляются номера инструкций в зависимости от лейбла, вpush label
заменяются метки на адреса в памяти, проверяются ограничения на аргументы;- Код из высокоурвневой структуры переводится в бинарный вид в функции
write_code
, определенной вisa
Правила:
- Не более одного определения секций
.data
и.text
- Одиночные числа, объявленные в
.data
должны принимать значения [-2^31; 2^31 - 1]; - Метка в секции
.data
задается на той же строке, что и данные. Данные задаются на одной строке; - Метка в секции
.text
задается перед инструкцией, на которую он указывает; - Обязательна метка
_start
;
Реализация модели процессора: machne
Интерфейс командной строки:
- Получить справку:
poetry run machine --help
usage: machine [-h] [--log_level {FATAL,ERROR,WARN,INFO,DEBUG,NOTSET,}] [--output_ports {1,2,1;2}] instructions_file data_file input_file
CSA Lab 3 machine runner.
positional arguments:
instructions_file File with instructions
data_file File with data
input_file File with user input
options:
-h, --help show this help message and exit
--log_level {FATAL,ERROR,WARN,INFO,DEBUG,NOTSET}
Log level
--output_ports {1,2,1;2}
IO ports to print output
- Первый аргумент - путь до файла с инструкциями,
- Второй аргумент - путь до файла с данными.
- Третий аргумент - путь до файла, откуда берется ввод пользователя.
- Опция
--log_level
- позволяет установить уровень логирования. - Опция
--output_ports
- позволяет выбрать, с каких устройств ввода-вывода по портам данные будут также выводиться в терминал при запуске.
Разработаны IOController
, который на основании порта [0-15] использует устройство ввода-вывода. Сделано несколько устройств ввода-вывода (реализация в io.py):
IO0
: ввод данных посимвольно из stdin (реализация через файл<input_file>
). Если данные закончились, отдает EOF (-1). Использование:INPUT 0
IO1
: вывод ячейки в stdout как символа (для значения 97 выведетa
). Использование:OUTPUT 1
IO2
: вывод ячейки в stdout как числа (для значения 97 выведет97
). Использование:OUTPUT 1
IO8
: ввод данных из бесконечного потока символов'1', ..., '9', '0', '1', ...
. Читает по одному символу из этого потока. Использование:INPUT 8
Реализован в data_path
Сигналы (обрабатываются за один такт, реализованы в виде методов класса)
latch_data_addr
- защёлкнуть значение в data_addrlatch_tos
- защёлкнуть вершину стекаstore
/load
- сигналы записи / чтения памяти данныхoperation
- сигнал, определяющий операцию алуread
/write
/port
- сигналы чтения / записи / порта устройства ввода вывода
Флаги:
Z
- zero - отражает нулевое значение в вершине стекаN
- negative - отражает отрицательное значение в вершине стека
Реализован в control_unit
- hardwired - внутренняя логика дешифратора инструкций скрыта. В данной модели реализована на Python.
- Метод
decode_and_execute_instruction
моделирует выполнение полного цикла инструкции. _tick
- имитирует работу счетчика тактов.
Сигналы:
latch_pc
- защелкнуть значение в program_counterread
- чтение из памяти инструкций
Особенности работы модели:
- Цикл симуляции осуществляется в функции
simulation
. - Шаг моделирования соответствует одной инструкции с выводом состояния в журнал.
- Для журнала состояний процессора используется стандартный модуль
logging
. - Остановка модели осуществляется при следующих условиях:
- достижение инструкции halt;
- переполнение стека или чтение из пустого стека;
- отсутствие данных для чтения из порта ввода;
- чтение или запись в несуществующий адрес памяти.
- Модель может быть остановлена и возобновлена командой
debug
.
Тестирование выполняется при помощи golden test-ов.
- Конфигурация лежит в директории tests
GitHub Actions при совершении push
-а автоматически
- запускает golden-тесты (задание
test
) - проверяет форматирование Python и запускает линтеры (
ruff
) - проверяет форматирование Markdown (
markdownlint
)
Конфигурация для GitHub Actions находится в файлах python.yml и markdown.yml
Golden-тесты:
❯ poetry run coverage run -m pytest . -v
============================================================================================ test session starts ============================================================================================
platform linux -- Python 3.12.2, pytest-7.4.4, pluggy-1.5.0 -- /home/max/.cache/pypoetry/virtualenvs/csa3-stack-machine-Mqil_AOd-py3.12/bin/python
cachedir: .pytest_cache
rootdir: /home/max/prog/itmo/csa3-stack-machine
configfile: pyproject.toml
plugins: golden-0.2.2
collected 6 items
tests/golden_test.py::test_translator_and_machine[golden/prob2.yml] PASSED [ 16%]
tests/golden_test.py::test_translator_and_machine[golden/0_to_9.yml] PASSED [ 33%]
tests/golden_test.py::test_translator_and_machine[golden/cat.yml] PASSED [ 50%]
tests/golden_test.py::test_translator_and_machine[golden/hello_username.yml] PASSED [ 66%]
tests/golden_test.py::test_translator_and_machine[golden/hello_world.yml] PASSED [ 83%]
tests/golden_test.py::test_translator_and_machine[golden/string_utils.yml] PASSED [100%]
============================================================================================= 6 passed in 1.62s =============================================================================================
Покрытие:
❯ poetry run coverage report -m
Name Stmts Miss Cover Missing
-------------------------------------------------------------------------
src/__init__.py 0 0 100%
src/constants.py 9 0 100%
src/isa/__init__.py 6 0 100%
src/isa/data.py 16 0 100%
src/isa/dump.py 16 0 100%
src/isa/instruction.py 18 1 94% 23
src/isa/json_utils.py 15 0 100%
src/isa/memory.py 33 0 100%
src/isa/opcode.py 48 2 96% 56, 64
src/machine/__init__.py 0 0 100%
src/machine/components/__init__.py 0 0 100%
src/machine/components/alu.py 27 2 93% 50, 52
src/machine/components/call_stack.py 18 0 100%
src/machine/components/data_stack.py 48 2 96% 35-36
src/machine/components/io.py 80 8 90% 11, 15, 29, 58, 69, 86, 109, 123
src/machine/components/memory.py 20 1 95% 21
src/machine/control_unit.py 89 3 97% 114-117
src/machine/data_path.py 41 0 100%
src/machine/main.py 44 25 43% 35-45, 49-53, 57-77, 81
src/machine/simulation.py 41 3 93% 24, 26, 31
src/main.py 8 3 62% 9-11
src/translator/__init__.py 3 0 100%
src/translator/data_translator.py 82 4 95% 15-16, 104-105
src/translator/instructions_translator.py 69 2 97% 21, 35
src/translator/main.py 34 7 79% 50-57, 61
src/translator/utils.py 15 0 100%
tests/__init__.py 0 0 100%
tests/golden_test.py 32 0 100%
-------------------------------------------------------------------------
TOTAL 812 63 92%
Алгоритмы согласно варианту:
Дополнительные алгоритмы:
- string_utils - набор функций для удобной работы со строками.
- 0_to_9.yml - демонстрация работы IO8.
Исходный код:
.data
hello_str: "Hello, world!"
.text
_start:
push hello_str
load
cycle:
jz ext
swap
inc
load
output 1
pop
swap
dec
jmp cycle
pop
pop
halt
Машинный код:
[
{"address": 0, "opcode": "jmp", "operand": 1},
{"address": 1, "opcode": "push", "operand": 0},
{"address": 2, "opcode": "load", "operand": null},
{"address": 3, "opcode": "jz", "operand": 12},
{"address": 4, "opcode": "swap", "operand": null},
{"address": 5, "opcode": "inc", "operand": null},
{"address": 6, "opcode": "load", "operand": null},
{"address": 7, "opcode": "output", "operand": 1},
{"address": 8, "opcode": "pop", "operand": null},
{"address": 9, "opcode": "swap", "operand": null},
{"address": 10, "opcode": "dec", "operand": null},
{"address": 11, "opcode": "jmp", "operand": 3},
{"address": 12, "opcode": "pop", "operand": null},
{"address": 13, "opcode": "pop", "operand": null},
{"address": 14, "opcode": "halt", "operand": null}
]
Данные:
[
{"address": 0, "value": 13},
{"address": 1, "value": 72},
{"address": 2, "value": 101},
{"address": 3, "value": 108},
{"address": 4, "value": 108},
{"address": 5, "value": 111},
{"address": 6, "value": 44},
{"address": 7, "value": 32},
{"address": 8, "value": 119},
{"address": 9, "value": 111},
{"address": 10, "value": 114},
{"address": 11, "value": 108},
{"address": 12, "value": 100},
{"address": 13, "value": 33}
]
Вывод:
source LoC: 20 code instr: 15
============================================================
Hello, world!
instr_counter: 123 ticks: 137
Журнал (не весь):
DEBUG simulation:run TICK: 70, PC: 8, AR: 7, MEM_OUT: 32, TOS: [32, 7, 7] , pop |
DEBUG simulation:run TICK: 71, PC: 9, AR: 7, MEM_OUT: 32, TOS: [7, 7] , swap |
DEBUG simulation:run TICK: 72, PC: 10, AR: 7, MEM_OUT: 32, TOS: [7, 7] , dec |
DEBUG simulation:run TICK: 73, PC: 11, AR: 7, MEM_OUT: 32, TOS: [6, 7] , jmp 3 |
DEBUG simulation:run TICK: 74, PC: 3, AR: 7, MEM_OUT: 32, TOS: [6, 7] , jz 12 |
DEBUG simulation:run TICK: 75, PC: 4, AR: 7, MEM_OUT: 32, TOS: [6, 7] , swap |
DEBUG simulation:run TICK: 76, PC: 5, AR: 7, MEM_OUT: 32, TOS: [7, 6] , inc |
DEBUG simulation:run TICK: 77, PC: 6, AR: 7, MEM_OUT: 32, TOS: [8, 6] , load |
DEBUG simulation:run TICK: 79, PC: 7, AR: 8, MEM_OUT: 119, TOS: [119, 8, 6] , output 1 |
DEBUG io:log_io OUTPUT: w
DEBUG simulation:run TICK: 80, PC: 8, AR: 8, MEM_OUT: 119, TOS: [119, 8, 6] , pop |
DEBUG simulation:run TICK: 81, PC: 9, AR: 8, MEM_OUT: 119, TOS: [8, 6] , swap |
DEBUG simulation:run TICK: 82, PC: 10, AR: 8, MEM_OUT: 119, TOS: [6, 8] , dec |
DEBUG simulation:run TICK: 83, PC: 11, AR: 8, MEM_OUT: 119, TOS: [5, 8] , jmp 3 |
DEBUG simulation:run TICK: 84, PC: 3, AR: 8, MEM_OUT: 119, TOS: [5, 8] , jz 12 |
DEBUG simulation:run TICK: 85, PC: 4, AR: 8, MEM_OUT: 119, TOS: [5, 8] , swap |
DEBUG simulation:run TICK: 86, PC: 5, AR: 8, MEM_OUT: 119, TOS: [8, 5] , inc |
DEBUG simulation:run TICK: 87, PC: 6, AR: 8, MEM_OUT: 119, TOS: [9, 5] , load |
DEBUG simulation:run TICK: 89, PC: 7, AR: 9, MEM_OUT: 111, TOS: [111, 9, 5] , output 1 |
DEBUG io:log_io OUTPUT: o
DEBUG simulation:run TICK: 90, PC: 8, AR: 9, MEM_OUT: 111, TOS: [111, 9, 5] , pop |
DEBUG simulation:run TICK: 91, PC: 9, AR: 9, MEM_OUT: 111, TOS: [9, 5] , swap |
DEBUG simulation:run TICK: 92, PC: 10, AR: 9, MEM_OUT: 111, TOS: [5, 9] , dec |
DEBUG simulation:run TICK: 93, PC: 11, AR: 9, MEM_OUT: 111, TOS: [4, 9] , jmp 3 |
DEBUG simulation:run TICK: 94, PC: 3, AR: 9, MEM_OUT: 111, TOS: [4, 9] , jz 12 |
DEBUG simulation:run TICK: 95, PC: 4, AR: 9, MEM_OUT: 111, TOS: [4, 9] , swap |
DEBUG simulation:run TICK: 96, PC: 5, AR: 9, MEM_OUT: 111, TOS: [9, 4] , inc |
DEBUG simulation:run TICK: 97, PC: 6, AR: 9, MEM_OUT: 111, TOS: [10, 4] , load |
DEBUG simulation:run TICK: 99, PC: 7, AR: 10, MEM_OUT: 114, TOS: [114, 10, 4] , output 1 |
DEBUG io:log_io OUTPUT: r
DEBUG simulation:run TICK: 100, PC: 8, AR: 10, MEM_OUT: 114, TOS: [114, 10, 4] , pop |
DEBUG simulation:run TICK: 101, PC: 9, AR: 10, MEM_OUT: 114, TOS: [10, 4] , swap |
DEBUG simulation:run TICK: 102, PC: 10, AR: 10, MEM_OUT: 114, TOS: [4, 10] , dec |
DEBUG simulation:run TICK: 103, PC: 11, AR: 10, MEM_OUT: 114, TOS: [3, 10] , jmp 3 |
DEBUG simulation:run TICK: 104, PC: 3, AR: 10, MEM_OUT: 114, TOS: [3, 10] , jz 12 |
DEBUG simulation:run TICK: 105, PC: 4, AR: 10, MEM_OUT: 114, TOS: [3, 10] , swap |
DEBUG simulation:run TICK: 106, PC: 5, AR: 10, MEM_OUT: 114, TOS: [10, 3] , inc |
DEBUG simulation:run TICK: 107, PC: 6, AR: 10, MEM_OUT: 114, TOS: [11, 3] , load |
DEBUG simulation:run TICK: 109, PC: 7, AR: 11, MEM_OUT: 108, TOS: [108, 11, 3] , output 1 |
DEBUG io:log_io OUTPUT: l
DEBUG simulation:run TICK: 110, PC: 8, AR: 11, MEM_OUT: 108, TOS: [108, 11, 3] , pop |
DEBUG simulation:run TICK: 111, PC: 9, AR: 11, MEM_OUT: 108, TOS: [11, 3] , swap |
DEBUG simulation:run TICK: 112, PC: 10, AR: 11, MEM_OUT: 108, TOS: [3, 11] , dec |
DEBUG simulation:run TICK: 113, PC: 11, AR: 11, MEM_OUT: 108, TOS: [2, 11] , jmp 3 |
DEBUG simulation:run TICK: 114, PC: 3, AR: 11, MEM_OUT: 108, TOS: [2, 11] , jz 12 |
DEBUG simulation:run TICK: 115, PC: 4, AR: 11, MEM_OUT: 108, TOS: [2, 11] , swap |
DEBUG simulation:run TICK: 116, PC: 5, AR: 11, MEM_OUT: 108, TOS: [11, 2] , inc |
DEBUG simulation:run TICK: 117, PC: 6, AR: 11, MEM_OUT: 108, TOS: [12, 2] , load |
DEBUG simulation:run TICK: 119, PC: 7, AR: 12, MEM_OUT: 100, TOS: [100, 12, 2] , output 1 |
DEBUG io:log_io OUTPUT: d
DEBUG simulation:run TICK: 120, PC: 8, AR: 12, MEM_OUT: 100, TOS: [100, 12, 2] , pop |
DEBUG simulation:run TICK: 121, PC: 9, AR: 12, MEM_OUT: 100, TOS: [12, 2] , swap |
DEBUG simulation:run TICK: 122, PC: 10, AR: 12, MEM_OUT: 100, TOS: [2, 12] , dec |
DEBUG simulation:run TICK: 123, PC: 11, AR: 12, MEM_OUT: 100, TOS: [1, 12] , jmp 3 |
DEBUG simulation:run TICK: 124, PC: 3, AR: 12, MEM_OUT: 100, TOS: [1, 12] , jz 12 |
DEBUG simulation:run TICK: 125, PC: 4, AR: 12, MEM_OUT: 100, TOS: [1, 12] , swap |
DEBUG simulation:run TICK: 126, PC: 5, AR: 12, MEM_OUT: 100, TOS: [12, 1] , inc |
DEBUG simulation:run TICK: 127, PC: 6, AR: 12, MEM_OUT: 100, TOS: [13, 1] , load |
DEBUG simulation:run TICK: 129, PC: 7, AR: 13, MEM_OUT: 33, TOS: [33, 13, 1] , output 1 |
DEBUG io:log_io OUTPUT: !
DEBUG simulation:run TICK: 130, PC: 8, AR: 13, MEM_OUT: 33, TOS: [33, 13, 1] , pop |
DEBUG simulation:run TICK: 131, PC: 9, AR: 13, MEM_OUT: 33, TOS: [13, 1] , swap |
DEBUG simulation:run TICK: 132, PC: 10, AR: 13, MEM_OUT: 33, TOS: [1, 13] , dec |
DEBUG simulation:run TICK: 133, PC: 11, AR: 13, MEM_OUT: 33, TOS: [0, 13] , jmp 3 |
DEBUG simulation:run TICK: 134, PC: 3, AR: 13, MEM_OUT: 33, TOS: [0, 13] , jz 12 |
DEBUG simulation:run TICK: 135, PC: 12, AR: 13, MEM_OUT: 33, TOS: [0, 13] , pop |
DEBUG simulation:run TICK: 136, PC: 13, AR: 13, MEM_OUT: 33, TOS: [13] , pop |
DEBUG simulation:run TICK: 137, PC: 14, AR: 13, MEM_OUT: 33, TOS: [] , halt |
DEBUG simulation:simulation memory: DATA: [
0: 13
1: 72
2: 101
3: 108
4: 108
5: 111
6: 44
7: 32
8: 119
9: 111
10: 114
11: 108
12: 100
13: 33
]
INFO simulation:simulation output_buffer (port 1): 'Hello, world!'
INFO simulation:simulation output_buffer (port 2): ''
| ФИО | алг | LoC | code инстр. | инстр. | такт. |
| Барсуков Максим Андреевич | cat | 47 | 38 | 198 | 234 |
| Барсуков Максим Андреевич | hello_world | 20 | 15 | 123 | 137 |
| Барсуков Максим Андреевич | hello_username | 86 | 60 | 677 | 774 |
| Барсуков Максим Андреевич | prob2 | 69 | 44 | 513 | 597 |