13.12.2016, 03:06
|
|
Профессор
|
|
Регистрация: 16.09.2009
Сообщений: 253
|
|
Замыкания и расширение области видимости (движок эмулятора ПК)
Нe получается никак решить проблему с замыканием.
<script>
String.prototype.x = function(n, j) {var s = this, buf = ""; while(n > 0) { if(n&1) buf+=s; s+=(j?j:"")+s; n >>= 1; } return buf; }
Number.prototype.toHex = function(n) {
return (n < 0 ? "0x" : "") + ((((this >> 16) & 0x0000FFFF) | 0x00010000).toString(16) + ((this & 0x0000FFFF) | 0x00010000).toString(16).substr(1)).substr(-Math.abs(n)).toUpperCase();
}
Number.prototype.hi = function(n) {
if(isFinite(n))
return (this & 255) | ((n & 255) << 8);
return (this >> 8) & 255;
}
Number.prototype.lo = function(n) {
if(isFinite(n))
return (this & 0xFF00) | (n & 255);
return this & 255;
}
var CPU =
function(pattern) {
var matrix = {
actions : [], // Instructions set
commands : [], // Assembly commands
};
var user = {
instructions : null,
logs : null,
};
var Logging = [];
// Отображение таблицы команд
this.showCommands = function(e) {
user.instructions = e;
};
function command_set(ic, ib) {
var large = false,
white = "<b style=background-color:white><u style=color:black>",
cols = 7,
dump = [],
Acts = [],
opers = [];
for(code = 0; code < 256; ++ code) {
var Action = matrix.actions[code];
var Act = Action.command + " ".x(cols),
Regs = Action.operand,
len = Regs.length - cols;
if(len > 0)
Act = Act.substr(0, cols - len) + Regs,
Regs = Regs.substr(-cols);
Act += " ",
Regs += " ";
html = "<span class=CPU_Group_" + Action.color + ">#</span>";
Act = Act.substr(0, cols);
Regs = Regs.substr(0, cols);
Acts.push(html.replace("#", (ic == code ? white + Act + "</u></b>" : Act)));
opers.push(html.replace("#", (ic == code ? white + Regs.replace("IB", ib.toHex(2)) + "</u></b>" : Regs)));
if((code & 15) == 15)
dump.push("║" + ("<span style=text-decoration:overline>" + (code >> 4).toHex(1) + "║" + Acts.join("│") + "</span>║<br />")
+ ("║ ║"+ opers.join("│") + "║").replace(/(IB|XX)/g, "<b style=color:cyan>$1</b>")),
Acts = [], opers = [];
}
for(code = 0; code < 16; ++ code)
opers.push("╝" + code.toHex(1) + "╚════");
user.instructions.innerHTML = (isFinite(ic) ? ic.toHex(2) + " " : "___") + "╔═╗ ".x(16) + "<br />" +
"╔═╦" + opers.join("╤") + "╗<br />" +
dump.join(large ? "<br />╟─╫" + "─".x(cols).x(16, "┼") + "╢<br />" : "<br />") +
"<br />╚═╩" + "═".x(cols).x(16, "╧") + "╝";
}
this.command_set = command_set;
// Начало инициализации
if(pattern) {
var res, tmp, id;
// Коллекция битов дешифратора
var pins = [],
pinex = /^([A-Z_]+)\?$/gm,
pinexp = [];
// Коллекция набора операндов
var opers = [],
operex = /^([^\s]{1,13})\t(.*)$/gm,
operexp = [],
operact = [],
operem = [];
// Коллекция командной модели
var models = [],
modelex = /^([0X1_]+)([A-Z_])\t([^:\t]+)\t*([^:\t]*?)\t*:(.*?)((?:\/\/)(.*))?$/gm;
// Начинаем разбирать представленный шаблом
if(!(res = pattern.match(pinex)))
return alert("Where the pins?");
// Разбираем битовые поля инструкций
res[0].replace(/[_?]/g, "").split("").reverse()
.forEach
(function(id, x, whole) {
(((pins[id]) || (pins[id] = [])) && pins[id]).push("(((x >> " + x + ") & 1) << " + pins[id].length + ")");
});
// Объявляем функциональное считывание
for(id in pins)
pinexp.push("$" + id),
pins["$" + id] = new Function("x", "return " + pins[id].join(" | ")),
delete pins[id];
// Собираем имена полей в выражение
pinexp = new RegExp("(" + pinexp.join("|").replace(/(\$)/g, "\\$1") + ")", "g");
if(!(res = pattern.match(operex)))
return alert("Where the operands?");
// Разбираемся с операндами
res.forEach
(function(str) {
var str = str.split(/\t+/);
operexp.push(str[0]);
opers[str[0]] = str[1];
operact[str[0]] = str[2];
operem[str[0]] = str[3] || str[1];
});
// Собираем имена операндов в выражение
operexp = new RegExp("(" + operexp.join("|").replace(/(\$)/g, "\\$1") + ")", "g");
if(!(res = pattern.match(modelex)))
return alert("Where the model???");
// Разбираемся и строим полную командную модель
res.forEach
(function(desc) {
desc.replace(modelex,
function(str, mask, group, command, operand, action, description) {
mask = mask.replace(/_/g, "");
var $D, commands, operands, actions, descriptions;
base = parseInt(mask.replace(/X/g, "0"), 2), // 0XX1X0X1XX -> 0001000100
over = parseInt(mask.replace(/X/g, "1"), 2), // 0XX1X0X1XX -> 0111101111
last = parseInt(mask.replace(/./g, "1"), 2), // 0XX1X0X1XX -> 1111111111
mix = base ^ over ^ last; // 1001010100
// Пробегаем по всем комбинациям неопределённых битов
for($D = base; $D <= over; $D = ((($D | mix) + 1) & ~mix) | base) {
if(matrix.actions[$D])
continue;
// Корректируем объявления шаблона с подстановкой конкретных числовых величин
commands = command .replace(pinexp ,function($id) {return pins[$id]($D); });
operands = operand .replace(pinexp ,function($id) {return pins[$id]($D); });
actions = action .replace(pinexp ,function($id) {return pins[$id]($D); });
descriptions = description .replace(pinexp ,function($id) {return pins[$id]($D); });
// Проходимся второй раз с подстановкой перечисленных имён шаблона конкретными ссылками
commands = commands .replace(operexp,function($id) {return opers[$id]; });
operands = operands .replace(operexp,function($id) {return opers[$id]; });
actions = actions .replace(operexp,function($id) {return operact[$id]; });
descriptions = descriptions .replace(operexp,function($id) {return operem[$id]; });
Logging.push($D.toHex(2) + "#" + group + "|" + commands + "\t" + operands + "\t{" + actions + "}" + descriptions);
// Строим функциональную матрицу системы команд для эмуляции и дизассемблера
matrix.actions[$D] = {
color : group, // Цвет группы, к которой относится операция
command : commands, // Название команды
operand : operands, // Операнды команды
action : actions, // Функциональное описание действия команды
remark : descriptions, // Краткое описание инструкции
};
if(!matrix.commands[commands])
matrix.commands[commands] = [];
// Строим обратную матрицу для ассемблера
operands.split("/")
.forEach(function(operands) {
if(!(operand in matrix.commands[commands]))
matrix.commands[commands][operands] = $D;
});
};
});
});
/**/document.getElementById("Logging").innerText = Logging.join("\r\n");
}
};
var cpu = null;
function main() {
cpu = new CPU(document.getElementById("Pattern").textContent);
cpu.showCommands(document.getElementById("Commands"));
cpu.command_set(0x55, 1);
}
</script>
<style>
pre#Commands {
color : lightgreen;
cursor : default;
}
span.CPU_Group__{
background-color: #012;
cursor : pointer;
}
span.CPU_Group_A{
background-color: #772; <!--ALU-->
}
span.CPU_Group_B{
background-color: #764; <!--JMP-->
}
span.CPU_Group_C{
background-color: #888; <!--HLT-->
}
span.CPU_Group_D{
background-color: #663; <!--INX-->
}
span.CPU_Group_E{
background-color: #363; <!--POP-->
}
span.CPU_Group_F{
background-color: #367; <!--MOV-->
}
span.CPU_Group_X{
background-color: #437; <!--???-->
}
var {
display :none
}
</style>
</head>
<body onload='main()'>
<var id=Pattern
>P0 BC reg.bc B and C
P2 DE reg.de D and E
P4 HL reg.hl H and L
P6 PSW reg.acc Status
Q0 B reg.bc B
Q1 C reg.bc C
Q2 D reg.de D
Q3 E reg.de E
Q4 H reg.hl H
Q5 L reg.hl L
Q6 M reg.m Memory
Q7 A reg.acc Accumulator
R0 B reg.bc.hi B
R1 C reg.bc.lo C
R2 D reg.de.hi D
R3 E reg.de.lo E
R4 H reg.hl.hi H
R5 L reg.hl.lo L
R6 M reg.mem Memory
R7 A reg.acc.lo Accumulator
ALU0 ADD 0 Addition
ALU1 ADC 0 Addition with carry
ALU2 SUB 0 Subtraction
ALU3 SBB 0 Subtraction with borrow
ALU4 ANA 0 Bitwise conjunction
ALU5 XRA 0 Bitwise exclude disjunction
ALU6 ORA 0 Bitwise disjunction
ALU7 CMP 0 Comparation
ZZ_YYY_XXX_?
00_000_000_C NOP : //No operation
00_110_001_B LXI SP,IW :reg.sp=$IW() //
00_XX0_001_B LXI P$Y,IW :P$Y=$IW() //Load address into P$Y
00_XXX_110_F MVI R$Y,IB :Q$X=$IB() //Flip-flop translation byte to R$Y
01_110_110_F HLT :reg.pc -- //Halting
01_XXX_XXX_F MOV R$Y,R$X :Q$X=R$Y(R$X()) //Flip-flop translation R$X to R$Y
10_XXX_XXX_A ALU$Y R$Y :ALU$Y(R$Y()) //ALU$Y
11_XX0_001_E POP P$Y :P$Y=STACK() //Pop P$Y from stack
11_XX0_101_E PUSH P$Y :STACK(P$Y) //Push P$Y to stack
XX_XXX_XXX_X ??? : //
</var>
<pre id=Commands></pre>
<pre id=Logging></pre>
</body>
Нe думал, что придётся просить помощи в элементарном.
Мне нужно организовать всё так, чтобы анонимные функции видели локальные переменные.
Спасибо!
P.S.: Пример выше - очень абстрактный. И я здорово запутался в проблеме видимости локальных переменных.
Пришлось явно всё передавать, да ещё и with(...) встроить...
Последний раз редактировалось Paguo-86PK, 02.03.2017 в 00:51.
Причина: Построение генератора по шаблону
|
|
22.02.2017, 03:02
|
|
Профессор
|
|
Регистрация: 16.09.2009
Сообщений: 253
|
|
Удалoсь таки заставить "славный говнокод" работать
(доработал представленное выше, но не разобрался с замыканиями)
Нa этих выходных решил попробовать написать эмулятор с нуля, руководствуясь накопленным опытом.
Основной задачей было поставлено написать некий универсальный движок, с помощью которого можно описать нужный процессор простым шаблоном, который развернётся в работающую модель с комплектом 3 в 1: Эмулятор, Дизассемблер, Ассемблер. При этом, не нужно было бы сурово переделывать сам js-текст.
В итоге, уложился в трое суток бессонных ночей отладки.
Получился компактный - 1500 строк и 60кб.
P.S.: Если браузерная совместимость не подведёт, эмулятор запустится сразу под рандомным мусором в его ОЗУ…
Необходимо нажать кнопку Reset, а затем - Start.
Клавиши тоже должны работать: F1-Шаг отладки, F4-Полный ход, F9-Брейк-пойнт.
Также, F7-Выбор настраиваемого параметра(FPS, IPC, IPS), F6/F8-Декремент/Инкремент параметра.
Пожалуйста, отпишитесь, у кого - какой результат.
Кстати, шаблон можно редактировать прямо в процессе (кнопка Matrix) и изменить всю систему команд на ходу (двойной клик по той же Matrix)…
(по идее, можно описать 6502. Для Z80 пока ещё не хватает поддержки префиксов, что довольно поправимо)
|
|
27.02.2017, 00:00
|
|
Профессор
|
|
Регистрация: 16.09.2009
Сообщений: 253
|
|
Сообщение от Rise
|
локализуй проблему...
|
Сил уже нет. Всё перепробовал:
var BUG =
function(formula) {
var expression =
function() {
return 0;
},
adjust = 7,
times = 3;
function Bug(n) {
var no = n;
while(n > 0) {
console.log("OUTSIDE: Adjust is " + adjust + ", N is " + n);
*!*console.log("RESULT is " + expression.bind(self).call());*/!*
if(no == n) {
console.log("BUGGEST");
n --;
}
no = n;
}
if(-- times > 0)
setTimeout(this.Bug.bind(self), 2500);
}
if(!!formula)
expression = (new Function("", formula));
this.Bug = Bug;
return this;
};
var Bugs = new BUG(
" console.log(\"INSIDER...\");\
console.log(\"INSIDE: Adjust is \" + this.adjust);\
console.log(\"INSIDE: N is \" + this.n);\
try {\
console.log(\"INSIDE: Adjust is \" + adjust);\
} catch(e) {\
console.log(\"INSIDE: Adjust is ???\");\
}\
try {\
console.log(\"INSIDE: N is \" + n);\
} catch(e) {\
console.log(\"INSIDE: N is ???\");\
}\
try {\
console.log(\"return n -- * adjust\");\
return n -- * adjust;\
} catch(e) {\
}\
try {\
console.log(\"return this.n -- * this.adjust\");\
return this.n -- * this.adjust;\
} catch(e) {\
console.log(\"Total Error...\");\
}\
return 0;"
);
alert(Bugs.Bug(3));
P.S.: Проблема в том, что из-под eval всё работает и все переменные доступны и обновляемы.
А вот красиво обвернув в функцию никак не получается…
Выше я обновил пример - пишу эмулятор. И он пока весь держится на eval… Хотелось бы иначе
Спасибо!
Последний раз редактировалось Paguo-86PK, 02.03.2017 в 00:24.
|
|
28.02.2017, 10:40
|
|
Профессор
|
|
Регистрация: 16.09.2009
Сообщений: 253
|
|
Сообщение от Rise
|
Paguo-86PK, можно сразу передавать функцию:
var BUG = function(formula) {
var adjust = 7;
this.Bug = function(n) {
while (n--) {
console.log("OUTSIDE: Adjust is " + adjust + ", N is " + n);
console.log("RESULT is " + formula(adjust, n));
}
return this;
};
};
var Bugs = new BUG(function(x, y) {
return x * y;
});
Bugs.Bug(5);
|
Eсли бы всё было так просто
Вы с эмуляторами сталкивались?
Пишу сейчас собственный под РАДИО-86РК, где нудная цепочка "switch(машинный_код) case инструкция№1 ... case инструкция№255" заменена на массив.
Т.е. имеется структура регистров
var Register =
function(x) {
return {
id : "",
fx : 0,
hi : (x >> 8) & 255,
lo : x & 255,
start : x & 65535,
get reset() {
this.lo = this.start & 255,
this.hi = this.start >> 8;
return this.lo | (this.hi << 8);
},
get h() {
return this.hi;
},
set h(x) {
this.fx = (x >> 8) & 1;
this.hi = (x &= 255);
this.fx |= (x & 128) | (!x ? 64 : 0);
x ^= x >> 4;
x ^= x << 2;
x ^= x >> 1;
this.fx |= x & 4;
//console.log(this.id + ":" + (this.lo | (this.hi << 8)).toHex(-4));
},
get l() {
return this.lo;
},
set l(x) {
this.fx = (x >> 8) & 1;
this.lo = (x &= 255);
this.fx |= (x & 128) | (!x ? 64 : 0);
x ^= x >> 4;
x ^= x << 2;
x ^= x >> 1;
this.fx |= x & 4;
//console.log(this.id + ":" + (this.lo | (this.hi << 8)).toHex(-4));
},
get x() {
//console.log(this.id + ":" + (this.lo | (this.hi << 8)).toHex(-4));
return this.lo | (this.hi << 8);
},
set x(x) {
this.lo = x & 255, this.hi = (x >> 8) & 255;
//console.log(this.id + ":" + (this.lo | (this.hi << 8)).toHex(-4));
},
get m() {
//console.log(this.id + "[" + (this.lo | (this.hi << 8)).toHex(-4) + "]:" + (ram[this.lo | (this.hi << 8)] & 255).toHex(-2));
return ram[this.lo | (this.hi << 8)] & 255;
},
set m(x) {
ram[this.lo | (this.hi << 8)] = x & 255;
//console.log(this.id + "[" + (this.lo | (this.hi << 8)).toHex(-4) + "]=" + (ram[this.lo | (this.hi << 8)] & 255).toHex(-2));
},
get n() {
var x = this.lo | (this.hi << 8);
this.lo = (this.lo + 1) & 255;
this.hi = !this.lo ? (this.hi + 1) & 255 : this.hi;
return ram[x];
},
set n(x) {
this.hi = !this.lo ? (this.hi - 1) & 255 : this.hi;
this.lo = (this.lo - 1) & 255;
ram[this.lo | (this.hi << 8)] = x & 255;
},
get w() {
var x = this.lo | (this.hi << 8), d;
this.lo = (this.lo + 2) & 255;
this.hi = this.lo < 2 ? (this.hi + 1) & 255 : this.hi;
d = ram[x] + 256 * ram[(x + 1) & 65535];
//console.log("[" + x.toHex(-4) + "]:" + d.toHex(-4));
return d;
},
set w(x) {
this.hi = this.lo < 2 ? (this.hi - 1) & 255 : this.hi;
this.lo = (this.lo - 2) & 255;
ram[this.lo | (this.hi << 8)] = x & 255;
ram[(this.lo + (this.hi << 8) + 1) & 65535] = (x >> 8) & 255;
//console.log("[" + (this.lo | (this.hi << 8)).toHex(-4) + "]=" + x.toHex(-4));
},
}
};
В основном цикле эмулятора, когда просто через eval пропускается нечто типа "r.a.h = r.b.l" - полный порядок. А если всё красиво обернуть в функции { r.a.h = r.b.l; }, то никак не получается заставить видеть r-структуру.
Вы сами понимаете, что подготовить все 256 функций к вызовам и потом их вызывать - куда быстрее, чем каждый раз интерпретировать eval'ом тысячи команд за раз.
P.S.: Сейчас нашёл более-менее работающий способ: Все 256 функций при инициализации прописываю прямо внутри операционного цикла, к которому насильно привязываю ещё и регистры с памятью.
Некрасиво, обвёрнуто в with(this), но заработало…
А передавать всё через аргументы - пробовал в прошлом году. Огороды скобок и некоторые вещи сделать нельзя.
(у меня R$1 разворачивается в r.a.l, что раньше было R$1(R$1()+R$2()) как r.a.l(r.a.l()+r.b.h()) и тяжело визуально наблюдалось. сейчас - просто R$1+=R$2 за r.a.l+=r.b.h, что коротко и понятно)
Не просил бы помощи, если бы задача была проще.
Нужно мне именно так, как я описал выше. И никак иначе
Последний раз редактировалось Paguo-86PK, 02.03.2017 в 00:22.
|
|
28.02.2017, 17:17
|
|
junior
|
|
Регистрация: 29.11.2011
Сообщений: 3,924
|
|
Не знаю, что тут у вас происходит, много разных непонятных символов
Судя по
Сообщение от Paguo-86PK
|
(у меня R$1 разворачивается в r.a.l, что раньше было R$1(R$1()+R$2()) как r.a.l(r.a.l()+r.b.h()) и тяжело визуально наблюдалось. сейчас - просто R$1+=R$2 за r.a.l+=r.b.h, что коротко и понятно)
|
Если я правильно понял, тебе нужно определить (описать) свой язык, операторы, а дальше делать то, что требуется в рамках этого языка. В прологе так можно было. Применительно к js, вероятно, что-нибудь из этого:
+ https://pegjs.org/
+ https://github.com/harc/ohm
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук
|
|
01.03.2017, 15:12
|
|
Профессор
|
|
Регистрация: 16.09.2009
Сообщений: 253
|
|
Основные принципы организации шаблона
Конечнo, Спасибо за советы…
В самом начале темы я пост поправил. Вы запускали пример в нём?
Имеется конкретный эмулятор (нажмите кнопку V между Console и Full Screen, чтобы увидеть таблицу команд), который расписан классически, как можете убедиться, без выкрутасов (древом switch(код_команды) case код_nn: ействие_nn…).
Когда переписывался с его автором и пытался чуточку подогнать его под свои фантазии, приходилось модифицировать и древо ассемблера, и древо дизассемблера, и саму визуальную таблицу, и ядро эмуляции. Что крайне сложно для отладки.
Тогда появилась мысль, разработать некий автоматический конструктор для эмуляции. Из справочника по конкретному процессору переводишь таблицу в некоторый шаблон, а библиотека сама его "переварит" и всё сделает без особого напряга со стороны пользователя. Если что-то не так работает, правится только шаблон…
В детстве изучил кучу советской справочной литературы отца на темы ПЛ/1, ПЛ/М, Ада, Фортран, Лисп, Пролог, Паскаль, Форт, Си, АПЛ и т.д. Т.е. когда сел за более-менее приветливый терминал, имел некоторые представления о том, как заставить машину делать что-то именно моё уникальное. Ассемблер был роскошью и команды писал прямо дампом.
Сейчас задуманное работает. До 512 срабатываний таймера в секунду с обработкой до 2048 инструкций (512*2048=до миллиона команд в секунду). И всё держится на eval, а разумно бы в new Function завернуть. В функцию нельзя передавать аргументы. Вернее, можно, но их будет с несколько десятков, что расходно и бессмысленно.
Тем более, на выходе - ничего нет. Процесс игнорирует результат eval и не принимает значения от function-return. Т.е. оперирование идёт со всеми окружающими структурами и массивами. Понимаете?
P.S.: Когда впервые пересел с IBM-PC/XT - DOS 3.11 за Pentium-I под Windows'98, через год изучения Visual Basic 4 написал свой первый эмулятор с кучей if-then-else/switch-case и т.д.
Теперь хочу автоматизировать всё это дело…
P.P.S.: Несколько слов о принципах шаблона и его "разворачивания"…
Аналогично оператору casex в шаблоне перечисляются все возможные комбинации битов кода для каждой операции:
Код:
|
1X0X - Бинарная маска шаблона: Здесь X указывает на биты с произвольным линейным содержимым
==== - Разворачивается в 2²=4 (двойка в степени количества X в строке) комбинации:
1000 - Базовая комбинация
1001 - Первая комбинация
1100 - Вторая комбинация
1101 - Третья комбинация |
В шаблоне указываются также битовые поля операционных констант, закреплённых за конкретным кодом:
Код:
|
?XYX? - Здесь за X берутся биты 3 и 1 соответственно. Только за Y берётся бит 2,
Y???? - Затем и бит 4 - в обратном порядке. Знак вопроса в конце (?) обязателен
----- - Все перечисленные имена констант далее действуют в целом шаблоне
XXXX - Всё это дело разворачивается в
==== - следующую таблицу бинарной маски:
0000 - $X = 00, $Y = 00
0001 - $X = 01, $Y = 00
0010 - $X = 00, $Y = 10
0011 - $X = 01, $Y = 10
0100 - $X = 10, $Y = 00
0101 - $X = 11, $Y = 00
0110 - $X = 10, $Y = 10
0111 - $X = 11, $Y = 10
1000 - $X = 00, $Y = 01
1001 - $X = 01, $Y = 01
1010 - $X = 00, $Y = 11
1011 - $X = 01, $Y = 11
1100 - $X = 10, $Y = 01
1101 - $X = 11, $Y = 01
1110 - $X = 10, $Y = 11
1111 - $X = 11, $Y = 11 |
Тем самым, в строке конкретной операции все операционные константы при разборе шаблона подменяются на конкретные значения:
Код:
|
0XX1 DO R$Y+=R$X
==== - Данная выше строчка развернётся в 4:
0001 DO R0+=R1
0011 DO R2+=R1
0101 DO R0+=R3
0111 DO R2+=R3 |
Что значительно облегчает описание всех возможных комбинаций конкретного набора однотипных инструкций.
В шаблоне также можно описать псевдонимы для операций и регистров, закрепив за ними конкретные действия:
Код:
|
R0 Door Open_Door
R1 Desk Wash_Desk
R2 Cat Make_Purr
R3 Dog Keep_Home |
Тем самым, представленный выше шаблон совсем изменится в развёртке:
Код:
|
0XX1 DO R$Y+=R$X :R$Y(R$X)
==== - Данная выше строчка развернётся в 4:
0001 DO Door+=Desk :Open_Door(Wash_Desk)
0011 DO Cat+=Desk :Make_Purr(Wash_Desk)
0101 DO Door+=Dog :Open_Door(Keep_Home)
0111 DO Cat+=Dog :Make_Purr(Keep_Home) |
Чем достигается описывание довольно сложных алгоритмических выражений с шаблонной подстановкой конкретных комбинаций за конкретными кодами.
Разрабатываемая маленькая библиотека делает всё сама. При этом, когда Вы опишете шаблон абсолютно корректно, на выходе получите полноценный функциональный инструмент: - Эмулятор: Берёт последовательно коды команд из таблицы и вызывает их как конкретные функции
- Дизассемблер: Читает коды операций и преобразует их в колонку символьного представления
- Ассемблер: Читает Ваш текст программы символьных команд и преобразует их в совокупность бинарных кодов тех команд
Так, например, мы напишем следующие строчки:
Код:
|
DO Door+=Dog
DO Cat+=Desk
DO Cat+=Dog |
В таблицу памяти он упакуется кодами 0101, 0011, 0111.
Запустив данную "программу" мы заставим цикл эмуляции выполнить следующую последовательность операций:
Open_Door(Keep_Home); Make_Purr(Wash_Desk); Make_Purr(Keep_Home);
Последний раз редактировалось Paguo-86PK, 03.03.2017 в 09:21.
|
|
08.03.2017, 08:56
|
|
Профессор
|
|
Регистрация: 16.09.2009
Сообщений: 253
|
|
<head><script type='text/javascript'>
var Register = function(reg) {
this.store = [0x43,0x42,0x45,0x44,0x4C,0x48,0x46,0x41,0,0,0,0,0,0,0,0];
for(var id in reg) {
var ptr = reg[id].split(/\s+/),
num = ptr.length,
gets = {
"1" : "return this.store[0x_0]",
"2" : "return this.store[0x_0] | this.store[0x_1] << 8",
"3" : "var tmp = this.store[0x_0] | this.store[0x_1] << 8; return 0x_2==1 ? m[tmp] : m[tmp] | m[tmp + 1] << 8"
},
sets = {
"1" : "this.store[0x_0] = x & 255",
"2" : "this.store[0x_0] = x & 255, this.store[0x_1] = x >> 8 & 255",
"3" : "var tmp = this.store[0x_0] | this.store[0x_1] << 8; 0x_2==1 ? m[tmp] = x & 255 : (m[tmp] = x & 255, m[tmp + 1] = x >> 8 & 255)"
};
Object.defineProperty(this, id, {
enumerable : true,
get : new Function(
"",
gets[num].replace(/_(\d)/g, function(s, i) {
return ptr[i];
}
)
),
set : new Function(
"x",
sets[num].replace(/_(\d)/g, function(s, i) {
return ptr[i];
}
)
)
});
}
return this;
};
var r;
var m = (function(n) {
var tmp = [];
while(n --)
tmp.push(Math.random() * 256 & 255);
return tmp;
})(65535);
var regs = {
bc : "0 1",
b : "1",
c : "0",
de : "2 3",
d : "3",
e : "2",
hl : "4 5",
h : "5",
l : "4",
psw : "7 6",
f : "6",
a : "7",
m : "4 5 1",
cx : "0 1",
ch : "1",
cl : "0",
dx : "2 3",
dh : "3",
dl : "2",
bx : "4 5",
bh : "5",
bl : "4",
al : "7"
};
window.onload = function() {
var log = [];
r = new Register(regs);
for(var id in regs)
log.push(id + ": " + r[id].toString(16));
document.getElementsByTagName("pre")[0].innerHTML = log.join("<br />");
}
</script>
</head>
<body>
<pre></pre>
</body>
P.S.: Код работает…
Однако, вопрос к настоящим знатокам: Может что-то можно описать красивее?
Последний раз редактировалось Paguo-86PK, 08.03.2017 в 10:03.
|
|
09.03.2017, 12:45
|
|
Профессор
|
|
Регистрация: 13.03.2013
Сообщений: 1,572
|
|
Сообщение от Paguo-86PK
|
Может что-то можно описать красивее?
|
Конечно можно. Просто посмотри на него через год
|
|
|
|