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

Эмулятор троичного компьютера:ассемблер и инструкции

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

Эмулятор троичного компьютера:ассемблер и инструкции

Сообщение nezabudka »

Начало где то здесь
Каталог всех файлов на гитхабе
Пора писать программу и создавать язык своего асемблера.
Для начала его надо как то назвать. Ну раз процессор у нас ternary
то имя троичному ассемблеру напрашивается соответственное tas.

Сперва пишем простенькую программу и возьмем за основу синтаксис AT&T.
потом распарсим ее (препроцессор будет отдельный на баше) и переведем в трайт код.
Как помним мы условились определять размер массива при записи первым его индекcом.
Можно конечно заставить считать размер сам парсер но зачем в неотносящихся к теме вещах
усложнять себе жизнь? Вводим все данные вручную. Пишем программу на ассемблере.
.data
.str welcome 5 'hello'
.str by 2 'by'
.str etab 16 'there is a table'
.str how 18 'what is your name?'
.str chan 12 'change table'
.str buff 10 /*строчный буфер для ввода данных*/
.arr tab 10 0 1 2 3 4 5 6 7 8 9 /*целочисленный массив, если после размера массива нет данных то он инициализируется нулями*/
.int ind 3 //целое число, должно записаться в область Text
/*на этом ограничимся c типами переменных*/
.text //Все что запишется в Text

/*спросим имя*/
mov $1 %r0
mov how %r1
mov $2 %r2
syscall

/*запишем имя сырым в буфер*/
mov $2 %r0 /*услуга сканирования с терминала линукс*/
mov buff %r1 /*вынести в аргументы адрес буфера*/
mov $2 %r2 /*строчный массив, без преобразования!*/
syscall

/*поздароваемся*/
mov $1 %r0
mov welcome %r1
mov $2 %r2
syscall

/*выведем имя*/
mov $1 %r0
mov welcome %r1
mov $2 %r2
syscall

/*сообщим о выводе таблицы*/
mov $1 %r0 /*функция вывода на терминал, услуга вывода*/
mov etab %r1
mov $2 %r2 /*строчные символы*/
syscall /*вызов-прерывание, просим линукс о услуге*/

/*выводим таблицу*/
mov tab %r1
mov $1 %r0
mov $1 %r2 /*вот так, сообщим функции что это сырые байты и их надо выводить через конвертор*/
syscall

/*выводим на экран предложение записать свои значения таблицы*/
mov chan %r1
mov $1 %r0
mov $2 %r2
syscall

/*сканируем новые значения с преобразованием из oscii кода в машинный*/
mov $2 %r0 /*функция сканирования*/
mov tab %r3 /*заносим в параметры адрес буфера*/
mov $1 %r2 /*целочисленный массив с преобразованием*/
syscall

mov $0 %r4 //count
_start
mov %r4 %r0
mov ind %r1
cmp %r0 %r1
add $1 %r4
jumpe _exit //jumpe jumpne jumpl jump

mov $1 %r0
mov by %r1
mov $2 %r2
syscall
jump _start
_exit


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

Для первой программы слишком сложно, немного упростим задачу
и уберем для первой программы целочисленные
массивы. На следующем уровне еще вернемся к ним.
Все инструкции начинаются со знака табуляции
Все директивы начинаются с начала строки и с точки
Все метки имеют префикс знак подчеркивания.

.data

.str welcome 5 'hello'
.str by 2 'by'
.str how 18 'what is your name?'
.str buff 10
/*строчный буфер для ввода данных*/

.text

/*спросим имя*/
mov $1 %r0 /*непосредственное значение в регистр*/
mov how %r1 /*адресс в регистр*/
mov $2 %r2
syscall


/*запишем имя в буфер*/
mov $2 %r0 /*услуга скнирования с терминала линукс*/
mov $2 %r2 /*строчный массив, без преобразования!*/
mov buff %r3 /*вынести в аргументы адрес буфера*/
syscall

/*поздороваемся*/
mov $1 %r0
mov welcome %r1
mov $2 %r2
syscall


/*выведем имя*/
mov $1 %r0
mov welcome %r1
mov $2 %r2
syscall


mov $0 %r4 /*count*/

/*скажем 3 раза "пока"*/
_start
mov %r4 %r0
mov $3 %r1
cmp %r0 %r1
add $1 %r4
je _exit

mov $1 %r0
mov by %r1
mov $2 %r2
syscall
jmp _start
_exit


секция Data,
директива <строка>, имя массива которое заменяется адресом из
Data и этот адрес вставляется в места программы где есть имя этой переменной,
рамер массива, строка, если пустая то просто выделить место и записать по
адресу только размер по нулевому индексу.

Забыла совсем, у нас же есть стек и можно было вызывать функции
через запись параметров в стек, как это делается в 32 битной x86 архитектуре.
Ну ладно, пока проехали.
Далее по теме, я выписала в текстовый файл возможные инструкции
которые будет искать в тексте парсер, заменять на номера и выстраивать в файле
соответствующим образом. Каждая инструкция имеет свой десятичный номер,
который приобразуется в структурный трайт компилятором.

1 mov значение в регистр $1, %r0 один параметр
2 mov значение в регистр $1, %r1 один параметр
3 mov значение в регистр $1, %r2 один параметр
4 mov значение в регистр $1, %r3 один параметр
5 mov значение в регистр $1, %r4
6
7
8
9
10 mov регистр по адрессу %r0, name
11 mov значение из адреса в регистр $name, %r0
12
13
14 mov регистр в регистр %r0, %r1
15 mov регистр в регистр %r0, %r2
16 mov регистр в регистр %r0, %r3
17 mov регистр в регистр %r0, %r4
18 mov регистр в регистр %r1, %r0
19 mov регистр в регистр %r2, %r0
20 mov регистр в регистр %r3, %r0
21 mov регистр в регистр %r4, %r0 нет параметров
22
23
24 mov значение из адреса в регистре в регистр mov (%r0), %r1
25
26 jen следующая метка
27 jep предыдущая метка
28 jnen следующая метка
29 jnep предыдущая метка
30 jmp адресс один параметр
31 je адресс один параметр
32 jne адресс
33
34 add два регистра %r0, %r1
35
36 add значение и регистр /один параметр $1, %r0
37 add значение и регистр /один параметр $1, %r1
38 add значение и регистр /один параметр $1, %r2
39 add значение и регистр /один параметр $1, %r3
40 add значение и регистр /один параметр $1, %r4 один параметр
41
42 sub два регистра
43 sub значение и регистр
44
45 cmp непосредственное значение и регистр
46 cmp регистр и регистр нет параметров
47
48
49
50 syscall нет параметров
https://github.com/olecya/trinc_4003/bl ... uktsii.txt
Номера в начале строки это номера инструкций пока в десятичном виде. Пустые
строчки это резерв на будущее что бы избежать возможной групповой дефрагментации
между разными типами инструкций.

Теперь пишем парсер и компилятор руководствуясь этим примером.
Еще я вывела в файл для наглядности все цифровые значения применяемые
в эмуляторе и соответствующий им oscii код. Это файл с именем oscii.txt.
Это было необходимо так как числовая последовательность не линейна, потому,
что определяя трит мы не исользовали значение 3 доступное в двух битовом поле.
https://github.com/olecya/trinc_4003/bl ... /oscii.txt
И эта таблица может помочь в ручную редактировать бинарные файлы.
Например я открываю бинарный файл в своем vim
vim out.bin
Потом ввожу внешнюю команду в командной строке вима
:%!xxd
И у нас появляются наши битики в шестнадцатиричном виде, можно их
редактировать и конвертнуть обратно
:%!xxd -r
:wq

Приходится только работать в шестнадцатеричном представлении чисел потому, что
если мы запустим тулзу xxd -b в двоичном виде то не сможем конвертнуть
обратно. Так что с опцией -b мы вынуждены только запускать файл в режиме
чтения. Вот для этого и нужна составленная мной таблица соответствия цифровых
значений.
"I invented the term Object-Oriented and I can tell you I did not have C++ in mind." - Alan Kay
Ответить

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