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

Интерпретатор/компилятор ассемблер-подобного языка - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 10, средняя оценка - 4.90
cygwin
1 / 1 / 0
Регистрация: 10.04.2013
Сообщений: 17
13.04.2013, 19:48     Интерпретатор/компилятор ассемблер-подобного языка #1
Привет!
Чую, что изобрёл велисипед, даже скорее велопарк, но всё же, поделюсь:

Некоторое время назад начал изучать кресты, в целом не плохо продвигаюсь. Недавно решил доделать программу, которая являлась заданием к книги Дейтелов - про "симплетрон".
На этой основе сделал сначала компилятор(если так можно сказать) в байт-код. Далее транслятор этого кода и к нему дебаггер а-ля AFD

В итоге, практически довёл до конца, осталось найти ошибки и дописать логику прерываний.

Как это всё выглядит: http://s45.***********/i109/1304/d0/a945bcefc537.png

Кратко опишу синтаксис:

Операторы: mov, add, sub, inc, dec, int, loop, jmp, ret, push, push, pop, nop, cmp, jz, jnz, mul, div, mget, mset, call, mod
Из них унарные: add, sub, inc, dec, int, loop, jmp, push, pop, cmp, jz, jnz, call
Бинарные: mov, mul, div, mget, mset, mod
Не принимают значений: ret, nop

Регистры: ax, bx, cx, dx, sp, bp, si, di, cs, ds, ss, es, ip - 16 бит
Регистры ax, bx, cx, dx соответственно имеют свои старшие и младшие половины - ah, al, bh, bl, ch, cl, dh, dl - 8 бит
Из них (в отличии от реального языка) используются:
cs - начало сегмента кода
ds - начало сегмента данных
ss - начало сегмента стека

ip - смещение от cs к текущей команде
sp - указывает на вершину стека

Все остальные не используются(исполнителем), однако все регистры можно свободно менять.

Все бинарные операции кроме одной соответствуют семантике:
[команда] приёмник, источник
Исключение это mset которая записывает значение из левого операнда в адрес памяти по правому операнду
Команда же mget(все остальные команды описывать не буду - надеюсь знаете) берёт из памяти по адресу правого операнда 2 байта, или 1 байт - в зависимости от размера регистра (ah или bx, например)

Все числа могут быть записаны с приставкой h -указывает, что число HEX, иначе считается, что с/с 10.
Например: 50000, FFF0h, CCCCh, 27, 25h

Определение данных рассмотрим на примере:
data1 db 'Hello, world!\n$'
где data1 - название указателя на первый байт данных(только a-zA-Z0-9), db - тип данных, далее следует строка с \n и $ - символ конца строки
Экранирование управляющих символов не реализовано. (а их два - \n и $)
Массивы:
array1 db [100] - массив на 100 байт
array2 dw [100] - массив на 200 байт, dw - data word - слово - 2 байта
или
array1 db 1, 2, 10, 101 - массив на 4 байта
array2 dw 5, FFFFh, 123Fh - массив на 3 слова - 6 байт памяти

Как и в с++ с операторами можно производить математические операции(а-ля арифметика указателей) благодаря команде квадратных скобок:
[array1] - получает адрес первого байта в связке.
Ограничение: операция взятия адреса поддерживается только для данных и может использоватся только как правый операнд в бинарных операциях и только!
Заметьте, что можно и делить и умножать указатели, ведь они - число.

Пример:
array1 db 100, 20h

mov ax, [array1] - взять адрес числа 100(в данном случае)
add ax, 1 или inc ax
mget bl, ax - в bl записывается 20h
mov ch, FFh - это понятно, надеюсь
mset ch, ax - записать по адресу ax значение ah

Если же допустить ошибку, и сделать так:
mov cx, FFAAh
mset cx, [array1]
То запишется уже не 1, а 2 байта(т.к cx - 16 битовый регистр), соответственно получим:
Вырезка из памяти(в hex) до изменения: 64 20
После : FF AA

Бегло скажу о операторах перехода и метках
имя_метки: - метка
loop метка - переход по метке и уменьшение cx на 1
jmp - безусловный переход
jz - перейти, если не установлен zero flag, т.е cmp вернул 0 (= верное равенство)
jnz - перейте если ZF установлен, т.е cmp - не верное равенство
GF - придуманный мною флаг(костыль, ага) установлен, когда правый операнд последнего cmp больше левого.

И, наконец, функции: рассмотрим также на примере

func_label uses ax, bx:
; какие-то действия
ret

можно написать и просто func_label:
uses - говорит, что нужно перед выполнением запихнуть в стек указанные регистры, а перед ret восстановить

Вызывать как :
call func_label
Оператор call перед переходом заносит в стек адрес возврата, так, что нужно быть аккуратным в функции, можно, однако реализовать передачу параметров, если сохранить адрес возврата из стека, и потом его восстановить. Однако проще пользоваться чтением из памяти (нам ведь не критично, память это или регистр - т.к код сам исполняется виртуально, и всё и так находится в памяти)

Фух, вот и всё, что-то явно забыл, но если что - спрашивайте)
Надеюсь, хоть кто-то посмотрит код (часть я подробно прокомментировал), также высказывайте свои советы и предложения - буду рад.
Спасибо за прочтение

P.S в принцепи, легко реализуется длинная арифметика (http://pastebin.com/FHKdSAik)
GIT = https://github.com/cygwin255/CppAsm
Интерпретатор и дебаггер с некоторыми примерами прикреплены ниже.
Вложения
Тип файла: rar Release.rar (91.6 Кб, 27 просмотров)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
cygwin
1 / 1 / 0
Регистрация: 10.04.2013
Сообщений: 17
13.04.2013, 20:25  [ТС]     Интерпретатор/компилятор ассемблер-подобного языка #2
Не рассказал, про то, как код преобразуется в байт код..

Все команды байт-кода содержат только 3 байта.
Все бинарные операторы преобразуются по следующему алгоритму:
В коде: mov ax, bx
В obj файле:
push bx
mov ax


Первый байт команда, второй 2 байта - регистр (его код) или числовое значение.
У push 2 версии - первая для регистров, вторая для чисел.

Добавлено через 24 минуты
Поправка в пункте о GF(GreaterFlag) - ... правый операнд последнего cmp меньше левого.

редактировать, почему-то уже не могу.

Добавлено через 6 минут
И еще поправка - add, sub, cmp случайно в унарные записал, в бинарные, конечно.
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4237 / 2770 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
13.04.2013, 21:13     Интерпретатор/компилятор ассемблер-подобного языка #3
Цитата Сообщение от cygwin Посмотреть сообщение
Надеюсь, хоть кто-то посмотрит код
а где код то?

В целом круто конечно, мне бы лень было все это делать
cygwin
1 / 1 / 0
Регистрация: 10.04.2013
Сообщений: 17
13.04.2013, 21:26  [ТС]     Интерпретатор/компилятор ассемблер-подобного языка #4
Цитата Сообщение от Kastaneda Посмотреть сообщение
а где код то?

В целом круто конечно, мне бы лень было все это делать
на github'e, внизу оп-поста есть ссылка.
Мне иногда хотелось кинуть), но дело есть дело, и еще нужно годные проекты в портфолио собирать

Повторюсь, что принимаю любые советы по коду или фичам.

Кстати, есть извращенное желание допилить к этому всему мультизадачность, только вот думаю как реализовать. Можно поочерёдно проверять список ожидающих выполнения программ(точнее команд) и выполнять каждую по очереди, предварительно сохранив все регистры в стеке и восстановив те, что в другой программе. Но, по моему, это костыли.
Может кто знает (и может кратко рассказать) как это устроено в действительности? (ссылки на ядро никсов не предлагать, я не разберусь)
Kastaneda
13.04.2013, 21:33     Интерпретатор/компилятор ассемблер-подобного языка
  #5

Не по теме:

Цитата Сообщение от cygwin Посмотреть сообщение
на github'e, внизу оп-поста есть ссылка.
А точно, что-то не по глазам было.

Yandex
Объявления
13.04.2013, 21:33     Интерпретатор/компилятор ассемблер-подобного языка
Ответ Создать тему
Опции темы

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