Автор: | Зимние сборы 2005 | Ограничение времени: | 2 сек | |
Входной файл: | indirect.in | Ограничение памяти: | 64 Мб | |
Выходной файл: | indirect.out |
Ваша задача — проэмулировать простую косвенную машину, предназначенную для исполнения арифметических операций.
Память этой машины представляет собой 32768 16-битных целых ячеек с номерами от 1 до 32768. Когда машина читает или пишет одну из этих ячеек, она в первую очередь проверяет число, записанное в этой ячейке. Если это число оказывается неотрицательным, то операция производится с этой ячейкой. Иначе абсолютная величина записанного в ячейке числа рассматривается как новый адрес для чтения/записи, и вышеописанный процесс повторяется. Если при выполнении операции чтения/записи машина входит в цикл, это считается ошибкой исполнения, и происходит останов машины.
У машины имеется единственный 16-битный регистр — аккумулятор. Все операции производятся с этим регистром. В случае переполнения значение берется по модулю 216 в пределах от − 32768 до 32767, как и в большинстве 16-битных систем.
Программа для этой машины состоит из не более чем 262144 инструкций. Вот список возможных команд:
Все обращения к памяти во время исполнения команд делаются так, как описано в начале условия. Деление и взятие остатка работают как операции div и mod в языке Паскаль. Все числа целые.
№ | Входной файл (indirect.in ) |
Выходной файл (indirect.out ) |
---|---|---|
1 |
|
|
2 |
|
|
3 |
|
|
Автор: | Зимние сборы 2005 | Ограничение времени: | 2 сек | |
Входной файл: | 2instr.in | Ограничение памяти: | 64 Мб | |
Выходной файл: | 2instr.out |
Возможно, самой важной инструкцией процессора 8086 является команда «pop sp», которая берёт значение указателя стека с вершины стека.
В дополнение к этой команде в процессоре 80486 была добавлена другая очень важная инструкция для работы с регистром указателя стека — «bswap sp». Она меняет местами старший и младший байт указателя.
Вам дано начальное значение регистра sp и содержимое памяти. Постройте самую короткую программу, которая после своего завершения получит в sp заданное конечное значение. Программа должна состоять только из операций «pop sp» и «bswap sp».
Первая строка содержит два шестнадцатибитных числа в пределах от 0000 до FFFF — начальное и конечное значение регистра sp. Следующие 4096 строк содержат дамп сегмента памяти.
Дамп задается в формате [8 байт][2 пробела][8 байт], где [8 байт] - это 8 значений последовательных байтов, разделенных одним пробелом. Байт задается как шестнадцатеричное число в пределах от 00 до FF, имеющее ровно две цифры.
В первой строке выведите число байтов кода в кратчайшей программе в десятичной системе счисления. Начиная со второй строки, выведите дамп кода получившейся программы в том же формате, что и во вводе. Последняя (возможно, незавершенная) строка дампа должна быть обязательно завершена переводом строки без лишних пробелов сразу же после последнего выведенного байта.
Если существует несколько кратчайших программ, выведите лексикографически наименьшую.
Если невозможно решить задачу для заданного дампа и значений sp, выведите единственную строку со словом IMPOSSIBLE.
№ | Входной файл (2instr.in ) |
Выходной файл (2instr.out ) |
---|---|---|
1 |
|
|
Автор: | Зимние сборы 2005 | Ограничение времени: | 2 сек | |
Входной файл: | ram.in | Ограничение памяти: | 64 Мб | |
Выходной файл: | ram.out |
RAM-машина — это простейшая модель вычислительной машины, зачастую используемая для анализа различных алгоритмов. Эта машина состоит из процессора, памяти, а также устройств ввода и вывода. Память RAM-машины представляет собой адресное пространство из регистров, в каждом из которых может быть записано некоторое целое число. Устройство ввода — это лента, с которой RAM-машина может читать в память входные данные. Кроме того, RAM-машина может выводить некоторые числа из своей памяти на устройство вывода.
Операндом команды для процессора RAM-машины может являться либо непосредственное значение (записывается =i), либо значение регистра с номером i (записывается i в записи программы, кроме того, для удобства определения системы команд часто используют обозначение c(a) для обозначения регистра с номером, равным значению параметра a), либо значение регистра с номером, записанном в регистре номер i (т.е. c(c(i)), в записи программы это обозначается как *i). Также для удобства описания вводится запись v(a), определяемая следующим образом:
Программа для RAM-машины представляет собой пронумерованную (начиная с 0) последовательность команд для процессора. Процессор RAM-машины умеет исполнять следующие команды:
Команда | Действие | Описание |
---|---|---|
LOAD a | c(0) ← v(a) | Загружает в регистр 0 значение v(a) |
STORE i | c(i) ← c(0) | Загружает в регистр i значение регистра 0 |
STORE *i | c(c(i)) ← c(0) | Загружает в регистр c(i) значение регистра 0 |
ADD a | c(0) ← c(0)+v(a) | Складывает c(0) и v(a) |
SUB a | c(0) ← c(0)-v(a) | Вычитает из c(0) значение v(a) |
MULT a | c(0) ← c(0) × v(a) | Умножает регистр 0 на v(a) |
DIV a | c(0) ← c(0) div v(a) | Целочисленное деление регистра 0 на v(a) |
READ i | c(i) ← вход | Читает из ввода значение в регистр i |
READ *i | c(c(i)) ← вход | Читает из ввода значение в регистр c(i) |
WRITE a | выход ← v(a) | Выводит на устройство вывода значение v(a) |
JUMP b | | Безусловный переход на команду номер b |
JGTZ b | | Переход на команду номер b, если c(0)>0 |
JZERO b | | Переход на команду номер b, если c(0)=0 |
HALT | | Окончание работы программы |
Вашей задачей будет промоделировать работу RAM-машины. При моделировании вы можете считать, что RAM-машина содержит всего 1000 регистров (пронумерованных от 0 до 999), и работает с 16-битными знаковыми целыми числами. Деление работает так же, как операция div в языке Паскаль.
В первой строке входного файла содержатся числа m и n — число команд в программе и количество чисел на входной ленте RAM-машины. Далее в m строках записана программа для RAM-машины, по одной команде на строку, в каждой строке записаны название команды и операнд (если он есть), разделенные пробелами. После описания программы идут n целых чисел, разделенные произвольным количеством пробелов и переводов строки — числа, которые будут читаться со входной ленты при выполнении команд READ.
Гарантируется, что входные данные корректны, что программа не будет использовать значения регистров, в которые не загружено никакое число, а также читать с устройства ввода больше чисел, чем присутствует в описании входных данных или переходить на команду с номером, которой нет в программе. Кроме того, программа не будет исполнять больше, чем 10,000,000 команд. Также программа не будет исполнять операций, которые могут приводить к переполнению или любой другой ошибке (например, делению на 0).
В выходной файл должны быть выведены (по одному на строку) все числа, которые исполняемая программа выдала с помощью команды WRITE.
№ | Входной файл (ram.in ) |
Выходной файл (ram.out ) |
---|---|---|
1 |
|
|
2 |
|
|