{"id":15439268,"url":"https://github.com/maxbarsukov/csa3-stack-machine","last_synced_at":"2025-03-28T06:30:25.443Z","repository":{"id":240434454,"uuid":"802608590","full_name":"maxbarsukov/csa3-stack-machine","owner":"maxbarsukov","description":"💻📚 Computer system architecture Lab #3 -- Experiment (stack machine)","archived":false,"fork":false,"pushed_at":"2024-09-30T11:40:00.000Z","size":173,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-02T07:23:19.678Z","etag":null,"topics":["basic-computer","computer-system-architecture","python","stack-machine"],"latest_commit_sha":null,"homepage":"https://gitlab.se.ifmo.ru/computer-systems/csa-rolling/-/blob/master/lab3-task.md","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/maxbarsukov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-05-18T19:14:51.000Z","updated_at":"2024-09-30T11:37:47.000Z","dependencies_parsed_at":"2024-05-18T21:24:51.354Z","dependency_job_id":"ac2ac6d6-c775-4498-a3d4-a8d5d3efbf27","html_url":"https://github.com/maxbarsukov/csa3-stack-machine","commit_stats":null,"previous_names":["maxbarsukov/csa3-stack-machine"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxbarsukov%2Fcsa3-stack-machine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxbarsukov%2Fcsa3-stack-machine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxbarsukov%2Fcsa3-stack-machine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxbarsukov%2Fcsa3-stack-machine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maxbarsukov","download_url":"https://codeload.github.com/maxbarsukov/csa3-stack-machine/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245984176,"owners_count":20704787,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["basic-computer","computer-system-architecture","python","stack-machine"],"created_at":"2024-10-01T19:04:02.981Z","updated_at":"2025-03-28T06:30:25.415Z","avatar_url":"https://github.com/maxbarsukov.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Лабораторная №3. Эксперимент.\n\n- Барсуков Максим Андреевич, P3215\n- Вариант: `alg -\u003e asm | stack | harv | hw | tick -\u003e instr | struct | stream | port | pstr | prob2 | cache`\n- **Упрощённый вариант**: `asm | stack | harv | hw | instr | struct | stream | port | pstr | prob2`\n\n## Язык программирования\n### Синтаксис\n\nРасширенная форма Бэкуса —Наура:\n\n``` ebnf\n\u003cprogram\u003e ::= \u003csection_data\u003e \u003csection_text\u003e | \u003csection_text\u003e \u003csection_data\u003e | \u003csection_text\u003e\n\n\u003csection_data\u003e ::= \".data\\n\" \u003cdeclaration\u003e*\n\u003csection_text\u003e ::= \".text\\n\" (\u003clabel_def\u003e | \u003cinstruction\u003e | \u003clabel_def\u003e \u003cinstruction\u003e)*\n\n\u003cdeclaration\u003e ::= \u003clabel_def\u003e (\u003carray\u003e | \u003creserve\u003e)\n\u003cinstruction\u003e ::= \u003clabel_arg_command\u003e | \u003cnumber_arg_command\u003e | \u003cwithout_arg_command\u003e\n\n\u003clabel_def\u003e ::= (\u003cname\u003e \":\" (\" \")*) | (\u003cname\u003e \":\" (\" \")* \"\\n\")\n\n\u003carray\u003e ::= (\u003carray_element\u003e \",\" (\" \")*)* \u003carray_element\u003e+\n\u003creserve\u003e ::= \"res\" (\" \")+ \u003cnumber\u003e\n\u003carray_element\u003e ::= (\"\\\"\" \u003cany_ascii\u003e \"\\\"\" | \u003cnumber\u003e)\n\n\u003clabel_arg_command\u003e ::= (\"push\" | \"jump\" | \"jz\" | \"jnz\" | \"js\" | \"jns\" | \"call\") (\" \")+ \u003cname\u003e\n\n\u003cnumber_arg_command\u003e ::= (\"push\" | \"input\" | \"output\") (\" \")+ \u003cnumber\u003e\n\n\u003cwithout_arg_command\u003e ::= (\"nop\" | \"halt\" | \"add\" | \"sub\" | \"mul\" | \"div\" | \"mod\"\n| \"cmp\" | \"and\" | \"or\" | \"xor\" | \"inc\" | \"dec\" | \"neg\" | \"not\" | \"ret\" | \"pop\"\n| \"swap\" | \"dup\" | \"over\" | \"over3\" | \"load\" | \"store\" | \"debug\")\n\n\u003cnumber\u003e ::= [-2^31; 2^31 - 1]\n\u003cname\u003e ::= (\u003cletter_or_\u003e)+\n\u003cletter_or_\u003e ::= \u003cletter\u003e | (\"_\")\n\u003cletter\u003e ::= [a-z] | [A-Z]\n``` \n\n### Семантика\n\n- `.text` -- секция, в которой все последующие слова (до конца файла или объявления `.data`) интерпретируются, как инструкции или их аргументы или комментарии или метки;\n- `.data` -- секция, в которой все последующие слова (до конца файла или объявления `.data`) интерпретируются как инициализация или резервация сегментов памяти для пользовательских данных;\n- `label` -- метка, которая является указателем на адрес памяти инструкции за ней (если метка в section `.text`) или является указателем на первый элемент зарезервированого сегмента памяти (если метка в section `.data`);\n- `res n` -- оператор, который может писаться после объявления метки в секции данных, обозначающий, что необходимо зарезервировать `n` слов памяти под эту метку;\n- `push n` -- кладет значение `n` на вершину стэка. Если `n` - **метка, то кладет адрес**, который она описывает, если `n` - число, то кладет само значение `n`. ВАЖНО: так как у меня гарвардская архитектура, `push label` я могу выполнять **только для label из Data Memory**;\n- `pop` -- удаляет верхний элемент со стэка;\n- `jump label` -- команда безусловного перехода. Устанавливает следующую команду, как ту, на которую указывает label - из Program Memory; \n- `jz label` -- если на вершине стэка 0, то выполняет `jump`, иначе переход к следующей команде;\n- `jnz label` -- если на вершине стэка не 0, то выполняет `jump`, иначе переход к следующей команде;\n- `js label` -- если на вершине стэка отрицательное число, то выполняет `jump`, иначе переход к следующей команде;\n- `jns label` -- если на вершине стэка не отрицательное число, то выполняет `jump`, иначе переход к следующей команде;\n- `call label` -- сохраняет на стэке вызывов адрес следующей команды и переходит к выполнению инструкции за label;\n- `ret` -- устанавливает следующую команду, как ту, что лежит на верху стэка вызовов и удаляет элемент с верхушки стэка вызовов;\n- `input n` -- считывает один символ из порта n и записывает его на верх стэка;\n- `output n` -- записывает в порт n значение из верхушки стэка;\n- `halt` -- завершение программы;\n- `add` -- складывает значение на вершине стэка и значение  следующее после вершины стэка, результат помещает на вершину стэка, операнды убираются со стэка;\n- `sub` -- вычитает значение на вершине стэка и значение  следующее после вершины стэка, результат помещает на вершину стэка, операнды убираются со стэка;\n- `mul` -- перемножает значение на вершине стэка и значение  следующее после вершины стэка, результат помещает на вершину стэка, операнды убираются со стэка;\n- `div` -- делит значение на вершине стэка и значение  следующее после вершины стэка нацело, результат помещает на вершину стэка, операнды убираются со стэка;\n- `mod` -- берёт остаток от деления значения на вершине стэка на значение следующего после вершины стэка, результат помещает на вершину стэка, операнды убираются со стэка;\n- `cmp` -- вычитает значение на вершине стэка и значение  следующее после вершины стэка, результат помещает на вершину стэка, операнды НЕ убираются со стэка;\n- `and` -- битовое И значения на вершине стэка и значения  следующего после вершины стэка, результат помещает на вершину стэка, операнды убираются со стэка;\n- `or` -- битовое ИЛИ значения на вершине стэка и значения  следующего после вершины стэка, результат помещает на вершину стэка, операнды убираются со стэка;\n- `xor` -- битовое исключающее ИЛИ значения на вершине стэка и значения  следующего после вершины стэка, результат помещает на вершину стэка, операнды убираются со стэка;\n- `not` -- битовое НЕ значения на вершине стэка;\n- `swap` -- меняет местами значение на вершине стэка и значение следующее после вершины стэка;\n- `dup` -- кладёт на вершину стэка значение с вершине стэка;\n- `over` -- кладёт на вершину стэка значение следующее после вершины стэка;\n- `over3` -- кладёт на вершину стэка значение следующее после значения, следующего после вершины стэка;\n- `inc` -- увеличивает значение верхушки стэка на 1;\n- `dec` -- уменьшает значение верхушки стэка на 1;\n- `neg` -- устанавливает значение верхушки стэка на отрицательное (* (-1));\n- `load` -- интерпретирует значение на вершине стэка, как адрес по которому из памяти загружает значение на вершину стэка.\n- `store` -- интерпретирует значение следующее после вершины стэка, как адрес по которому нужно записать значение на вершине стэка.\n- `debug` -- команда отладки. Вывод  в устройство ввода-вывода 1 отладочную информацию о текущем значении процессора и останавливает программу до нажатия пользователем любой клавиши.\n- `nop` -- пустая команда. Совершается тик, переходят к следующей инструкции.\n\n#### Комментарии:\n\nНачинаются со знака `;` и идут до конца строки.\n\n#### Особенности реализации\n\n- В программе не может быть дублирующихся меток.\n\n- Метка памяти данных задается на той же строке, что и данные:\n``` asm \nhello_world: \"Hello, world!\"\n```\n\n- Так как строки Pascal-string, компилятор сам упаковывает их во время компиляции (ставит первым словом строки длину строки).\n\n- Метка памяти команд задается на строке предшествующей инструкции, на которую указывает метка, либо на той же самой строке:\n```\nfoo:\n    push 10\n    ...\n\nbar: nop\n    ...\n```\n\n#### Порядок выполнения: \n\nПрограмма выполняется последовательно, одна инструкция за другой.\n\n#### Память: \n- Распределяется статически на этапе трансляции\n- Строковые литералы помещаются в память в начале работы программы в формате Pascal-string.\n- Под динамически считываемые строки пользователь сам определяет, как будет считываться строка. Он может выделить некоторый буфер через `res n`, или расположить строку в конце памяти и считывать сколько необходимо (или пока хватает памяти).\n\n#### Область видимости\n\nВ любом месте секции `.text` доступен стэк и операции над его верхними значениями. Видимость меток глобальная.\n\n#### Типизация, виды литералов\n\nЛитералы могут быть представлены в виде чисел и меток (в последствии интерпретируются как числа), в секции `.data` можно объявлять строки. Типизация отсутсвует, так как пользователь языка может интерпретировать любые данные как захочет и может с ними выполнить любые из возможных операций.\n\n## Организация памяти\n\n- Гарвардская архитектура\n- Резмер машинного слова:\n  - Память данных - 32 бит;\n  - Память команд - 32 бит.\n- Имеет линейное адресное пространство.\n- В памяти данных хранятся статические строки и переменных\n- В памяти команд хранятся инструкции для выполнения\n- Взаимодействие с памятью данных происходит при помощи инструкций `load` и `store`.\n- Адресации:\n  - Прямая абсолютная (например, `push label`)\n  - Косвенная (у команд `load`, `store` один из операндов является указателем на ячейку памяти)\n\n```\n       Program memory\n+------------------------------+\n| 00 : jump n                  |\n|   ...                        |\n|  n : _start: instruction1    |\n|   ...                        |\n+------------------------------+\n\n          Data memory\n+------------------------------+\n| 00  : array 1                |\n|    ...                       |\n|  n  : array 2                |\n|    ...                       |\n+------------------------------+\n\n```\n\n- Для работы с регистрами отведена память, организованная в виде стека. Программист напрямую имеет доступ к `TOS`, верхушке `Stack Registers`, заранее инициализированной памяти в `Data Memory`, а также, используя различные условные и безусловный переходы, может изменять `PC`;\n- Память данных разделена на массивы - разделение определяет пользователь, именуя каждый массив лейблом;\n- Массив может состоять из строк, чисел и свободного места (заполнено нулями), зарезервированного на определенное количество байт. Все данные в массивах и все массивы идут последовательно;\n- Инструкции хранятся в `Program Memory`;\n- Для операндов пользователю отводится 24 бита, т.к. предполагается, что оставшиеся 8 бит будет занимать информация о инструкции (например опкод);\n- Используя команду `push number` литерал используется при помощи непосредственной адресации;   \n- Используя команду `store` литерал будет загружен в статическую память;\n\n### Стэки\n\n- Имеются стек данных и стек возвратов.\n- Оба поддерживают операции `push` и `pop`\n- Стек данных поддерживает операции `dup` и `swap`, а также чтение из второй от вершины ячейки (предполагается реализация на уровне схемотехники).\n\n### Регистры\n\nРегистры:\n- PC - счетчик команд\n- AR - регистр адреса\n\n## Система команд\n\n**Особенности процессора:**\n- Машинное слово -- знаковое 32-ух битное число;\n- Доступ памяти осуществляется через указатель на вершине `Stack Register`. Установить можно при помощи `push label`;\n- Устройство ввода-вывод: port-mapped\n- Поток управления: \n  - Инкрементирование `PC`;\n  - Условный/безусловный переход;\n  - Адрес из вершины `Call Stack`.\n\n| Команда                                                         | Число тактов | Стек ДО                                                                           | Стек ПОСЛЕ                                                                         | Описание                                                                                                                                                                                           |\n|:----------------------------------------------------------------|--------------|:----------------------------------------------------------------------------------|------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| PUSH [value]                                                    | 1            | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e    | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003evalue\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e   | пушит на вершину стека свой аргумент, выставляет флаги `N` (negative) и `Z` (zero) для  верхушки стека                                                                                                                                                               |\n| PUSH [label]                                                    | 1            | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e    | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003elabel_addr\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e   | пушит на вершину стека свой адрес своего аргумента, выставляет флаги `N` (negative) и `Z` (zero) для  верхушки стека                                                                                                                                                               |\n| LOAD                                                            | 2            | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003eaddr\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e   | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003eaddr\u003c/td\u003e\u003ctr\u003e\u003ctd\u003evalue\u003c/td\u003e\u003c/tr\u003e\u003c/tr\u003e\u003c/table\u003e   | загружает значение из памяти, адрес берется из вершины стека, выставляет флаги `N` (negative) и `Z` (zero) для  верхушки стека                                                                                                                                       |\n| STORE                                                           | 2            | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003eaddr\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003evalue\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003eaddr\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003evalue\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e   | сохраняет значение из вершины стека, адрес берется из второй ячейки                                                                                                                          |\n| POP                                                             | 1            | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003evalue\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e  | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e     | удаляет вершину стека, выставляет флаги `N` (negative) и `Z` (zero) для  верхушки стека                                                                                                                                                                              |\n| ADD\u003cbr/\u003eSUB\u003cbr/\u003eMUL\u003cbr/\u003eDIV\u003cbr/\u003eMOD\u003cbr/\u003eAND\u003cbr/\u003eOR\u003cbr/\u003eXOR\u003cbr/\u003eMOD\u003cbr/\u003eMOD\u003cbr/\u003eMOD                             | 1            | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003ea\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003eb\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e        | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003eresult\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e  | выполняет арифметическую операцию, выставляет флаги `N` (negative) и `Z` (zero) для  верхушки стека                                                                                                                                                                  |\n| CMP                             | 1            | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003ea\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003eb\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e        | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003ea\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003eb\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003eresult\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e  | выполняет a - b, сохраняет операнды, выставляет флаги `N` (negative) и `Z` (zero) для  верхушки стека                                                                                                                                                                  |\n| INC\u003cbr/\u003eDEC                                                     | 1            | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003evalue\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e  | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003eresult\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e  | выполняет инкремент или декремент, выставляет флаги `N` (negative) и `Z` (zero) для  верхушки стека                                                                                                                                                                  |\n| INPUT [port]                                                     | 1            | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e    | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003evalue\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e   | читает из устройства ввода-вывода с порта один символ, выставляет флаги `N` (negative) и `Z` (zero) для  верхушки стека                                                                                                                                                                        |\n| OUTPUT [port]                                                    | 1            | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003evalue\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e  | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003evalue\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e     | записывает вершину стека в порт                                                                                                                                                                    |\n| DUP                                                             | 1            | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003evalue\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e  | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003evalue\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003evalue\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e | дублирует значение с вершины стека                                                                                                                                                                 |\n| SWAP                                                            | 1            | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003ea\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003eb\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e        | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003eb\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003ea\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e         | меняет местами верхние 2 значения в стеке, выставляет флаги `N` (negative) и `Z` (zero) для  верхушки стека                                                                                                                                                          |\n| OVER                                                            | 1            | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003ea\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003eb\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e        | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003ea\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003eb\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003ea\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e         | кладёт на вершину стэка значение следующее после вершины стэка, выставляет флаги `N` (negative) и `Z` (zero) для  верхушки стека                                                                                                                                                          |\n| OVER3                                                            | 1            | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003e...\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003ea\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003eb\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003ec\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e        | \u003ctable\u003e\u003ctr\u003e\u003ctd\u003ea\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003eb\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003ec\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd\u003ea\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e         | кладёт на вершину стэка значение второе после вершины стэка, выставляет флаги `N` (negative) и `Z` (zero) для  верхушки стека                                                                                                                                                          |\n| JUMP [addr]\u003cbr/\u003eJZ [addr]\u003cbr/\u003eJNZ [addr]\u003cbr/\u003eJS [addr]\u003cbr/\u003eJNS [addr] | 1            | -                                                                                 | -                                                                                  | прыжок на инструкцию на основании выставленных флагов. \u003cbr/\u003e`JUMP` - безусловный, \u003cbr/\u003e`JZ` - прыжок, если ноль, \u003cbr/\u003e`JNZ` - прыжок, если не ноль, \u003cbr/\u003e`JS`/`JNS` - прыжок, если отрицательное/не отрицательное |\n| CALL [addr]                                                     | 1            | -                                                                                 | -                                                                                  | вызов функции по адресу addr                                                                                                                                                                       |\n| RET                                                             | 1            | -                                                                                 | -                                                                                  | возврат из функции                                                                                                                                                                                 |\n| DEBUG                                                            | 1            | -                                                                                 | -                                                                                  | вывод отладочной информации на устройство на порту 1, остановка программы до действий пользователя                                                                                                                                                                              |\n| NOP                                                            | 1            | -                                                                                 | -                                                                                  | пустая инструкция                                                                                                                                                                              |\n| HALT                                                            | 1            | -                                                                                 | -                                                                                  | остановить выполнение                                                                                                                                                                              |\n\n### Формат инструкций\nИнструкции представлены в формате _JSON_:\n\n```json\n{\n  \"opcode\": \"jump\",\n  \"operand\": 123,\n  \"address\": 10\n}\n```\nгде:\n- `opcode` - код операции (Opcode - тип данных, определенный в [isa](./src/isa/opcode.py))\n- `operand` - аргумент инструкции\n- `address` - указывает адрес инструкции в памяти инструкций.\n\n## Транслятор\n\nРеализация транслятора: [translator](./src/translator/main.py)\n\nИнтерфейс командной строки:\n\n- Получить справку: `poetry run translator --help`\n\n```\nusage: translator [-h] source_file target_instrs_file target_data_file\nCSA Lab 3 translator.\n\npositional arguments:\n  source_file         File with asm code\n  target_instrs_file  File to write instructions after compilation\n  target_data_file    File to write data after compilation\n\noptions:\n  -h, --help          show this help message and exit\n```\n\n`poetry run translator [-h] \u003csource_file\u003e \u003ctarget_instrs_file\u003e \u003ctarget_data_file\u003e`\n\n- Первый аргумент - путь до файла с исходным кодом,\n- второй аргумент - путь до файла, куда будут записаны инструкции, сохраненные в `json`.\n- третий аргумент - путь до файла, куда будут записаны массивы данных, инициализированные в пользовательской программе, сохраненные в `json`.  \n\nТрансляция секции `.data`:\n- Реализована в `get_data`;\n- Сначала определяется место в коде, где объявлена секция `.data`;\n- Потом лейбл отделяется от данных;\n- В `get_codes_from_data` данные преобразуются в последовательность чисел:\n  - Функция `str2list_int` возвращает массив, в котором строка представляется как массив байт, на позициях одиночных чисел и резервирования - пустые массивы;\n  - Функция `get_integers` удалят из данных строки, возвращает массив одиночных чисел и резервированной памяти;\n  - Далее на пустые места вставляются одиночные числа и массивы резервирования;\n  - В конце все данные выпрямляются в один итоговый массив.\n  \nТрансляция секции `.text`:\n- `translate_without_operands`: инструкции разбиваются на токены, запоминаются номера меток. Возвращается высокоуровневая структура, описывающая инструкции;\n- `translate_operands`: в джампы подставляются номера инструкций в зависимости от лейбла, в `push label` заменяются метки на адреса в памяти, проверяются ограничения на аргументы;\n- Код из высокоурвневой структуры переводится в бинарный вид в функции `write_code`, определенной в `isa`\n\nПравила:\n- Не более одного определения секций `.data` и `.text`\n- Одиночные числа, объявленные в `.data` должны принимать значения [-2^31; 2^31 - 1];\n- Метка в секции `.data` задается на той же строке, что и данные. Данные задаются на одной строке;\n- Метка в секции `.text` задается перед инструкцией, на которую он указывает;\n- Обязательна метка `_start`;\n\n## Модель процессора\n\nРеализация модели процессора: [machne](./src/machine/main.py)\n\nИнтерфейс командной строки:\n\n- Получить справку: `poetry run machine --help`\n\n```\nusage: machine [-h] [--log_level {FATAL,ERROR,WARN,INFO,DEBUG,NOTSET,}] [--output_ports {1,2,1;2}] instructions_file data_file input_file\n\nCSA Lab 3 machine runner.\n\npositional arguments:\n  instructions_file     File with instructions\n  data_file             File with data\n  input_file            File with user input\n\noptions:\n  -h, --help            show this help message and exit\n  --log_level {FATAL,ERROR,WARN,INFO,DEBUG,NOTSET}\n                        Log level\n  --output_ports {1,2,1;2}\n                        IO ports to print output\n```\n\n- Первый аргумент - путь до файла с инструкциями,\n- Второй аргумент - путь до файла с данными.\n- Третий аргумент - путь до файла, откуда берется ввод пользователя.  \n- Опция `--log_level` - позволяет установить уровень логирования.\n- Опция `--output_ports` - позволяет выбрать, с каких устройств ввода-вывода по портам данные будут также выводиться в терминал при запуске.\n\n\n### Ввод-вывод\n\nРазработаны `IOController`, который на основании порта [0-15] использует устройство ввода-вывода. Сделано несколько устройств ввода-вывода (реализация в [io.py](./src/machine/components/io.py)):\n- `IO0`: ввод данных посимвольно из stdin (реализация через файл `\u003cinput_file\u003e`). Если данные закончились, отдает EOF (-1). *Использование*: `INPUT 0`\n- `IO1`: вывод ячейки в stdout как символа (для значения 97 выведет `a`). *Использование*: `OUTPUT 1`\n- `IO2`: вывод ячейки в stdout как числа (для значения 97 выведет `97`). *Использование*: `OUTPUT 1`\n- `IO8`: ввод данных из бесконечного потока символов `'1', ..., '9', '0', '1', ...`. Читает по одному символу из этого потока. *Использование*: `INPUT 8`\n\n\n### DataPath\n\n![data_path.svg](./img/data_path.svg)\n\nРеализован в [data_path](src/machine/data_path.py)\n\nСигналы (обрабатываются за один такт, реализованы в виде методов класса)\n- `latch_data_addr` - защёлкнуть значение в data_addr\n- `latch_tos` - защёлкнуть вершину стека\n- `store` / `load` - сигналы записи / чтения памяти данных\n- `operation` - сигнал, определяющий операцию алу\n- `read` / `write` / `port` - сигналы чтения / записи / порта устройства ввода вывода\n\nФлаги:\n- `Z` - zero - отражает нулевое значение в вершине стека\n- `N` - negative - отражает отрицательное значение в вершине стека\n\n### ControlUnit\n\n![control_unit.svg](img/control_unit.svg)\n\nРеализован в [control_unit](./src/machine/control_unit.py)\n- hardwired - внутренняя логика дешифратора инструкций скрыта. В данной модели реализована на Python.\n- Метод `decode_and_execute_instruction` моделирует выполнение полного цикла инструкции.\n- `_tick` - имитирует работу счетчика тактов.\n\nСигналы: \n- `latch_pc` - защелкнуть значение в program_counter\n- `read` - чтение из памяти инструкций\n\nОсобенности работы модели:\n- Цикл симуляции осуществляется в функции `simulation`.\n- Шаг моделирования соответствует одной инструкции с выводом состояния в журнал.\n- Для журнала состояний процессора используется стандартный модуль `logging`.\n- Остановка модели осуществляется при следующих условиях:\n  - достижение инструкции halt;\n  - переполнение стека или чтение из пустого стека;\n  - отсутствие данных для чтения из порта ввода;\n  - чтение или запись в несуществующий адрес памяти.\n- Модель может быть остановлена и возобновлена командой `debug`.\n\n## Тестирование\n\nТестирование выполняется при помощи golden test-ов.\n- Конфигурация лежит в директории [tests](./tests)\n\nGitHub Actions при совершении `push`-а автоматически\n- запускает golden-тесты (задание `test`)\n- проверяет форматирование Python и запускает линтеры (`ruff`)\n- проверяет форматирование Markdown (`markdownlint`)\n\nКонфигурация для GitHub Actions находится в файлах [python.yml](.github/workflows/python.yml) и [markdown.yml](.github/workflows/markdown.yml)\n\n### Результаты тестирования:\n\nGolden-тесты:\n\n```\n❯ poetry run coverage run -m pytest . -v\n============================================================================================ test session starts ============================================================================================\nplatform 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\ncachedir: .pytest_cache\nrootdir: /home/max/prog/itmo/csa3-stack-machine\nconfigfile: pyproject.toml\nplugins: golden-0.2.2\ncollected 6 items                                                                                                                                                                                           \n\ntests/golden_test.py::test_translator_and_machine[golden/prob2.yml] PASSED                                                                                                                            [ 16%]\ntests/golden_test.py::test_translator_and_machine[golden/0_to_9.yml] PASSED                                                                                                                           [ 33%]\ntests/golden_test.py::test_translator_and_machine[golden/cat.yml] PASSED                                                                                                                              [ 50%]\ntests/golden_test.py::test_translator_and_machine[golden/hello_username.yml] PASSED                                                                                                                   [ 66%]\ntests/golden_test.py::test_translator_and_machine[golden/hello_world.yml] PASSED                                                                                                                      [ 83%]\ntests/golden_test.py::test_translator_and_machine[golden/string_utils.yml] PASSED                                                                                                                     [100%]\n\n============================================================================================= 6 passed in 1.62s =============================================================================================\n```\n\nПокрытие:\n\n```\n❯ poetry run coverage report -m\n\nName                                        Stmts   Miss  Cover   Missing\n-------------------------------------------------------------------------\nsrc/__init__.py                                 0      0   100%\nsrc/constants.py                                9      0   100%\nsrc/isa/__init__.py                             6      0   100%\nsrc/isa/data.py                                16      0   100%\nsrc/isa/dump.py                                16      0   100%\nsrc/isa/instruction.py                         18      1    94%   23\nsrc/isa/json_utils.py                          15      0   100%\nsrc/isa/memory.py                              33      0   100%\nsrc/isa/opcode.py                              48      2    96%   56, 64\nsrc/machine/__init__.py                         0      0   100%\nsrc/machine/components/__init__.py              0      0   100%\nsrc/machine/components/alu.py                  27      2    93%   50, 52\nsrc/machine/components/call_stack.py           18      0   100%\nsrc/machine/components/data_stack.py           48      2    96%   35-36\nsrc/machine/components/io.py                   80      8    90%   11, 15, 29, 58, 69, 86, 109, 123\nsrc/machine/components/memory.py               20      1    95%   21\nsrc/machine/control_unit.py                    89      3    97%   114-117\nsrc/machine/data_path.py                       41      0   100%\nsrc/machine/main.py                            44     25    43%   35-45, 49-53, 57-77, 81\nsrc/machine/simulation.py                      41      3    93%   24, 26, 31\nsrc/main.py                                     8      3    62%   9-11\nsrc/translator/__init__.py                      3      0   100%\nsrc/translator/data_translator.py              82      4    95%   15-16, 104-105\nsrc/translator/instructions_translator.py      69      2    97%   21, 35\nsrc/translator/main.py                         34      7    79%   50-57, 61\nsrc/translator/utils.py                        15      0   100%\ntests/__init__.py                               0      0   100%\ntests/golden_test.py                           32      0   100%\n-------------------------------------------------------------------------\nTOTAL                                         812     63    92%\n```\n\nАлгоритмы согласно варианту:\n- [hello_world](./tests/golden/hello_world.yml)\n- [cat](./tests/golden/cat.yml)\n- [hello_username](./tests/golden/hello_username.yml)\n- [prob2](./tests/golden/prob2.yml)\n\nДополнительные алгоритмы:\n- [string_utils](./tests/golden/string_utils.yml) - набор функций для удобной работы со строками.\n- [0_to_9.yml](./tests/golden/0_to_9.yml) - демонстрация работы IO8.\n\n### Отчет на примере Hello, world\n\nИсходный код:\n\n```asm\n.data\nhello_str: \"Hello, world!\"\n\n.text\n_start:\n        push hello_str\n        load\ncycle:\n        jz ext\n        swap\n        inc\n        load\n        output 1\n        pop\n        swap\n        dec\n        jmp cycle\n        pop\n        pop\n        halt\n```\n\nМашинный код:\n\n```json\n[\n  {\"address\": 0, \"opcode\": \"jmp\", \"operand\": 1},\n  {\"address\": 1, \"opcode\": \"push\", \"operand\": 0},\n  {\"address\": 2, \"opcode\": \"load\", \"operand\": null},\n  {\"address\": 3, \"opcode\": \"jz\", \"operand\": 12},\n  {\"address\": 4, \"opcode\": \"swap\", \"operand\": null},\n  {\"address\": 5, \"opcode\": \"inc\", \"operand\": null},\n  {\"address\": 6, \"opcode\": \"load\", \"operand\": null},\n  {\"address\": 7, \"opcode\": \"output\", \"operand\": 1},\n  {\"address\": 8, \"opcode\": \"pop\", \"operand\": null},\n  {\"address\": 9, \"opcode\": \"swap\", \"operand\": null},\n  {\"address\": 10, \"opcode\": \"dec\", \"operand\": null},\n  {\"address\": 11, \"opcode\": \"jmp\", \"operand\": 3},\n  {\"address\": 12, \"opcode\": \"pop\", \"operand\": null},\n  {\"address\": 13, \"opcode\": \"pop\", \"operand\": null},\n  {\"address\": 14, \"opcode\": \"halt\", \"operand\": null}\n]\n```\n\nДанные:\n\n```json\n[\n  {\"address\": 0, \"value\": 13},\n  {\"address\": 1, \"value\": 72},\n  {\"address\": 2, \"value\": 101},\n  {\"address\": 3, \"value\": 108},\n  {\"address\": 4, \"value\": 108},\n  {\"address\": 5, \"value\": 111},\n  {\"address\": 6, \"value\": 44},\n  {\"address\": 7, \"value\": 32},\n  {\"address\": 8, \"value\": 119},\n  {\"address\": 9, \"value\": 111},\n  {\"address\": 10, \"value\": 114},\n  {\"address\": 11, \"value\": 108},\n  {\"address\": 12, \"value\": 100},\n  {\"address\": 13, \"value\": 33}\n]\n```\n\nВывод:\n\n```\nsource LoC: 20 code instr: 15\n============================================================\nHello, world!\n\ninstr_counter:  123 ticks: 137\n```\n\nЖурнал (не весь):\n\n```\nDEBUG   simulation:run           TICK:  70,  PC:   8,  AR:   7,  MEM_OUT:  32,  TOS: [32, 7, 7]            ,    pop       |\nDEBUG   simulation:run           TICK:  71,  PC:   9,  AR:   7,  MEM_OUT:  32,  TOS: [7, 7]                ,    swap      |\nDEBUG   simulation:run           TICK:  72,  PC:  10,  AR:   7,  MEM_OUT:  32,  TOS: [7, 7]                ,    dec       |\nDEBUG   simulation:run           TICK:  73,  PC:  11,  AR:   7,  MEM_OUT:  32,  TOS: [6, 7]                ,    jmp 3     |\nDEBUG   simulation:run           TICK:  74,  PC:   3,  AR:   7,  MEM_OUT:  32,  TOS: [6, 7]                ,    jz 12     |\nDEBUG   simulation:run           TICK:  75,  PC:   4,  AR:   7,  MEM_OUT:  32,  TOS: [6, 7]                ,    swap      |\nDEBUG   simulation:run           TICK:  76,  PC:   5,  AR:   7,  MEM_OUT:  32,  TOS: [7, 6]                ,    inc       |\nDEBUG   simulation:run           TICK:  77,  PC:   6,  AR:   7,  MEM_OUT:  32,  TOS: [8, 6]                ,    load      |\nDEBUG   simulation:run           TICK:  79,  PC:   7,  AR:   8,  MEM_OUT: 119,  TOS: [119, 8, 6]           ,    output 1  |\nDEBUG   io:log_io        OUTPUT: w\nDEBUG   simulation:run           TICK:  80,  PC:   8,  AR:   8,  MEM_OUT: 119,  TOS: [119, 8, 6]           ,    pop       |\nDEBUG   simulation:run           TICK:  81,  PC:   9,  AR:   8,  MEM_OUT: 119,  TOS: [8, 6]                ,    swap      |\nDEBUG   simulation:run           TICK:  82,  PC:  10,  AR:   8,  MEM_OUT: 119,  TOS: [6, 8]                ,    dec       |\nDEBUG   simulation:run           TICK:  83,  PC:  11,  AR:   8,  MEM_OUT: 119,  TOS: [5, 8]                ,    jmp 3     |\nDEBUG   simulation:run           TICK:  84,  PC:   3,  AR:   8,  MEM_OUT: 119,  TOS: [5, 8]                ,    jz 12     |\nDEBUG   simulation:run           TICK:  85,  PC:   4,  AR:   8,  MEM_OUT: 119,  TOS: [5, 8]                ,    swap      |\nDEBUG   simulation:run           TICK:  86,  PC:   5,  AR:   8,  MEM_OUT: 119,  TOS: [8, 5]                ,    inc       |\nDEBUG   simulation:run           TICK:  87,  PC:   6,  AR:   8,  MEM_OUT: 119,  TOS: [9, 5]                ,    load      |\nDEBUG   simulation:run           TICK:  89,  PC:   7,  AR:   9,  MEM_OUT: 111,  TOS: [111, 9, 5]           ,    output 1  |\nDEBUG   io:log_io        OUTPUT: o\nDEBUG   simulation:run           TICK:  90,  PC:   8,  AR:   9,  MEM_OUT: 111,  TOS: [111, 9, 5]           ,    pop       |\nDEBUG   simulation:run           TICK:  91,  PC:   9,  AR:   9,  MEM_OUT: 111,  TOS: [9, 5]                ,    swap      |\nDEBUG   simulation:run           TICK:  92,  PC:  10,  AR:   9,  MEM_OUT: 111,  TOS: [5, 9]                ,    dec       |\nDEBUG   simulation:run           TICK:  93,  PC:  11,  AR:   9,  MEM_OUT: 111,  TOS: [4, 9]                ,    jmp 3     |\nDEBUG   simulation:run           TICK:  94,  PC:   3,  AR:   9,  MEM_OUT: 111,  TOS: [4, 9]                ,    jz 12     |\nDEBUG   simulation:run           TICK:  95,  PC:   4,  AR:   9,  MEM_OUT: 111,  TOS: [4, 9]                ,    swap      |\nDEBUG   simulation:run           TICK:  96,  PC:   5,  AR:   9,  MEM_OUT: 111,  TOS: [9, 4]                ,    inc       |\nDEBUG   simulation:run           TICK:  97,  PC:   6,  AR:   9,  MEM_OUT: 111,  TOS: [10, 4]               ,    load      |\nDEBUG   simulation:run           TICK:  99,  PC:   7,  AR:  10,  MEM_OUT: 114,  TOS: [114, 10, 4]          ,    output 1  |\nDEBUG   io:log_io        OUTPUT: r\nDEBUG   simulation:run           TICK: 100,  PC:   8,  AR:  10,  MEM_OUT: 114,  TOS: [114, 10, 4]          ,    pop       |\nDEBUG   simulation:run           TICK: 101,  PC:   9,  AR:  10,  MEM_OUT: 114,  TOS: [10, 4]               ,    swap      |\nDEBUG   simulation:run           TICK: 102,  PC:  10,  AR:  10,  MEM_OUT: 114,  TOS: [4, 10]               ,    dec       |\nDEBUG   simulation:run           TICK: 103,  PC:  11,  AR:  10,  MEM_OUT: 114,  TOS: [3, 10]               ,    jmp 3     |\nDEBUG   simulation:run           TICK: 104,  PC:   3,  AR:  10,  MEM_OUT: 114,  TOS: [3, 10]               ,    jz 12     |\nDEBUG   simulation:run           TICK: 105,  PC:   4,  AR:  10,  MEM_OUT: 114,  TOS: [3, 10]               ,    swap      |\nDEBUG   simulation:run           TICK: 106,  PC:   5,  AR:  10,  MEM_OUT: 114,  TOS: [10, 3]               ,    inc       |\nDEBUG   simulation:run           TICK: 107,  PC:   6,  AR:  10,  MEM_OUT: 114,  TOS: [11, 3]               ,    load      |\nDEBUG   simulation:run           TICK: 109,  PC:   7,  AR:  11,  MEM_OUT: 108,  TOS: [108, 11, 3]          ,    output 1  |\nDEBUG   io:log_io        OUTPUT: l\nDEBUG   simulation:run           TICK: 110,  PC:   8,  AR:  11,  MEM_OUT: 108,  TOS: [108, 11, 3]          ,    pop       |\nDEBUG   simulation:run           TICK: 111,  PC:   9,  AR:  11,  MEM_OUT: 108,  TOS: [11, 3]               ,    swap      |\nDEBUG   simulation:run           TICK: 112,  PC:  10,  AR:  11,  MEM_OUT: 108,  TOS: [3, 11]               ,    dec       |\nDEBUG   simulation:run           TICK: 113,  PC:  11,  AR:  11,  MEM_OUT: 108,  TOS: [2, 11]               ,    jmp 3     |\nDEBUG   simulation:run           TICK: 114,  PC:   3,  AR:  11,  MEM_OUT: 108,  TOS: [2, 11]               ,    jz 12     |\nDEBUG   simulation:run           TICK: 115,  PC:   4,  AR:  11,  MEM_OUT: 108,  TOS: [2, 11]               ,    swap      |\nDEBUG   simulation:run           TICK: 116,  PC:   5,  AR:  11,  MEM_OUT: 108,  TOS: [11, 2]               ,    inc       |\nDEBUG   simulation:run           TICK: 117,  PC:   6,  AR:  11,  MEM_OUT: 108,  TOS: [12, 2]               ,    load      |\nDEBUG   simulation:run           TICK: 119,  PC:   7,  AR:  12,  MEM_OUT: 100,  TOS: [100, 12, 2]          ,    output 1  |\nDEBUG   io:log_io        OUTPUT: d\nDEBUG   simulation:run           TICK: 120,  PC:   8,  AR:  12,  MEM_OUT: 100,  TOS: [100, 12, 2]          ,    pop       |\nDEBUG   simulation:run           TICK: 121,  PC:   9,  AR:  12,  MEM_OUT: 100,  TOS: [12, 2]               ,    swap      |\nDEBUG   simulation:run           TICK: 122,  PC:  10,  AR:  12,  MEM_OUT: 100,  TOS: [2, 12]               ,    dec       |\nDEBUG   simulation:run           TICK: 123,  PC:  11,  AR:  12,  MEM_OUT: 100,  TOS: [1, 12]               ,    jmp 3     |\nDEBUG   simulation:run           TICK: 124,  PC:   3,  AR:  12,  MEM_OUT: 100,  TOS: [1, 12]               ,    jz 12     |\nDEBUG   simulation:run           TICK: 125,  PC:   4,  AR:  12,  MEM_OUT: 100,  TOS: [1, 12]               ,    swap      |\nDEBUG   simulation:run           TICK: 126,  PC:   5,  AR:  12,  MEM_OUT: 100,  TOS: [12, 1]               ,    inc       |\nDEBUG   simulation:run           TICK: 127,  PC:   6,  AR:  12,  MEM_OUT: 100,  TOS: [13, 1]               ,    load      |\nDEBUG   simulation:run           TICK: 129,  PC:   7,  AR:  13,  MEM_OUT:  33,  TOS: [33, 13, 1]           ,    output 1  |\nDEBUG   io:log_io        OUTPUT: !\nDEBUG   simulation:run           TICK: 130,  PC:   8,  AR:  13,  MEM_OUT:  33,  TOS: [33, 13, 1]           ,    pop       |\nDEBUG   simulation:run           TICK: 131,  PC:   9,  AR:  13,  MEM_OUT:  33,  TOS: [13, 1]               ,    swap      |\nDEBUG   simulation:run           TICK: 132,  PC:  10,  AR:  13,  MEM_OUT:  33,  TOS: [1, 13]               ,    dec       |\nDEBUG   simulation:run           TICK: 133,  PC:  11,  AR:  13,  MEM_OUT:  33,  TOS: [0, 13]               ,    jmp 3     |\nDEBUG   simulation:run           TICK: 134,  PC:   3,  AR:  13,  MEM_OUT:  33,  TOS: [0, 13]               ,    jz 12     |\nDEBUG   simulation:run           TICK: 135,  PC:  12,  AR:  13,  MEM_OUT:  33,  TOS: [0, 13]               ,    pop       |\nDEBUG   simulation:run           TICK: 136,  PC:  13,  AR:  13,  MEM_OUT:  33,  TOS: [13]                  ,    pop       |\nDEBUG   simulation:run           TICK: 137,  PC:  14,  AR:  13,  MEM_OUT:  33,  TOS: []                    ,    halt      |\nDEBUG   simulation:simulation    memory: DATA: [\n    0:     13\n    1:     72\n    2:     101\n    3:     108\n    4:     108\n    5:     111\n    6:     44\n    7:     32\n    8:     119\n    9:     111\n    10:    114\n    11:    108\n    12:    100\n    13:    33\n]\nINFO    simulation:simulation    output_buffer (port 1): 'Hello, world!'\nINFO    simulation:simulation    output_buffer (port 2): ''\n```\n\n### Статистика по алгоритмам\n\n```text\n| ФИО                        | алг            | LoC | code инстр. | инстр. | такт. |\n| Барсуков Максим Андреевич  | cat            | 47  | 38          | 198    | 234   |\n| Барсуков Максим Андреевич  | hello_world    | 20  | 15          | 123    | 137   |\n| Барсуков Максим Андреевич  | hello_username | 86  | 60          | 677    | 774   |\n| Барсуков Максим Андреевич  | prob2          | 69  | 44          | 513    | 597   |\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxbarsukov%2Fcsa3-stack-machine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaxbarsukov%2Fcsa3-stack-machine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxbarsukov%2Fcsa3-stack-machine/lists"}