Форум программистов, компьютерный форум CyberForum.ru

Эмулятор трёхадресной машины. - C++

Восстановить пароль Регистрация
 
Alexander_Bah
 Аватар для Alexander_Bah
0 / 0 / 0
Регистрация: 06.11.2010
Сообщений: 5
06.11.2010, 16:48     Эмулятор трёхадресной машины. #1
В общем, имеется задача "Эмулятор трёхадресной машины".

Каждая инструкция имеет следующий формат: код инструкции (1 байт), операнд 1 (1 байт), операнд 2 (1 байт), операнд 3 (1 байт), при этом каждый операнд задает адрес параметра в оперативной памяти машины. Далее значение по адресу заданному операндом 1 будем обозначать [ОП1]. Если предполагается числовой параметр инструкции, то используется знаковая форма записи параметра (в дополнительном коде), таким образом каждый числовой параметр представляет собой целое число в интервале [-128, 127].

Поддерживаются следующие инструкции:
0 — останов работы машины, параметры игнорируются,
1 — сложение, [ОП1] складывается с [ОП2], результат помещается в ячейку, заданную операндом 3, IP увеличивается на 4,
2 — умножение, [ОП1] переменожается с [ОП2], результат помещается в ячейку, заданную операндом 3, IP увеличивается на 4,
3 — условный переход, если [ОП1] < [ОП2], IP присваивается значение [ОП3] (иначе IP увеличивается на 4).

Машина отслеживает как минимум следующие ошибочные ситуации (в Вашей программе, возможно, будут отслеживаться и еще какие-то ситуации):
код инструкции не поддерживается машиной,
операнды инструкции размещаются за пределами оперативной памяти.

Приведенная программа (tam.c) реализует скелет эмулятора описанной машины. Необходимо дополнить программу, при этом имитация работы с внешним носителем должна быть реализована следующим образом. Код и данные считываются из файла, заданного первым параметром, если он не задан, или файл невозможно открыть, то из стандартного потока ввода. Программа должна контролировать неверный ввод (менее 256 байт). По завершению работы образ памяти выводится в файл, заданный вторым параметром программы, если он не задан — на стандартный вывод.


Есть первый файл, в котором сначала идёт операнд (то есть код того, что нужно делать, потом подряд два адреса двух чисел, с которыми нужно что-то сделать, потом адрес куда нужно записать. Вот пример входного файла:

00 | 01 E0 E1 E2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
20 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
40 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
60 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
80 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
A0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
C0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
E0 | 23 3F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00


А вот - выходного:


00 | 01 E0 E1 E2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0
20 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0
40 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0
60 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0
80 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0
A0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0
C0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
E0 | 23 3F 62 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Как сложить два двузначных шестнадцатеричных числа я ещё могу понять, хотя и с трудом.
Но возникает вопрос: как обращаться к числам, лежащим по какому-то адресу, заданному вторым и третьим параметрами в строке 00 (в данном случае это E0 и E1), а также как заносить результат в ячейку по адресу, заданному четвёртым параметром в строке 00 (в данном случае это E2)?

Буду очень благодарен всем, кто поможет. Прошу сильно не пинать, если что не так, просто с таким делом столкнулся впервые, первый курс, а же такое И сдать надо в среду.

P.S. Если кто хочет полностью ознакомиться с заданием, то оно тут, называется "Задача 4":
http://cs.karelia.ru/~aborod/inf/2010/schedule.php.ru
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.11.2010, 16:48     Эмулятор трёхадресной машины.
Посмотрите здесь:

C++ Эмулятор CHIP-8
C++ Эмулятор Вебки под Seven
C++ Эмулятор клавиатуры
C++ Эмулятор Нормальных Алгорифмов Маркова
Эмулятор мышки C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
fasked
Эксперт C++
 Аватар для fasked
4925 / 2505 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
06.11.2010, 17:05     Эмулятор трёхадресной машины. #2
Но возникает вопрос: как обращаться к числам, лежащим по какому-то адресу, заданному вторым и третьим параметрами в строке 00
Память должна быть как-то представлена, например, байтовым массивом.
Как обращаться к элементам массива я думаю вы знаете.
Alexander_Bah
 Аватар для Alexander_Bah
0 / 0 / 0
Регистрация: 06.11.2010
Сообщений: 5
06.11.2010, 17:09  [ТС]     Эмулятор трёхадресной машины. #3
Цитата Сообщение от fasked Посмотреть сообщение
Память должна быть как-то представлена, например, байтовым массивом.
Как обращаться к элементам массива я думаю вы знаете.
Да, это я знаю, по условию она представляется одномерным массивом, как
unsigned char memory [MEMSIZE], где #define MEMSIZE 256. Вы можете это увидеть, прочитав скелет программы, данный в задании по ссылке, которую я дал выше, и на котором уже надо делать всё остальное.
Но если заданы адреса, и всё идёт, как таблица, то это уже двумерный массив. В этом вся моя сложность (или моя глупость ).
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
06.11.2010, 17:11     Эмулятор трёхадресной машины. #4
Alexander_Bah, ну и что, что одномерным. Неужели так сложно по индексу вычислить адрес?
Alexander_Bah
 Аватар для Alexander_Bah
0 / 0 / 0
Регистрация: 06.11.2010
Сообщений: 5
06.11.2010, 17:18  [ТС]     Эмулятор трёхадресной машины. #5
Цитата Сообщение от silent_1991 Посмотреть сообщение
Alexander_Bah, ну и что, что одномерным. Неужели так сложно по индексу вычислить адрес?
Не то, чтобы сложно, но не совсем понятно как. И возникает вопрос: если я проведу работу со всем этим, как с обычными элементами обычного одномерного массива, то потом, если при объявлении файла (входного и выходного) были заданы параметры работы соответственно "rb" и "wb" (FILE* input = fopen("input.txt", "rb") и FILE* output = fopen("output.txt", "wb"); ), то есть работать как с бинарным, то при выводе в выходной файл всё встанет на нужные места? Такие вопросы у меня потому, что в работе бинарниками я полный ноль (а скорее даже -1 ).
fasked
Эксперт C++
 Аватар для fasked
4925 / 2505 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
06.11.2010, 17:20     Эмулятор трёхадресной машины. #6
Alexander_Bah, тогда в чем же проблема. читайте входной файл. потом memory[x]. - где x -необходимое число, прочитанное из файла.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
06.11.2010, 17:27     Эмулятор трёхадресной машины. #7
Просто читайте файл построчно в одномерный массив, и знайте, что mas[i * 32 + j] - это элемент на пересечении i-й строки и j-го столбца в исходной таблице.
Alexander_Bah
 Аватар для Alexander_Bah
0 / 0 / 0
Регистрация: 06.11.2010
Сообщений: 5
06.11.2010, 17:29  [ТС]     Эмулятор трёхадресной машины. #8
Цитата Сообщение от fasked Посмотреть сообщение
Alexander_Bah, тогда в чем же проблема. читайте входной файл. потом memory[x]. - где x -необходимое число, прочитанное из файла.
Наверное, я всё же страшно туплю...

Действительно, если всё подряд писать в memory то memory[0] будет числом, отвечающим за то, что надо делать, memory[1] и memory[2] - над чем делать и memory[3] - куда писать результат. Это всё ясно.
Но мне никак непонятно, каким образом произойдёт вычленение элементов из адресов, указанных в memory[1] и memory[2] для проведения операций над ними, а также как произойдёт запись результата эти операций в ячейку по адресу, указанному в memory[3]. То есть как это организовать?

upd
Просто читайте файл построчно в одномерный массив, и знайте, что mas[i * 32 + j] - это элемент на пересечении i-й строки и j-го столбца в исходной таблице.
Спасибо! Хоть что-то прояснилось.
Теперь, наверное, один из последних вопросов: i и j - стандартные int и десятичные. А вот в бинарнике адреса задаются совсем не десятичными числами, а комбинацией, наподобие морского боя. Как преодолеть эту проблему?
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
06.11.2010, 17:38     Эмулятор трёхадресной машины. #9
Вы для себя держите в голове, какие шестнадцатеричные адреса (как по горизонтали, так и по вертикали) соответствуют десятеричным счётчикам (скажем, для i = 0 адрес 00, для i = 1 адрес 20 и т.д.).

Добавлено через 29 секунд
А можно и не в голове, можно сделать сводную таблицу
fasked
Эксперт C++
 Аватар для fasked
4925 / 2505 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
06.11.2010, 17:58     Эмулятор трёхадресной машины. #10
Цитата Сообщение от silent_1991 Посмотреть сообщение
Просто читайте файл построчно в одномерный массив, и знайте, что mas[i * 32 + j] - это элемент на пересечении i-й строки и j-го столбца в исходной таблице.
не путайте человека, нет здесь никаких строк и столбцов. где Вы их увидели?
то написано в примере записано в одну строку. просто большинство hex-вьюверов представляют информацию в таком виде, по 0x10 элементов в строке.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
06.11.2010, 18:02     Эмулятор трёхадресной машины. #11
Да, но нам в любом случае необходимо иметь доступ к любому из этих элементов (по сути к четвёрке элементов, но и внутри каждой четвёрки надо доставать элементы), и в этом контексте это можно представить просто как таблицу.
Alexander_Bah
 Аватар для Alexander_Bah
0 / 0 / 0
Регистрация: 06.11.2010
Сообщений: 5
06.11.2010, 18:02  [ТС]     Эмулятор трёхадресной машины. #12
Цитата Сообщение от fasked Посмотреть сообщение
не путайте человека, нет здесь никаких строк и столбцов. где Вы их увидели?
то написано в примере записано в одну строку. просто большинство hex-вьюверов представляют информацию в таком виде, по 0x10 элементов в строке.
О чём Вы? Объясните понятнее, пожалуйста, я запутался.О_о
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
06.11.2010, 18:03     Эмулятор трёхадресной машины. #13
А, ну я понял, о чём вы. Но был вопрос, как разложить двумерный массив в одномерный (по сути), ведь думать он будет (составляя программы) в контексте двумерного массива.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.11.2010, 18:18     Эмулятор трёхадресной машины.
Еще ссылки по теме:

C++ Эмулятор. На С, С++
C++ Эмулятор SetTimer
Эмулятор часов настенных (стрелочных) C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
fasked
Эксперт C++
 Аватар для fasked
4925 / 2505 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
06.11.2010, 18:18     Эмулятор трёхадресной машины. #14
В общем так.
У нас имеется блок памяти
C
1
unsigned char memory[MEMSIZE];
Информация в этот блок памяти очень легко заносится обычным чтением из файла.
C
1
fread(memory, sizeof(unsigned char), MEMSIZE, pfile);
потом делаем функцию, которая выполняет операцию, относительно текущего смещения:
C
1
2
3
4
5
6
7
switch(memory[offset])
{
    case 0: // останов машины
    case 1: memory[offset + 3] = memory[offset + 1] + memory[offset + 2]; break; // сложение
    case 2: memory[offset + 3] = memory[offset + 1] * memory[offset + 2]; break; // умножение
    case 3: // условный переход
}
Как я понял загадочный IP и есть offset, о котором я говорю, то есть текущая позиция в памяти.

Тут надо сказать, что, если в файле вся инструкция (4 байта) записана именно 32-х битным числом, то могут быть ньюансы на разных машинах, я сейчас о порядке байт big-endian и little-endian.
Поэтому так просто (fread) заполнить память может не получиться.
Чтобы избежать этого можно воспользоваться небольшой модификацией функции заполнения памяти - то есть надо будет перевернуть слово в нужном порядке.
Если же инструкция записана именно побайтово, то ничего делать не надо будет.
Yandex
Объявления
06.11.2010, 18:18     Эмулятор трёхадресной машины.
Ответ Создать тему
Опции темы

Текущее время: 16:11. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru