Команда IT специалистов выполнит подготовку инфраструктуры для вашего бизнеса.
Внедрение самых передовых решений и технологий.
Поддержка и сопровождение ваших сервисов.
Выполнение работ под "ключ", от покупки сервера, до настройки автоматизации процессов.
8(977)608-78-62 adm@nixm.ru

Эмулятор троичного компьютера: ввод-вывод

Ответить
Аватара пользователя
nezabudka
Местный говорун
Местный говорун
Сообщения: 618
Зарегистрирован: 18 апр 2015, 06:13
Откуда: Ростов на Дону

Эмулятор троичного компьютера: ввод-вывод

Сообщение nezabudka »

Цикл статей:
эмулятор троичного процессора
оперативная память
Чтобы общаться с программами на эмулируемом компьютере необходимо
написать несколько функций взаимодействия с линукс терминалом
и еще чтение программы из бинарного файла и чтение-запись текстовых
файлов. Что надо сделать. Первое две функции - сканирование с терминала
и печать строк. Второе преобразование кодов ascii символов в упращенную
таблицу. Так как предел эмулируемого процессора ограничен 80 символами
Исключим из таблицы ряд прописных символов и сдвинем все влево на 31
пункт, а оставшиеся за бортом пять знаков перенесем по отдельному
алгоритму на место неиспользованных заглавных букв. В результате
у нас образуется даже резервное поле шириной в 10 значений. Удивительно
и это всего на четырех канальной шине!
Так, базовую таблицу преобразовали, следующим шагом будет считанные
байты символов с терминала линукс преобразовать и записать в трайты.
За это отвечает ранее написанные функции decimalToTernary() которая
байт за байтом будет транслировать байт-код в трайт-код и две других
функции с самоопределяющимися назавниями writeBus() и readBus(). Готово.
Следующая задача научить компьютер определять границы массива строк,
но так же будет актуально и для массивов целых чисел.
В си это организованно тем что в конце любой строки помещается
нулевой байт код '\0' это кстати не ноль который имеет в таблице ascii
код 48. И функция чтения останавливается там где находит этот нулевой
символ. Я подумала раз мы будем вынуждены на такую метку тратить
по любому один трайт - минимально доступный опперанд данных для
нашего компьютера, то не лучше ли тогда использовать лишний трайт по
максимуму. Я решила добавить в спецификацию хранения массивов
такой порядок - первым трайтом записывается размер массива и только
потом тело самого массива. Тем самым мы исключим за ненадобностью
сперва считывать массив до метки а потом вычислять его размер и только
потом перебирать массив по индексу. Функция вывода на печать сразу
считает нулевой индекс (а это как известно адресс самого массива или
имя массива в текстовом коде), поместит полученный результат в логический
блок и проведет итерацию по символам начиная не с нуля как обычно,
а с единицы. Если мне не изменяет память такое хранение массивов
является правильным по какомуто докумету по стандартизации,
может ANSI ?
Функции printStr() и scanStr()
https://github.com/olecya/trinc_4003/bl ... .ru/main.c

Код: Выделить всё

sed '352,389!d' main.c #современем номера интервала строк станут неактуальными
Добавила в главную функцию пару строк демонстрирующих
работу написанных функций, скомпилируйте программу и запустите

Код: Выделить всё

сс -Wall -O2 main.c -o main
./main
Потом мусор удалю.
Готово, закоммитила. Пошла писать функции по загрузке бинарной программы из
файла и по работе с текстовыми файлами.
"I invented the term Object-Oriented and I can tell you I did not have C++ in mind." - Alan Kay
Аватара пользователя
nezabudka
Местный говорун
Местный говорун
Сообщения: 618
Зарегистрирован: 18 апр 2015, 06:13
Откуда: Ростов на Дону

Re: Эмулятор троичного компьютера: ввод-вывод

Сообщение nezabudka »

Задание 1
Первое, что бы запустить программу в эмуляторе достаточно
запустить эмулятор с программой в виде параметра к нему.
значит сперва наперво надо запускать эмулятор с бинарным файлом
мини-операционной_системой. Вообще то это просто, в главной
функции main() предусмотрен такой вариант, не будем на этом
останавливаться, главное понимать порядок действий.
Аргументом эмулятора у нас и будет программа с элементарной осью.
Что будет делать наша мини-ос?
Например, воображаемая программа мини-ос, которая запросит
строковые аргументы с терминала и выведет на терминал
результат своей работы. Это может быть манипулирование с массивами
строк или простой калькулятор. Скорее всего соединим все в
одной небольшой программе. НО. Между прочим строковые цифры
надо будет преобразовывать в их реальные значения и обратно.

Задача написать функцию загрузки программы в память.
Для этого нам надо будет определится с меткой в бинарном файле.
Включим воображение, по идее все будет выглядеть так:
1.Пишем на придуманном ассемблере программу
2.Включаем компилятор. Он по порядку распарсит каждую строчку и переведет
полученные результаты в два блока машинного кода - в две секции.
Знание этого нам пока достаточно.
Важно что наша функция должна различать в бинарном файле с программой
эту метку по которой будет раздельно записан код программы
в адресное пространство шины Text и данные в пространство
шины Data.
Все. Пока возьму за метку наибольшее доступное число 80,
в трайте это выглядит так (2, 2, 2, 2) или в бинарном представлении
для нашего реального компьютера так 10101010 из восьми реальных битов.
Это то, что касается главной программы мини-ос. Все другие
файлы будут доступны только из этой программы и уже в этой программе
мы будет указывать через терминальный диалог имя файла для чтения и записи.
Пока я думаю преждевременно планировать
запуск из программы мини-ос другой бинарной программы,
например текстового редактора. Может статься что на это
у нас не останется доступной памяти.
Разобрались, пишем запускатр.

Задание 2
прочтем из текстового файла ascii строки, запишем в память
прочтем и выведем в другой файл. Соответствующий алгоритм
пока реализуем в ручную в главной функции и который потом на
себя возьмет программа мини-ос. Функция вывода на монитор есть.
Остается разобрать алгоритм работы самих функций чтения-записи из
текстовых файлов, это легко.

Создаем бинарный файл и вставляем посередине метку 80.
содержимое бинарного файла должно записаться в разную память.
запишем например по аглицки такой текст "I am" и "he is" и вставим
между ними метку 80 в бинарном файле это будет выглядеть
в переводе на десятичную систему так
42(73) 1(32) 34(65) 46(77) 80 56(77) 38(69) 1(32) 42(73) 52(83)
В скобочках реальные ascii значения, а рядышком преобразованные
для троичной структуры в значения oscii(our simple code...).
Проще всего создать такой бинарный файл прямо из нашего
эмулятора. Скопируем все кроме того что содержит функция main()
в отдельный файл и назовем его tryte.h.
https://github.com/olecya/trinc_4003/bl ... ru/tryte.h
Новый файл назовем create_bin.c и к концу статьи он будет выглядеть так
https://github.com/olecya/trinc_4003/bl ... eate_bin.c
Пришлось из функций ввода-вывода выделить в отдельные
функции перевод из базового ascii кода в упрощенный оscii код.
"американский стандартный код обмена информацией" превратился в
"наш упрощенный код обмена информацией".
Прочтем из файла первую половину данных и запишем в память,
потом запишем число 80 и допишем остальные данные из файла.
Сделали.
В памяти у нас нужный массив данных. Теперь просто побитно
запишем их в файл.
Компилируем, создаем текстовый файл

Код: Выделить всё

echo -n "i amhe is" > in.txt
Посмотрим на него без маскарада

Код: Выделить всё

xxd -b in.txt
Все на месте.
запускаем программу

Код: Выделить всё

./creat_bin
Смотрим результат в получившемся файле

Код: Выделить всё

xxd -b out.bin
Программа создаст бинарный файл и одновременно прочтет его, сделает
перевод на ascii и выведет полученный результат на монитор, вот только
вместо значения 80 у нас появится знак вопроса, потому что при переводе
мы определили условие, всем встречающимся незнакомым символам мы присваиваем
знак вопроса.
И помним, в коде программы младший трит в трайте находится с лева,
а в файле младший бит в байте находится справа в выводе утилиты xxd.
Возьмем для анализа первый байт, выглядит он так 01011000. Разобем его
на триты 01 01 10 00. Здесь хорошо знакомый нам порядок следования,
справа младшие значения трайта, перевожу в троичную систему
1 1 2 0 в десятичной системе это цифра 42 а в переводе с oscii
это буква английского алфавита "i" с кодом 105. Все правильно. Глянем за одно
на четвертый байт, он у нас должен выглядеть так 10101010 тоесть 2 2 2 2
а значит это 80, все правильно. Бинарный файл у нас получился и мы
можем писать запускатр и проверять на нем работоспособность будущей
функции. Я сделала отдельный каталог на гитхабе /linuxim_ru, где выложенные
на форуме файлы больше не будут изменяться, а только добавляться новые, чтобы
избежать путаницы. Главный файл будет изменятся с коммитами и находится
он в корне с именем main.c
"I invented the term Object-Oriented and I can tell you I did not have C++ in mind." - Alan Kay
Аватара пользователя
nezabudka
Местный говорун
Местный говорун
Сообщения: 618
Зарегистрирован: 18 апр 2015, 06:13
Откуда: Ростов на Дону

Re: Эмулятор троичного компьютера: ввод-вывод

Сообщение nezabudka »

Вот что получилось.
[spoiler]

Код: Выделить всё

void upStart(char *fname) {
        Tryte_t date;
        Tryte_t addr = MIN;
        FILE  *in;
        in = fopen(fname, "r");
        assert(in);
        while(fread(&date, sizeof(Tryte_t), 1, in)) {
                addr = writeBus(Text, addr, date);
                puts("Text ok");
                if(equal(date, MAX))
                        break;
        }
        addr = MIN;
        while(fread(&date, sizeof(Tryte_t), 1, in)) {
                addr = writeBus(Data, addr, date);
                puts("Data ok");
        }
}
[/spoiler]

Код: Выделить всё

int main(int argc, char *argv[]) {
        if(argc == 2) {
                 upStart(argv[1]);
Задумка такая, применила условие и если эмулятор запускается вместе с файлом
значит он запускается с мини-ос, иначе в режиме "биоса". Функцию загрузки ос я вывела в отдельную
фукцию, остальной код в главной функции в будущем будет не нужен и является вспомогательным,
чтобы проверить правильность запись в раздельную память. Наш ранее созданный бинарный файл
прекрасно разделился по метке и записался в разные области памяти. Запускаем так

Код: Выделить всё

./upstart out.bin
https://github.com/olecya/trinc_4003/tr ... linuxim.ru
"I invented the term Object-Oriented and I can tell you I did not have C++ in mind." - Alan Kay
Ответить

Вернуться в «C/C++»