может нафиг эти C-Strings
постоянное место для граблей
может нафиг эти C-Strings
постоянное место для граблей
Получилось 150 строк кода, для программы преобразующей синтаксис Си и байткод. И там почти все закончено. И 300 строк для байткода. Причем реализовано лишь 5% всех функций байткода.
Код:... void bindVar(CType& type) { // Чтение монооператора, выполнять будет потом vector<MonoOperator> mo; while(true) { if(p.ifToken("*")) { mo.push_back(moDeaddr); continue; } if(p.ifToken("&")) { mo.push_back(moAddr); continue; } if(p.ifToken("!")) { mo.push_back(moNot); continue; } if(p.ifToken("-")) { mo.push_back(moNeg); continue; } break; } bindVar_2(p, type); while(true) { if(p.ifToken("[")) { CType type1; readVar(p, -1, type1); p.needToken("]"); if(type1.addr!=0) raise("[]"); asm_index(type); continue; } if(p.ifToken("++")) { asm_callMonoOperator(moPostInc, type); continue; } if(p.ifToken("--")) { asm_callMonoOperator(moPostDec, type); continue; } break; } // Вычисление моно операторов for(int i=0; i<mo.size(); i++) asm_callMonoOperator(mo[i], type); } const char_t* operators [] = { "++", "--", "/", "%", "*", "+", "-", "<<", ">>", "<", ">", "<=", ">=", "==", "!=", "&", "^", "|", "&&", "||", "?", "=", "+=", "-=", "*=", "/=", "%=", ">>=", "<<=", "&=", "^=", "|=", 0 }; int operatorsP[] = { 13, 13, 12, 12, 12, 11, 11, 10, 10, 9, 9, 9, 9, 8, 8, 7, 6, 5, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; Operator operatorsI[] = { oInc, oDec, oDiv,oMod,oMul,oAdd,oSub,oShl, oShr, oL, oG, oLE, oGE, oE, oNE, oAnd, oXor, oOr, oLAnd, oLOr, oIf, oSet,oSAdd,oSSub,oSMul,oSDiv,oSMod,oSShl, oSShr, oSAnd,oSXor,oXOr }; void readVar(int level, CType& type) { // Чтение аргумента bindVar(type); // Чтение оператора while(true) { int l=0; Operator o = findOperator(p, level, l); if(o == oNone) return; //! Оптимизировать проверку условий. //! Команда ? : // Чтение второго аргумента CType b_type; readVar(p, l, b_type); // Выполнение опертора asm_callOperator(o, type, b_type); } } void readCommand() { if(p.ifToken(";")) return; if(p.ifToken("while")) { p.needToken("("); CType type; readVar(p, -1, type); int label1 = labelesCnt++; int label2 = labelesCnt++; asm_label(label1); asm_jz(label2, type); p.needToken(")"); readCommand(p); asm_jmp(label1); asm_label(label2); return; } if(p.ifToken("if")) { p.needToken("("); CType type; readVar(p, -1, type); p.needToken(")"); int label1 = labelesCnt++; asm_jz(label1, type); readCommand(p); if(p.ifToken("else")) { int label2 = labelesCnt++; asm_jmp(label2); asm_label(label1); readCommand(p); asm_label(label2); } else { asm_label(label1); } return; } ... }
---------- Post added at 19:46 ---------- Previous post was at 19:43 ----------
А вот кусок преобразователя байт код - асм, на который не одну неделю придется убить.
Код:void pushHL(int l, bool de=false) { Stack& bs = stack[stack.size()-1-l]; switch(bs.place) { case pConst: code.str(de ? " ld de" : " ld hl").str(", ").i2s(bs.value).str("\r\n"); break; case pVar: code.str(" ld hl, (").str(bs.name).str(")\r\n"); if(de) code.str(" ex de, hl\r\n"); break; case pVar8: code.str(" ld hl, (").str(bs.name).str(")\r\n"); code.str(" ld h, 0\r\n"); if(de) code.str(" ex de, hl\r\n"); break; case pRef: code.str(" ld hl, (").str(bs.name).str(")\r\n"); if(!de) { code.str(" ld a, (hl)\r\n"); code.str(" inc hl\r\n"); code.str(" ld h, (hl)\r\n"); code.str(" ld l, a\r\n"); } else { code.str(" ld e, (hl)\r\n"); code.str(" inc hl\r\n"); code.str(" ld d, (hl)\r\n"); } break; case pConstRef: code.str(" ld hl, (").i2s(bs.value).str(")\r\n"); if(de) code.str(" ex de, hl\r\n"); break; default: raise("3"); } } void asm_callOperator(Operator o, CType& a, CType b) { Stack& as = stack[stack.size()-2]; Stack& bs = stack[stack.size()-1]; // Преобразование константы USHORT в UCHAR if(a.baseType==cbtUChar && b.baseType==cbtUShort && bs.place==pConst) { if(bs.value>=0 && bs.value<=0xFF) b = cbtUChar; } if(a.baseType!=b.baseType || a.addr !=b.addr) raise("asm_callOperator type"); if(o==oSet) { if(a.baseType==cbtUChar && a.addr==0) { pushA(0); switch(as.place) { case pConst: raise("Нельзя изменить константу"); break; case pRef: code.str(" ld hl, (").str(as.name).str(")\r\n"); code.str(" ld (hl), a\r\n\r\n"); break; case pVar: code.str(" ld (").str(as.name).str("), a\r\n\r\n"); break; case pConstRef: code.str(" ld (").i2s(as.value).str("), a\r\n\r\n"); break; default: raise("2"); } stack.pop_back(); return; } if((a.baseType==cbtUShort || a.baseType==cbtShort) || a.addr>0) { pushHL(0); switch(as.place) { case pConst: raise("Нельзя изменить константу"); break; case pRef: code.str(" ex hl, de\r\n"); code.str(" ld hl, (").str(as.name).str(")\r\n"); code.str(" ld (hl), e\r\n"); code.str(" inc hl\r\n"); code.str(" ld (hl), d\r\n\r\n"); break; case pVar: code.str(" ld (").str(as.name).str("), hl\r\n\r\n"); break; case pConstRef: code.str(" ld (").i2s(as.value).str("), hl\r\n\r\n"); break; default: raise("4"); } stack.pop_back(); return; } raise("xxx"); return; }
Последний раз редактировалось vinxru; 11.09.2012 в 21:17.
Вчера скомпилировал первые программы. Мне этого функционала пока хватит для написания меню. А по мелочи добавлю.
Ключевые слова break, continue, return, switch, default, do {} while, union, typedef, extern, sizeof не реализованы.
Описание внешних функций (прототипы), переменных не реализованы. Например: int myFunction(int); extern int a;
Арифметика реализована только для типов uchar, ushort. Только операции +, -, ++, --, +=, -=, |=, &=, ^=, *, /, =, |, &, ^, <. Например сдвигов пока нет. Операции с типами ulong, long производить пока нельзя.
Инициализации статических переменных нет Например: char data[] = { 0x10, 0x20 }; FileInfo files[] = { { "abc", 1 }, { "def", 2 } };
Типы данных real, float, double, const, static, register, volatile, auto не реализованы. Слово register будет заставлять размещать переменную в регистре BC (или B или C).
Препроцессор не реализован, хотя там 5 минут работы. Например: #include, #define, #ifdef, #ifndef, #endif
Вставки ассемблера не реализованы.
Грамотный учет временных переменных не реализован. Резервирует больше памяти, чем нужно. Вообще переделаю на push hl, pop hl
Контроля рекурсии нет и необходимый размер стека не определяется. Рекурсия кстати будет. При рекурсивном вызове функции, все переменные используемые предыдущим вызовом функции будут копироваться в стек, а новая функция будет работать с фиксированной памятью. Не идеальный способ, но относительно быстрый. Будут проблемы при использовании указателей на локальные переменные.
Функции сравнения не оптимизированы. Сейчас первым этапом сравнения вычисляется значение True, False, а уже потом оно анализируется функцей перехода.
Сравнение
ld a, (var1)
ld hl, (var2)
cp (hl)
sbc a
Переход
or a
jp z, label
Последний раз редактировалось vinxru; 17.09.2012 в 02:03.
А как обстоят дела с макросами и #include ??
Кстати, do {} while может быть и без фигурных скобок.
do ;
while (i--);
корректный пример организации задержки.
Последний раз редактировалось predatoralpha; 12.09.2012 в 11:54.
Вообще, байткод получившегося Си очень сильно напоминает PDP11. (Что не удивительно). Все адресации переменных копируют адресацию PDP11.
Но система команд 8080 за исключением некоторых моментов то же выглядит вполне логичной, если не использовать стек.
Для всех двухадресных 16 битных команд регистр HL используется для хранения основного значения, DE для второго. Команды "EX HL, DE", "LD HL, IMM", "LD HL, (ADDR)", "ADD HL, DE", "LD (ADDR), HL" используются постоянно. Традиционно: XCHG, LHLD, LXI H, DAD D, SHLD
addr = (y*78 + 0xA000 + x - offset ) | 1234h;
; y*78
LD A, (Y)
LD D, 78
CALL MUL_UCHAR8 ; Вход A,D. Выход HL
; +0xA000
LD DE, 0A000h
ADD HL, DE
; +x
EX HL, DE
LD HL, (x) ; 8 бит
LD H, 0
ADD HL, DE
; -offset
EX HL, DE
LD HL, (offset)
LD A, E
SUB L
LD L, A
LD A, D
SBC H
LD H, A
; | 1234h
LD A, L
OR 34h
LD L, A
LD A, H
OR 12h
LD H, A
; addr=
LD (addr), HL
Но все таки не понятно, почему команды
LD BC, IMM16
LD HL, IMM16
есть, а
LD DE, нет
Последний раз редактировалось vinxru; 13.09.2012 в 13:12.
Ой, есть
---------- Post added at 11:18 ---------- Previous post was at 11:15 ----------
Парсер их поддерживает, надо только пару строк написать.
---------- Post added at 11:23 ---------- Previous post was at 11:18 ----------
Да, у меня там DO <команда> WHILE(<вражение>)
Можно так писать: do a++, b++, c++; while(c<10);
Вчера во время отладки, перебирая все варианты, написал:
while(a==1) {
a=2;
} while(a==2);
И долго пялился.
А точно нет? В Z80 всем этим командам соответствует опкодНо все таки не понятно, почему команды
LD BC, IMM16
LD HL, IMM16
есть, а
LD DE, нет
00 dd0 001
Где dd для BC=00; DE=01; HL=10; SP=11
Может в 8080 неверно декодируется команда, когда младший бит dd==1, потому команды так и не появились..
ПС. Вопрос снят.....
Ступил, я вчера думал про команду
LD DE, (ADDR)
Вот в этом куске не нужна была бы команда
EX HL, DE
LD HL, (offset)
LD A, E
SUB L
LD L, A
LD A, D
SBC H
LD H, A
Аналогично
EX HL, DE
LD HL, (offset)
ADD HL, DE
---
Традиционно:
XCHG
LHLD offset
MOV A, E
SUB L
MOV L, A
MOV A, D
SBB H
MOV H, A
Аналогично
XCHG
LHLD offset
DAD D
---------- Post added at 11:48 ---------- Previous post was at 11:28 ----------
По сравнению с PDP11 топорно очень
*a += *b;
LD HL, (B)
LD E, (HL)
INC HL
LD D, (HL)
LD HL, (A)
LD A, (HL)
INC HL
LD H, (HL)
LD L, A
ADD HL, DE
EX HL, DE
LD HL, (A)
LD (HL), E
INC HL
LD (HL), D
(Можно использовать команды 8-битной арифметики сократить программу на пару строк, но не суть).
или на PDP11
ADD @(A), @(B)
Последний раз редактировалось vinxru; 13.09.2012 в 13:16.
Тут разве что интеллектуально делать первым не HL, а DE. И команды сложения производить с ним, накапливая в нём результат. Тогда можно обойтись без обмена.
ПС. Хотя нет, арифметика работает только с HL. Блин, уже основательно подзабыл ассемблер Z80...
Да, удобная вещь. Я работал на DSP, там есть команды индексной загрузки с пост- и пред- инкрементом/декрементом, очень быстро работает перебор.
Последний раз редактировалось predatoralpha; 12.09.2012 в 13:37.
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)