Как любитель составлять всяческие логические головоломки теоретического применения, задался вопросом <Можно ли спроектировать процессор без системы команд с абстрактным байт-кодом? Просто разработать аппаратный парсер листингов> и на протяжении пяти лет занимался этим на досуге.
Из опытов стало очевидно, что с помощью простой прошитой таблицы в ROM объёмом 128 байтов, можно спокойно разбирать вычислительные выражения Си-листинга со скоростью до одного символа за цикл чтения одного байта. Если использовать более хитрые схематические приёмы с кучей ROM включённых цепочкой, можно добиться аппаратного проглатывания целых имён переменных за цикл. Но, это вопрос мастерства инженеринга.
Как личность, частая противоречещая собственным принципам, я поставил себе также альтернативную задачу по разработке облегчённого варианта парсера. По задумке, он должен стать основным составляющим ядра моего процессора. Тогда как разборщик листинга из стандартных ascii-символов станет лишь транслятором к тому ядру.
Итак. Ядро должно иметь всё-таки свой байт-код или, как принято говорить, микрокод. Тем самым, хочешь - не хочешь, а абстрактную систему команд всё-таки придётся разработать! А чтобы хоть как-то разгрузить себя от этого занятия и поставить какие-то стандартные рамки, за основу кодирования байт-кода системы команд я взял уже готовый мировой стандарт - UTF-8. Взял из таблицы те коды, которые не должны нигде использоваться.
В Unicode допускаются символы лишь в диапазоне 0..0x1FFFFF, а значит всё остальное можно использовать на своё усмотрение.
По этому, для начала, я захватил дипазон 0x40000000..0x7FFFFFFF под свой байт-код. Т.е. в листинге всё кодируется шести байтовой последовательностью:
11111100 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx - FC xx xx xx xx xx
Так как изначально я начинал путь по разработке именно парсера читабильных Си-выражений, байт-код должен нести в себе смысловую составляющую. А именно, дизассемблер должен отобразить такой UTF байт-код в виде Си-выражений. А ассемблер - собрать Си-выражения в UTF код. Причём, операции должны быть обратимыми. Чтобы изначально любой исполнительный код экзешника был в ранге Open-Source!
Конечно, Си-выражения должны быть лишь формально. На деле необходимы абсолютно специфические записи. Чтобы охватывать и весь потенциал низкого уровня, и сочетаться с уровнем более высоким.
Например, имена переменных должны явно указывать на ячейку памяти, а не на саму переменную где-то в памяти. Так, если мы укажем переменную "F", именно процессор, а не компилятор, которого не будет, должне знать положение этой переменной в памяти. А именно, если имя "F" имеет шестнадцатиричное представление 0x0000000F, то это и будет адресом ячейки переменной. С поправкой, что каждая переменная - 32-разрядное слово. Значит адрес сдвигается влево - 0x0000003C.
Вот составленная таблица кодирования имён переменных:
╔═╤═╤═╤═╤═╤═╤═╤═╤═╤═╤═╤═╤═╤═╤═╤═╦═╗ ║p│q│r│s│t│u│v│w│x│y│z│G│H│I│J│_║3║ ╟─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─╫─╢ ║@│a│b│c│d│e│f│g│h│i│j│k│l│m│n│o║2║ ╟─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─╫─╢ ║P│Q│R│S│T│U│V│W│X│Y│Z│K│L│M│N│O║1║ ╟─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─╫─╢ ║0│1│2│3│4│5│6│7│8│9│A│B│C│D│E│F║0║ ╠═╪═╪═╪═╪═╪═╪═╪═╪═╪═╪═╪═╪═╪═╪═╪═╬═╝ ║?│!│~│#│$│%│&│^│|│-│*│+│<│=│>│/║ <- кодирование операторов ╔═╬═╪═╪═╪═╪═╪═╪═╪═█═╧═╧═╧═╧═╧═╧═╧═╝ ║0║0│1│2│3│4│5│6│7║ ╟─╫─┼─┼─┼─┼─┼─┼─┼─╢ ║1║8│9│A│B│C│D│E│F║ ╟─╫─┼─┼─┼─┼─┼─┼─┼─╢ ║2║P│Q│R│S│T│U│V│W║ ╟─╫─┼─┼─┼─┼─┼─┼─┼─╢ ║3║X│Y│Z│K│L│M│N│O║ ╟─╫─┼─┼─┼─┼─┼─┼─┼─╢ ║4║@│a│b│c│d│e│f│g║ ╟─╫─┼─┼─┼─┼─┼─┼─┼─╢ ║5║h│i│j│k│l│m│n│o║ ╟─╫─┼─┼─┼─┼─┼─┼─┼─╢ ║6║p│q│r│s│t│u│v│w║ ╟─╫─┼─┼─┼─┼─┼─┼─┼─╢ ║7║x│y│z│G│H│I│J│_║ ╚═╩═╧═╧═╧═╧═╧═╧═╧═╝
(внизу - восьмиричная таблица)
И пример имён переменных и их положением в памяти
╔═════╤═══════════╤══════════╤══════════╤════════════════════════════════════╗ ║ Var │Octimal Id │Hexadec Id│ Address │ Shorty description ║ ╠═════╪═══════════╪══════════╪══════════╪════════════════════════════════════╣ ║ hi│00000005051│0x00000A29│0x000028A4│ ║ ║ xyz│00000707172│0x00038E7A│0x000E39E8│ ║ ║keybd│05345714244│0x2B9798A4│0xAE5E6290│ ║ ╚═════╧═══════════╧══════════╧══════════╧════════════════════════════════════╝
Т.е. если мы планируем подключать контроллер клавиатуры, нужно обязательно посадить его на едрес 0xAE5E6290 - посадка в памяти переменной "keybd".
Также решается задача с именами подпрограмм: Их расположение сохраняется по адресу посадки переменной. Т.е. адрес процедуры "hi" хранится в ячейках по адресу 0x000028A4. Тем самым, операция "hi:" явно определяет текущий указатель листинга как метку, занося адрес в ячейку по вектору 0x000028A4. Всё складывается элементарно и предельно просто.
Однако, не хватает информативности. Скажем, откуда процессор будет знать, считывать из "keybd" один байт или два? Тут обычным "byte ptr" не обойтись: громоздко!
Смотрим в правила синтасиса любого языка программирования: Имена переменных не могут начинаться с цифры!
Значит, запись "1keybd" будет явно указывать "1 byte by keybd". Заходя вперёд, замечу, что подобная запись считается устаревшей по ряду причин и теперь у меня принято её представлять как "010keybd": 010 - восьмиричное представление 8 (8 бит - байт).
Все имена переменных, состоящие из пяти символов и начинающияся со знака подчёркивания считаются служебными, так как указывают на вектор в памяти верхних границ [0xFC000000..0xFFFFFFFC].
А так как имена переменных не могут начинаться также и с "@", то ряд идентификаторов считается зарезервированными.
На данный момент завершу таблицей, с которой потом разберёмся:
0xxxxxxx|D07|ascii 110xxxxx 10xxxxxx|D11|unicode 1110xxxx 10xxxxxx 10xxxxxx|D16|unicode 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx|D21|unicode 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx|D26|reserved 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx|D31|Volume/Vector ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ .._Sextet Sextet Sextet Sextet Sextet|Octet #4 Octet #3 Octet #2 Octet #1|Reflex |Remark ~~ ~~~~~~ ~~~~~~ ~~~~~~ ~~~~~~ ~~~~~~|~~~~~~~~ ~~~~~~~~ ~~~~~~~~ ~~~~~~~~|~~~~~~~~~|~~~~~~ 00 000000 000000 000000 000000 000000|00000000 00000000 00000000 00000000|HALT | 00 0001-- ------ ------ -----x xxxxxx|000001-- -------- -------- -xxxxxxx|Char-Char| 00 001--- ------ ------ -xxxxx xxxxxx|00001--- -------- -----xxx xxxxxxxx|unicode11| 0..2047 00 01---- ------ --0000 0xxxxx xxxxxx|0001---- -------- 00000xxx xxxxxxxx| |reserved 00 01---- ------ --xxxx xxxxxx xxxxxx|0001---- -------- xxxxxxxx xxxxxxxx|unicode16| 2048..65535 00 1----- ---000 00xxxx xxxxxx xxxxxx|001----- ---00000 xxxxxxxx xxxxxxxx| |reserved 00 1----- ---0xx xxxxxx xxxxxx xxxxxx|001----- ---0xxxx xxxxxxxx xxxxxxxx|unicode20| 65536..1048575 00 1----- ---10x xxxxxx xxxxxx xxxxxx|001----- ---10xxx xxxxxxxx xxxxxxxx|unicode21|1048576..1572863 00 1----- ---11x xxxxxx xxxxxx xxxxxx|001----- ---11xxx xxxxxxxx xxxxxxxx| |reserved 01 ----xx xxxxxx xxxxxx xxxxxx xxxxxx|01----xx xxxxxxxx xxxxxxxx xxxxxxxx| |reserved 10 000000 000000 000000 000000 000000|10000000 00000000 00000000 00000000|Nop :" "| 10 000000 000000 000000 000000 000xxx|10000000 00000000 00000000 00000xxx| |option[001..007] 10 000000 000000 000000 000000 00100x|10000000 00000000 00000000 0000100x|0........|option[010..011] 10 000000 000000 000000 000000 100000|10000000 00000000 00000000 00100000|........9|option[000] 10 000000 000000 000000 000000 xxxxxx|10000000 00000000 00000000 00xxxxxx|Vector:06|"." 10 000000 000000 000000 000xxx xxxxxx|10000000 00000000 0000000x xxxxxxxx|LineWidth|option[00100..00777] 10 000000 000000 000000 00100x xxxxxx|10000000 00000000 00000010 0xxxxxxx|0........|option[01000..01177] 10 000000 000000 000000 100000 xxxxxx|10000000 00000000 00001000 00xxxxxx|......639|option[00000..00077] 10 000000 000000 000000 xxxxxx xxxxxx|10000000 00000000 0000xxxx xxxxxxxx|Vector:12|".." 10 000000 000000 000xxx xxxxxx xxxxxx|10000000 00000000 0xxxxxxx xxxxxxxx| |option[0010000..0077777] 10 000000 000000 00100x xxxxxx xxxxxx|10000000 00000000 100xxxxx xxxxxxxx|0........|option[0100000..0117777] 10 000000 000000 100000 xxxxxx xxxxxx|10000000 00000010 0000xxxx xxxxxxxx|....40959|option[0000000..0007777] 10 000000 000000 xxxxxx xxxxxx xxxxxx|10000000 000000xx xxxxxxxx xxxxxxxx|Vector:18|"..." 10 000000 000xxx xxxxxx xxxxxx xxxxxx|10000000 000xxxxx xxxxxxxx xxxxxxxx|LineIndex|option[001000000..007777777] 10 000000 00100x xxxxxx xxxxxx xxxxxx|10000000 00100xxx xxxxxxxx xxxxxxxx|0........|option[010000000..011777777] 10 000000 100000 xxxxxx xxxxxx xxxxxx|10000000 100000xx xxxxxxxx xxxxxxxx|..2621439|option[000000000..000777777] 10 000000 xxxxxx xxxxxx xxxxxx xxxxxx|10000000 xxxxxxxx xxxxxxxx xxxxxxxx|Vector:24|"...." 10 000001 xxxxxx xxxxxx xxxxxx xxxxxx|10000001 xxxxxxxx xxxxxxxx xxxxxxxx| |option[000000000..077777777] 10 000010 xxxxxx xxxxxx xxxxxx xxxxxx|10000010 xxxxxxxx xxxxxxxx xxxxxxxx|Factor+08|000000000000..000077777777 10 000011 xxxxxx xxxxxx xxxxxx xxxxxx|10000011 xxxxxxxx xxxxxxxx xxxxxxxx|Factor-08|037700000000..037777777777 10 000100 xxxxxx xxxxxx xxxxxx xxxxxx|10000100 xxxxxxxx xxxxxxxx xxxxxxxx|Factor+10| +0..+16777215 10 000101 xxxxxx xxxxxx xxxxxx xxxxxx|10000101 xxxxxxxx xxxxxxxx xxxxxxxx|Factor-10| -16777216..-1 10 000110 xxxxxx xxxxxx xxxxxx xxxxxx|10000110 xxxxxxxx xxxxxxxx xxxxxxxx|Factor+16| 0x00000000..0x00FFFFFF 10 000111 xxxxxx xxxxxx xxxxxx xxxxxx|10000111 xxxxxxxx xxxxxxxx xxxxxxxx|Factor-16| 0xFF000000..0xFFFFFFFF 10 001000 xxxxxx xxxxxx xxxxxx xxxxxx|10001000 xxxxxxxx xxxxxxxx xxxxxxxx|Stream...| 10 001001 xxxxxx xxxxxx xxxxxx xxxxxx|10001001 xxxxxxxx xxxxxxxx xxxxxxxx|Volume...|Block Volume 10 100000 111000 000000 000000 000000|10100000 11100000 00000000 00000000|LOR :"||"| 10 100000 111000 000000 000000 000001|10100000 11100000 00000000 00000001|LAND:"&&"| 10 100000 111000 000000 000000 000010|10100000 11100000 00000000 00000010|.EQ.:"=="| 10 100000 111000 000000 000000 000011|10100000 11100000 00000000 00000011|.NE.:"!="| 10 100000 111000 000000 000000 000100|10100000 11100000 00000000 00000100|.LT. :"<"| 10 100000 111000 000000 000000 000101|10100000 11100000 00000000 00000101|.LE.:"<="| 10 100000 111000 000000 000000 000110|10100000 11100000 00000000 00000110|.GT. :">"| 10 100000 111000 000000 000000 000111|10100000 11100000 00000000 00000111|.GE.:">="| 10 100000 111000 000000 000000 001000|10100000 11100000 00000000 00001000|Call :"("| 10 100000 111000 000000 000000 001001|10100000 11100000 00000000 00001001|Dash :")"| 10 100000 111000 000000 000000 001010|10100000 11100000 00000000 00001010|Else :":"| 10 100000 111000 000000 000000 001011|10100000 11100000 00000000 00001011|Bind :";"| 10 100000 111000 000000 000000 001100|10100000 11100000 00000000 00001100|Push :","| 10 100000 111000 000000 000000 001101|10100000 11100000 00000000 00001101|Load :"="| 10 100000 111000 000000 000000 001110|10100000 11100000 00000000 00001110|Drop :"."| 10 100000 111000 000000 000000 001111|10100000 11100000 00000000 00001111|Then :"?"| 10 100000 111000 000000 0000xx xxyyyy|10100000 11100000 00000000 xxxxyyyy|Action:04|'.' 10 100000 111000 000000 xxxx00 00yyyy|10100000 11100000 0000xxxx 0000yyyy| |option[0x00100..0x00F0F] 10 100000 111000 000000 xxxxxx xxyyyy|10100000 11100000 0000xxxx xxxxyyyy|Action:08|'..' 10 100000 111000 00xxxx 0000yy yyyyyy|10100000 11100000 xxxx0000 yyyyyyyy| |option[0x01000..0x010FF] 10 100000 111000 00xxxx xxxx00 00yyyy|10100000 11100000 xxxxxxxx 0000yyyy| |option[0x00100..0x0FF0F] 10 100000 111000 00xxxx xxxxxx xxyyyy|10100000 11100000 xxxxxxxx xxxxyyyy|Action:12|'...' 10 100000 1110xx xx0000 yyyyyy yyyyyy|10100000 1110xxxx 0000yyyy yyyyyyyy| |option[0x10000..0xF0FFF] 10 100000 1110xx xxxxxx 0000yy yyyyyy|10100000 1110xxxx xxxx0000 yyyyyyyy| |option[0x11000..0xFF0FF] 10 100000 1110xx xxxxxx xxxx00 00yyyy|10100000 1110xxxx xxxxxxxx 0000yyyy| |option[0x11100..0xFFF0F] 10 100000 1110xx xxxxxx xxxxxx xxyyyy|10100000 1110xxxx xxxxxxxx xxxxyyyy|Action:16|'....' 10 xxxxxx xxxxxx xxxxxx xxxxxx xxxxxx|10xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx|Vector:30|"....." 11 xxxxxx xxxxxx xxxxxx xxxxxx xxxxxx|11xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx| |reserved
Label →New label →4i = 0; 4j = 256; → →int i = 0, j = 256; →4m = 0xA0000; → → →char *m = (char*)0xA0000; → →block(0x00000000); →Binding for new nested block → →1[4m++] = 0; → →*m ++ = 0; → →4i++; → → →i ++; → →break(4i < 4j ? +1 : -1); →if(i < j) continue; else break; →block();
R_: xyz
Тема в архиве.