diff --git a/assets/asmsimulator.js b/assets/asmsimulator.js index 221315f..4d04f8c 100644 --- a/assets/asmsimulator.js +++ b/assets/asmsimulator.js @@ -719,7 +719,7 @@ var app = angular.module('ASMSimulator', []); self.zero = true; } else if (value < 0) { self.carry = true; - value = 255 - (-value) % 256; + value = 256 - (-value) % 256; } return value; diff --git a/assets/asmsimulator.min.js b/assets/asmsimulator.min.js index 04819d3..303ccd0 100644 --- a/assets/asmsimulator.min.js +++ b/assets/asmsimulator.min.js @@ -1,2 +1,2 @@ -/*! asmsimulator 15-03-2015 */ -var app=angular.module("ASMSimulator",[]);app.service("assembler",["opcodes",function(a){return{go:function(b){for(var c=/^[\t ]*(?:([.A-Za-z]\w*)[:])?(?:[\t ]*([A-Za-z]{2,4})(?:[\t ]+(\[(\w+((\+|-)\d+)?)\]|\".+?\"|\'.+?\'|[.A-Za-z0-9]\w*)(?:[\t ]*[,][\t ]*(\[(\w+((\+|-)\d+)?)\]|\".+?\"|\'.+?\'|[.A-Za-z0-9]\w*))?)?)?/,d=3,e=7,f=/^[-+]?[0-9]+$/,g=/^[.A-Za-z]\w*$/,h=[],i={},j={},k={},l=b.split("\n"),m=function(a){if("0x"===a.slice(0,2))return parseInt(a.slice(2),16);if("0o"===a.slice(0,2))return parseInt(a.slice(2),8);if("b"===a.slice(a.length-1))return parseInt(a.slice(0,a.length-1),2);if("d"===a.slice(a.length-1))return parseInt(a.slice(0,a.length-1),10);if(f.exec(a))return parseInt(a,10);throw"Invalid number format"},n=function(a){return a=a.toUpperCase(),"A"===a?0:"B"===a?1:"C"===a?2:"D"===a?3:"SP"===a?4:void 0},o=function(a){a=a.toUpperCase();var b=0,c=0;if("A"===a[0])c=0;else if("B"===a[0])c=1;else if("C"===a[0])c=2;else if("D"===a[0])c=3;else{if("SP"!==a.slice(0,2))return void 0;c=4}var d=1;if(4===c&&(d=2),"-"===a[d])b=-1;else{if("+"!==a[d])return void 0;b=1}var e=b*parseInt(a.slice(d+1),10);if(-16>e||e>15)throw"offset must be a value between -16...+15";return 0>e&&(e=32+e),8*e+c},p=function(a,b,c){var d=n(a);if(void 0!==d)return{type:b,value:d};var e=q(a);if(void 0!==e)return{type:c,value:e};if("regaddress"===b&&(d=o(a),void 0!==d))return{type:b,value:d};var f=m(a);if(isNaN(f))throw"Not a "+c+": "+f;if(0>f||f>255)throw c+" must have a value between 0-255";return{type:c,value:f}},q=function(a){return g.exec(a)?a:void 0},r=function(a){switch(a.slice(0,1)){case"[":var b=a.slice(1,a.length-1);return p(b,"regaddress","address");case'"':for(var c=a.slice(1,a.length-1),d=[],e=0,f=c.length;f>e;e++)d.push(c.charCodeAt(e));return{type:"numbers",value:d};case"'":var g=a.slice(1,a.length-1);if(g.length>1)throw"Only one character is allowed. Use String instead";return{type:"number",value:g.charCodeAt(0)};default:return p(a,"register","number")}},s=(function(a){var b=a.toUpperCase();if(b in k)throw"Duplicate label: "+a;if("A"===b||"B"===b||"C"===b||"D"===b)throw"Label contains keyword: "+b;j[a]=h.length}),t=function(a,b){if(void 0!==b)throw a+": too many arguments"},u=0,v=l.length;v>u;u++)try{var w=c.exec(l[u]);if(void 0!==w[1]||void 0!==w[2]){if(void 0!==w[1]&&s(w[1]),void 0!==w[2]){var x,y,z,A=w[2].toUpperCase();switch("DB"!==A&&(i[h.length]=u),A){case"DB":if(x=r(w[d]),"number"===x.type)h.push(x.value);else{if("numbers"!==x.type)throw"DB does not support this operand";for(var B=0,C=x.value.length;C>B;B++)h.push(x.value[B])}break;case"HLT":t("HLT",w[d]),z=a.NONE,h.push(z);break;case"MOV":if(x=r(w[d]),y=r(w[e]),"register"===x.type&&"register"===y.type)z=a.MOV_REG_TO_REG;else if("register"===x.type&&"address"===y.type)z=a.MOV_ADDRESS_TO_REG;else if("register"===x.type&&"regaddress"===y.type)z=a.MOV_REGADDRESS_TO_REG;else if("address"===x.type&&"register"===y.type)z=a.MOV_REG_TO_ADDRESS;else if("regaddress"===x.type&&"register"===y.type)z=a.MOV_REG_TO_REGADDRESS;else if("register"===x.type&&"number"===y.type)z=a.MOV_NUMBER_TO_REG;else if("address"===x.type&&"number"===y.type)z=a.MOV_NUMBER_TO_ADDRESS;else{if("regaddress"!==x.type||"number"!==y.type)throw"MOV does not support this operands";z=a.MOV_NUMBER_TO_REGADDRESS}h.push(z,x.value,y.value);break;case"ADD":if(x=r(w[d]),y=r(w[e]),"register"===x.type&&"register"===y.type)z=a.ADD_REG_TO_REG;else if("register"===x.type&&"regaddress"===y.type)z=a.ADD_REGADDRESS_TO_REG;else if("register"===x.type&&"address"===y.type)z=a.ADD_ADDRESS_TO_REG;else{if("register"!==x.type||"number"!==y.type)throw"ADD does not support this operands";z=a.ADD_NUMBER_TO_REG}h.push(z,x.value,y.value);break;case"SUB":if(x=r(w[d]),y=r(w[e]),"register"===x.type&&"register"===y.type)z=a.SUB_REG_FROM_REG;else if("register"===x.type&&"regaddress"===y.type)z=a.SUB_REGADDRESS_FROM_REG;else if("register"===x.type&&"address"===y.type)z=a.SUB_ADDRESS_FROM_REG;else{if("register"!==x.type||"number"!==y.type)throw"SUB does not support this operands";z=a.SUB_NUMBER_FROM_REG}h.push(z,x.value,y.value);break;case"INC":if(x=r(w[d]),t("INC",w[e]),"register"!==x.type)throw"INC does not support this operand";z=a.INC_REG,h.push(z,x.value);break;case"DEC":if(x=r(w[d]),t("DEC",w[e]),"register"!==x.type)throw"DEC does not support this operand";z=a.DEC_REG,h.push(z,x.value);break;case"CMP":if(x=r(w[d]),y=r(w[e]),"register"===x.type&&"register"===y.type)z=a.CMP_REG_WITH_REG;else if("register"===x.type&&"regaddress"===y.type)z=a.CMP_REGADDRESS_WITH_REG;else if("register"===x.type&&"address"===y.type)z=a.CMP_ADDRESS_WITH_REG;else{if("register"!==x.type||"number"!==y.type)throw"CMP does not support this operands";z=a.CMP_NUMBER_WITH_REG}h.push(z,x.value,y.value);break;case"JMP":if(x=r(w[d]),t("JMP",w[e]),"register"===x.type)z=a.JMP_REGADDRESS;else{if("number"!==x.type)throw"JMP does not support this operands";z=a.JMP_ADDRESS}h.push(z,x.value);break;case"JC":case"JB":case"JNAE":if(x=r(w[d]),t(A,w[e]),"register"===x.type)z=a.JC_REGADDRESS;else{if("number"!==x.type)throw A+" does not support this operand";z=a.JC_ADDRESS}h.push(z,x.value);break;case"JNC":case"JNB":case"JAE":if(x=r(w[d]),t(A,w[e]),"register"===x.type)z=a.JNC_REGADDRESS;else{if("number"!==x.type)throw A+"does not support this operand";z=a.JNC_ADDRESS}h.push(z,x.value);break;case"JZ":case"JE":if(x=r(w[d]),t(A,w[e]),"register"===x.type)z=a.JZ_REGADDRESS;else{if("number"!==x.type)throw A+" does not support this operand";z=a.JZ_ADDRESS}h.push(z,x.value);break;case"JNZ":case"JNE":if(x=r(w[d]),t(A,w[e]),"register"===x.type)z=a.JNZ_REGADDRESS;else{if("number"!==x.type)throw A+" does not support this operand";z=a.JNZ_ADDRESS}h.push(z,x.value);break;case"JA":case"JNBE":if(x=r(w[d]),t(A,w[e]),"register"===x.type)z=a.JA_REGADDRESS;else{if("number"!==x.type)throw A+" does not support this operand";z=a.JA_ADDRESS}h.push(z,x.value);break;case"JNA":case"JBE":if(x=r(w[d]),t(A,w[e]),"register"===x.type)z=a.JNA_REGADDRESS;else{if("number"!==x.type)throw A+" does not support this operand";z=a.JNA_ADDRESS}h.push(z,x.value);break;case"PUSH":if(x=r(w[d]),t(A,w[e]),"register"===x.type)z=a.PUSH_REG;else if("regaddress"===x.type)z=a.PUSH_REGADDRESS;else if("address"===x.type)z=a.PUSH_ADDRESS;else{if("number"!==x.type)throw"PUSH does not support this operand";z=a.PUSH_NUMBER}h.push(z,x.value);break;case"POP":if(x=r(w[d]),t(A,w[e]),"register"!==x.type)throw"PUSH does not support this operand";z=a.POP_REG,h.push(z,x.value);break;case"CALL":if(x=r(w[d]),t(A,w[e]),"register"===x.type)z=a.CALL_REGADDRESS;else{if("number"!==x.type)throw"CALL does not support this operand";z=a.CALL_ADDRESS}h.push(z,x.value);break;case"RET":t(A,w[d]),z=a.RET,h.push(z);break;case"MUL":if(x=r(w[d]),t(A,w[e]),"register"===x.type)z=a.MUL_REG;else if("regaddress"===x.type)z=a.MUL_REGADDRESS;else if("address"===x.type)z=a.MUL_ADDRESS;else{if("number"!==x.type)throw"MULL does not support this operand";z=a.MUL_NUMBER}h.push(z,x.value);break;case"DIV":if(x=r(w[d]),t(A,w[e]),"register"===x.type)z=a.DIV_REG;else if("regaddress"===x.type)z=a.DIV_REGADDRESS;else if("address"===x.type)z=a.DIV_ADDRESS;else{if("number"!==x.type)throw"DIV does not support this operand";z=a.DIV_NUMBER}h.push(z,x.value);break;case"AND":if(x=r(w[d]),y=r(w[e]),"register"===x.type&&"register"===y.type)z=a.AND_REG_WITH_REG;else if("register"===x.type&&"regaddress"===y.type)z=a.AND_REGADDRESS_WITH_REG;else if("register"===x.type&&"address"===y.type)z=a.AND_ADDRESS_WITH_REG;else{if("register"!==x.type||"number"!==y.type)throw"AND does not support this operands";z=a.AND_NUMBER_WITH_REG}h.push(z,x.value,y.value);break;case"OR":if(x=r(w[d]),y=r(w[e]),"register"===x.type&&"register"===y.type)z=a.OR_REG_WITH_REG;else if("register"===x.type&&"regaddress"===y.type)z=a.OR_REGADDRESS_WITH_REG;else if("register"===x.type&&"address"===y.type)z=a.OR_ADDRESS_WITH_REG;else{if("register"!==x.type||"number"!==y.type)throw"OR does not support this operands";z=a.OR_NUMBER_WITH_REG}h.push(z,x.value,y.value);break;case"XOR":if(x=r(w[d]),y=r(w[e]),"register"===x.type&&"register"===y.type)z=a.XOR_REG_WITH_REG;else if("register"===x.type&&"regaddress"===y.type)z=a.XOR_REGADDRESS_WITH_REG;else if("register"===x.type&&"address"===y.type)z=a.XOR_ADDRESS_WITH_REG;else{if("register"!==x.type||"number"!==y.type)throw"XOR does not support this operands";z=a.XOR_NUMBER_WITH_REG}h.push(z,x.value,y.value);break;case"NOT":if(x=r(w[d]),t(A,w[e]),"register"!==x.type)throw"NOT does not support this operand";z=a.NOT_REG,h.push(z,x.value);break;case"SHL":case"SAL":if(x=r(w[d]),y=r(w[e]),"register"===x.type&&"register"===y.type)z=a.SHL_REG_WITH_REG;else if("register"===x.type&&"regaddress"===y.type)z=a.SHL_REGADDRESS_WITH_REG;else if("register"===x.type&&"address"===y.type)z=a.SHL_ADDRESS_WITH_REG;else{if("register"!==x.type||"number"!==y.type)throw A+" does not support this operands";z=a.SHL_NUMBER_WITH_REG}h.push(z,x.value,y.value);break;case"SHR":case"SAR":if(x=r(w[d]),y=r(w[e]),"register"===x.type&&"register"===y.type)z=a.SHR_REG_WITH_REG;else if("register"===x.type&&"regaddress"===y.type)z=a.SHR_REGADDRESS_WITH_REG;else if("register"===x.type&&"address"===y.type)z=a.SHR_ADDRESS_WITH_REG;else{if("register"!==x.type||"number"!==y.type)throw A+" does not support this operands";z=a.SHR_NUMBER_WITH_REG}h.push(z,x.value,y.value);break;default:throw"Invalid instruction: "+w[2]}}}else{var D=l[u].trim();if(""!==D&&";"!==D.slice(0,1))throw"Syntax error"}}catch(E){throw{error:E,line:u}}for(u=0,v=h.length;v>u;u++)if(!angular.isNumber(h[u])){if(!(h[u]in j))throw{error:"Undefined label: "+h[u]};h[u]=j[h[u]]}return{code:h,mapping:i,labels:j}}}}]),app.service("cpu",["opcodes","memory",function(a,b){var c={step:function(){var c=this;if(c.fault===!0)throw"FAULT. Reset to continue.";try{var d=function(a){if(0>a||a>=c.gpr.length)throw"Invalid register: "+a;return a},e=function(a){if(0>a||a>=1+c.gpr.length)throw"Invalid register: "+a;return a},f=function(a,b){if(a>=0&&ac.maxSP)throw"Stack underflow"}},g=function(a){if(a>=0&&a15&&(e-=32),b+e},i=function(a){return c.zero=!1,c.carry=!1,a>=256?(c.carry=!0,a%=256):0===a?c.zero=!0:0>a&&(c.carry=!0,a=255- -a%256),a},j=function(a){if(0>a||a>=b.data.length)throw"IP outside memory";c.ip=a},k=function(a){if(b.store(c.sp--,a),c.spc.maxSP)throw"Stack underflow";return a},m=function(a){if(0===a)throw"Division by 0";return Math.floor(c.gpr[0]/a)};if(c.ip<0||c.ip>=b.data.length)throw"Instruction pointer is outside of memory";var n,o,p,q,r,s=b.load(c.ip);switch(s){case a.NONE:return!1;case a.MOV_REG_TO_REG:n=e(b.load(++c.ip)),o=e(b.load(++c.ip)),f(n,g(o)),c.ip++;break;case a.MOV_ADDRESS_TO_REG:n=e(b.load(++c.ip)),p=b.load(++c.ip),f(n,b.load(p)),c.ip++;break;case a.MOV_REGADDRESS_TO_REG:n=e(b.load(++c.ip)),o=b.load(++c.ip),f(n,b.load(h(o))),c.ip++;break;case a.MOV_REG_TO_ADDRESS:q=b.load(++c.ip),o=e(b.load(++c.ip)),b.store(q,g(o)),c.ip++;break;case a.MOV_REG_TO_REGADDRESS:n=b.load(++c.ip),o=e(b.load(++c.ip)),b.store(h(n),g(o)),c.ip++;break;case a.MOV_NUMBER_TO_REG:n=e(b.load(++c.ip)),r=b.load(++c.ip),f(n,r),c.ip++;break;case a.MOV_NUMBER_TO_ADDRESS:q=b.load(++c.ip),r=b.load(++c.ip),b.store(q,r),c.ip++;break;case a.MOV_NUMBER_TO_REGADDRESS:n=b.load(++c.ip),r=b.load(++c.ip),b.store(h(n),r),c.ip++;break;case a.ADD_REG_TO_REG:n=e(b.load(++c.ip)),o=e(b.load(++c.ip)),f(n,i(g(n)+g(o))),c.ip++;break;case a.ADD_REGADDRESS_TO_REG:n=e(b.load(++c.ip)),o=b.load(++c.ip),f(n,i(g(n)+b.load(h(o)))),c.ip++;break;case a.ADD_ADDRESS_TO_REG:n=e(b.load(++c.ip)),p=b.load(++c.ip),f(n,i(g(n)+b.load(p))),c.ip++;break;case a.ADD_NUMBER_TO_REG:n=e(b.load(++c.ip)),r=b.load(++c.ip),f(n,i(g(n)+r)),c.ip++;break;case a.SUB_REG_FROM_REG:n=e(b.load(++c.ip)),o=e(b.load(++c.ip)),f(n,i(g(n)-c.gpr[o])),c.ip++;break;case a.SUB_REGADDRESS_FROM_REG:n=e(b.load(++c.ip)),o=b.load(++c.ip),f(n,i(g(n)-b.load(h(o)))),c.ip++;break;case a.SUB_ADDRESS_FROM_REG:n=e(b.load(++c.ip)),p=b.load(++c.ip),f(n,i(g(n)-b.load(p))),c.ip++;break;case a.SUB_NUMBER_FROM_REG:n=e(b.load(++c.ip)),r=b.load(++c.ip),f(n,i(g(n)-r)),c.ip++;break;case a.INC_REG:n=e(b.load(++c.ip)),f(n,i(g(n)+1)),c.ip++;break;case a.DEC_REG:n=e(b.load(++c.ip)),f(n,i(g(n)-1)),c.ip++;break;case a.CMP_REG_WITH_REG:n=e(b.load(++c.ip)),o=e(b.load(++c.ip)),i(g(n)-g(o)),c.ip++;break;case a.CMP_REGADDRESS_WITH_REG:n=e(b.load(++c.ip)),o=b.load(++c.ip),i(g(n)-b.load(h(o))),c.ip++;break;case a.CMP_ADDRESS_WITH_REG:n=e(b.load(++c.ip)),p=b.load(++c.ip),i(g(n)-b.load(p)),c.ip++;break;case a.CMP_NUMBER_WITH_REG:n=e(b.load(++c.ip)),r=b.load(++c.ip),i(g(n)-r),c.ip++;break;case a.JMP_REGADDRESS:n=d(b.load(++c.ip)),j(c.gpr[n]);break;case a.JMP_ADDRESS:r=b.load(++c.ip),j(r);break;case a.JC_REGADDRESS:n=d(b.load(++c.ip)),c.carry?j(c.gpr[n]):c.ip++;break;case a.JC_ADDRESS:r=b.load(++c.ip),c.carry?j(r):c.ip++;break;case a.JNC_REGADDRESS:n=d(b.load(++c.ip)),c.carry?c.ip++:j(c.gpr[n]);break;case a.JNC_ADDRESS:r=b.load(++c.ip),c.carry?c.ip++:j(r);break;case a.JZ_REGADDRESS:n=d(b.load(++c.ip)),c.zero?j(c.gpr[n]):c.ip++;break;case a.JZ_ADDRESS:r=b.load(++c.ip),c.zero?j(r):c.ip++;break;case a.JNZ_REGADDRESS:n=d(b.load(++c.ip)),c.zero?c.ip++:j(c.gpr[n]);break;case a.JNZ_ADDRESS:r=b.load(++c.ip),c.zero?c.ip++:j(r);break;case a.JA_REGADDRESS:n=d(b.load(++c.ip)),c.zero||c.carry?c.ip++:j(c.gpr[n]);break;case a.JA_ADDRESS:r=b.load(++c.ip),c.zero||c.carry?c.ip++:j(r);break;case a.JNA_REGADDRESS:n=d(b.load(++c.ip)),c.zero||c.carry?j(c.gpr[n]):c.ip++;break;case a.JNA_ADDRESS:r=b.load(++c.ip),c.zero||c.carry?j(r):c.ip++;break;case a.PUSH_REG:o=d(b.load(++c.ip)),k(c.gpr[o]),c.ip++;break;case a.PUSH_REGADDRESS:o=b.load(++c.ip),k(b.load(h(o))),c.ip++;break;case a.PUSH_ADDRESS:p=b.load(++c.ip),k(b.load(p)),c.ip++;break;case a.PUSH_NUMBER:r=b.load(++c.ip),k(r),c.ip++;break;case a.POP_REG:n=d(b.load(++c.ip)),c.gpr[n]=l(),c.ip++;break;case a.CALL_REGADDRESS:n=d(b.load(++c.ip)),k(c.ip+1),j(c.gpr[n]);break;case a.CALL_ADDRESS:r=b.load(++c.ip),k(c.ip+1),j(r);break;case a.RET:j(l());break;case a.MUL_REG:o=d(b.load(++c.ip)),c.gpr[0]=i(c.gpr[0]*c.gpr[o]),c.ip++;break;case a.MUL_REGADDRESS:o=b.load(++c.ip),c.gpr[0]=i(c.gpr[0]*b.load(h(o))),c.ip++;break;case a.MUL_ADDRESS:p=b.load(++c.ip),c.gpr[0]=i(c.gpr[0]*b.load(p)),c.ip++;break;case a.MUL_NUMBER:r=b.load(++c.ip),c.gpr[0]=i(c.gpr[0]*r),c.ip++;break;case a.DIV_REG:o=d(b.load(++c.ip)),c.gpr[0]=i(m(c.gpr[o])),c.ip++;break;case a.DIV_REGADDRESS:o=b.load(++c.ip),c.gpr[0]=i(m(b.load(h(o)))),c.ip++;break;case a.DIV_ADDRESS:p=b.load(++c.ip),c.gpr[0]=i(m(b.load(p))),c.ip++;break;case a.DIV_NUMBER:r=b.load(++c.ip),c.gpr[0]=i(m(r)),c.ip++;break;case a.AND_REG_WITH_REG:n=d(b.load(++c.ip)),o=d(b.load(++c.ip)),c.gpr[n]=i(c.gpr[n]&c.gpr[o]),c.ip++;break;case a.AND_REGADDRESS_WITH_REG:n=d(b.load(++c.ip)),o=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]&b.load(h(o))),c.ip++;break;case a.AND_ADDRESS_WITH_REG:n=d(b.load(++c.ip)),p=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]&b.load(p)),c.ip++;break;case a.AND_NUMBER_WITH_REG:n=d(b.load(++c.ip)),r=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]&r),c.ip++;break;case a.OR_REG_WITH_REG:n=d(b.load(++c.ip)),o=d(b.load(++c.ip)),c.gpr[n]=i(c.gpr[n]|c.gpr[o]),c.ip++;break;case a.OR_REGADDRESS_WITH_REG:n=d(b.load(++c.ip)),o=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]|b.load(h(o))),c.ip++;break;case a.OR_ADDRESS_WITH_REG:n=d(b.load(++c.ip)),p=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]|b.load(p)),c.ip++;break;case a.OR_NUMBER_WITH_REG:n=d(b.load(++c.ip)),r=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]|r),c.ip++;break;case a.XOR_REG_WITH_REG:n=d(b.load(++c.ip)),o=d(b.load(++c.ip)),c.gpr[n]=i(c.gpr[n]^c.gpr[o]),c.ip++;break;case a.XOR_REGADDRESS_WITH_REG:n=d(b.load(++c.ip)),o=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]^b.load(h(o))),c.ip++;break;case a.XOR_ADDRESS_WITH_REG:n=d(b.load(++c.ip)),p=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]^b.load(p)),c.ip++;break;case a.XOR_NUMBER_WITH_REG:n=d(b.load(++c.ip)),r=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]^r),c.ip++;break;case a.NOT_REG:n=d(b.load(++c.ip)),c.gpr[n]=i(~c.gpr[n]),c.ip++;break;case a.SHL_REG_WITH_REG:n=d(b.load(++c.ip)),o=d(b.load(++c.ip)),c.gpr[n]=i(c.gpr[n]<>>c.gpr[o]),c.ip++;break;case a.SHR_REGADDRESS_WITH_REG:n=d(b.load(++c.ip)),o=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]>>>b.load(h(o))),c.ip++;break;case a.SHR_ADDRESS_WITH_REG:n=d(b.load(++c.ip)),p=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]>>>b.load(p)),c.ip++;break;case a.SHR_NUMBER_WITH_REG:n=d(b.load(++c.ip)),r=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]>>>r),c.ip++;break;default:throw"Invalid op code: "+s}return!0}catch(t){throw c.fault=!0,t}},reset:function(){var a=this;a.maxSP=231,a.minSP=0,a.gpr=[0,0,0,0],a.sp=a.maxSP,a.ip=0,a.zero=!1,a.carry=!1,a.fault=!1}};return c.reset(),c}]),app.service("memory",[function(){var a={data:Array(256),lastAccess:-1,load:function(a){var b=this;if(0>a||a>=b.data.length)throw"Memory access violation at "+a;return b.lastAccess=a,b.data[a]},store:function(a,b){var c=this;if(0>a||a>=c.data.length)throw"Memory access violation at "+a;c.lastAccess=a,c.data[a]=b},reset:function(){var a=this;a.lastAccess=-1;for(var b=0,c=a.data.length;c>b;b++)a.data[b]=0}};return a.reset(),a}]),app.service("opcodes",[function(){var a={NONE:0,MOV_REG_TO_REG:1,MOV_ADDRESS_TO_REG:2,MOV_REGADDRESS_TO_REG:3,MOV_REG_TO_ADDRESS:4,MOV_REG_TO_REGADDRESS:5,MOV_NUMBER_TO_REG:6,MOV_NUMBER_TO_ADDRESS:7,MOV_NUMBER_TO_REGADDRESS:8,ADD_REG_TO_REG:10,ADD_REGADDRESS_TO_REG:11,ADD_ADDRESS_TO_REG:12,ADD_NUMBER_TO_REG:13,SUB_REG_FROM_REG:14,SUB_REGADDRESS_FROM_REG:15,SUB_ADDRESS_FROM_REG:16,SUB_NUMBER_FROM_REG:17,INC_REG:18,DEC_REG:19,CMP_REG_WITH_REG:20,CMP_REGADDRESS_WITH_REG:21,CMP_ADDRESS_WITH_REG:22,CMP_NUMBER_WITH_REG:23,JMP_REGADDRESS:30,JMP_ADDRESS:31,JC_REGADDRESS:32,JC_ADDRESS:33,JNC_REGADDRESS:34,JNC_ADDRESS:35,JZ_REGADDRESS:36,JZ_ADDRESS:37,JNZ_REGADDRESS:38,JNZ_ADDRESS:39,JA_REGADDRESS:40,JA_ADDRESS:41,JNA_REGADDRESS:42,JNA_ADDRESS:43,PUSH_REG:50,PUSH_REGADDRESS:51,PUSH_ADDRESS:52,PUSH_NUMBER:53,POP_REG:54,CALL_REGADDRESS:55,CALL_ADDRESS:56,RET:57,MUL_REG:60,MUL_REGADDRESS:61,MUL_ADDRESS:62,MUL_NUMBER:63,DIV_REG:64,DIV_REGADDRESS:65,DIV_ADDRESS:66,DIV_NUMBER:67,AND_REG_WITH_REG:70,AND_REGADDRESS_WITH_REG:71,AND_ADDRESS_WITH_REG:72,AND_NUMBER_WITH_REG:73,OR_REG_WITH_REG:74,OR_REGADDRESS_WITH_REG:75,OR_ADDRESS_WITH_REG:76,OR_NUMBER_WITH_REG:77,XOR_REG_WITH_REG:78,XOR_REGADDRESS_WITH_REG:79,XOR_ADDRESS_WITH_REG:80,XOR_NUMBER_WITH_REG:81,NOT_REG:82,SHL_REG_WITH_REG:90,SHL_REGADDRESS_WITH_REG:91,SHL_ADDRESS_WITH_REG:92,SHL_NUMBER_WITH_REG:93,SHR_REG_WITH_REG:94,SHR_REGADDRESS_WITH_REG:95,SHR_ADDRESS_WITH_REG:96,SHR_NUMBER_WITH_REG:97};return a}]),app.controller("Ctrl",["$document","$scope","$timeout","cpu","memory","assembler",function(a,b,c,d,e,f){b.memory=e,b.cpu=d,b.error="",b.isRunning=!1,b.displayHex=!0,b.displayInstr=!0,b.displayA=!1,b.displayB=!1,b.displayC=!1,b.displayD=!1,b.speeds=[{speed:1,desc:"1 HZ"},{speed:4,desc:"4 HZ"},{speed:8,desc:"8 HZ"},{speed:16,desc:"16 HZ"}],b.speed=4,b.outputStartIndex=232,b.code='; Simple example\n; Writes Hello World to the output\n\n JMP start\nhello: DB "Hello World!" ; Variable\n DB 0 ; String terminator\n\nstart:\n MOV C, hello ; Point to var \n MOV D, 232 ; Point to output\n CALL print\n HLT ; Stop execution\n\nprint: ; print(C:*from, D:*to)\n PUSH A\n PUSH B\n MOV B, 0\n.loop:\n MOV A, [C] ; Get char from var\n MOV [D], A ; Write to output\n INC C\n INC D \n CMP B, [C] ; Check if end\n JNZ .loop ; jump if not\n\n POP B\n POP A\n RET',b.reset=function(){d.reset(),e.reset(),b.error="",b.selectedLine=-1},b.executeStep=function(){b.checkPrgrmLoaded()||b.assemble();try{var a=d.step();return d.ip in b.mapping&&(b.selectedLine=b.mapping[d.ip]),a}catch(c){return b.error=c,!1}};var g;b.run=function(){b.checkPrgrmLoaded()||b.assemble(),b.isRunning=!0,g=c(function(){b.executeStep()===!0?b.run():b.isRunning=!1},1e3/b.speed)},b.stop=function(){c.cancel(g),b.isRunning=!1},b.checkPrgrmLoaded=function(){for(var a=0,b=e.data.length;b>a;a++)if(0!==e.data[a])return!0;return!1},b.getChar=function(a){var b=String.fromCharCode(a);return""===b.trim()?"  ":b},b.assemble=function(){try{b.reset();var a=f.go(b.code);b.mapping=a.mapping;var c=a.code;if(b.labels=a.labels,c.length>e.data.length)throw"Binary code does not fit into the memory. Max "+e.data.length+" bytes are allowed";for(var d=0,g=c.length;g>d;d++)e.data[d]=c[d]}catch(h){void 0!==h.line?(b.error=h.line+" | "+h.error,b.selectedLine=h.line):b.error=h.error}},b.jumpToLine=function(c){a[0].getElementById("sourceCode").scrollIntoView(),b.selectedLine=b.mapping[c]},b.isInstruction=function(a){return void 0!==b.mapping&&void 0!==b.mapping[a]&&b.displayInstr},b.getMemoryCellCss=function(a){return a>=b.outputStartIndex?"output-bg":b.isInstruction(a)?"instr-bg":a>d.sp&&a<=d.maxSP?"stack-bg":""},b.getMemoryInnerCellCss=function(a){return a===d.ip?"marker marker-ip":a===d.sp?"marker marker-sp":a===d.gpr[0]&&b.displayA?"marker marker-a":a===d.gpr[1]&&b.displayB?"marker marker-b":a===d.gpr[2]&&b.displayC?"marker marker-c":a===d.gpr[3]&&b.displayD?"marker marker-d":""}}]),app.filter("flag",function(){return function(a){return a.toString().toUpperCase()}}),app.filter("number",function(){return function(a,b){if(b){var c=a.toString(16).toUpperCase();return 1==c.length?"0"+c:c}return a.toString(10)}}),app.directive("selectLine",[function(){return{restrict:"A",link:function(a,b){a.$watch("selectedLine",function(){if(a.selectedLine>=0){for(var c=b[0].value.split("\n"),d=0,e=0;ee||e>15)throw"offset must be a value between -16...+15";return 0>e&&(e=32+e),8*e+c},p=function(a,b,c){var d=n(a);if(void 0!==d)return{type:b,value:d};var e=q(a);if(void 0!==e)return{type:c,value:e};if("regaddress"===b&&(d=o(a),void 0!==d))return{type:b,value:d};var f=m(a);if(isNaN(f))throw"Not a "+c+": "+f;if(0>f||f>255)throw c+" must have a value between 0-255";return{type:c,value:f}},q=function(a){return g.exec(a)?a:void 0},r=function(a){switch(a.slice(0,1)){case"[":var b=a.slice(1,a.length-1);return p(b,"regaddress","address");case'"':for(var c=a.slice(1,a.length-1),d=[],e=0,f=c.length;f>e;e++)d.push(c.charCodeAt(e));return{type:"numbers",value:d};case"'":var g=a.slice(1,a.length-1);if(g.length>1)throw"Only one character is allowed. Use String instead";return{type:"number",value:g.charCodeAt(0)};default:return p(a,"register","number")}},s=(function(a){var b=a.toUpperCase();if(b in k)throw"Duplicate label: "+a;if("A"===b||"B"===b||"C"===b||"D"===b)throw"Label contains keyword: "+b;j[a]=h.length}),t=function(a,b){if(void 0!==b)throw a+": too many arguments"},u=0,v=l.length;v>u;u++)try{var w=c.exec(l[u]);if(void 0!==w[1]||void 0!==w[2]){if(void 0!==w[1]&&s(w[1]),void 0!==w[2]){var x,y,z,A=w[2].toUpperCase();switch("DB"!==A&&(i[h.length]=u),A){case"DB":if(x=r(w[d]),"number"===x.type)h.push(x.value);else{if("numbers"!==x.type)throw"DB does not support this operand";for(var B=0,C=x.value.length;C>B;B++)h.push(x.value[B])}break;case"HLT":t("HLT",w[d]),z=a.NONE,h.push(z);break;case"MOV":if(x=r(w[d]),y=r(w[e]),"register"===x.type&&"register"===y.type)z=a.MOV_REG_TO_REG;else if("register"===x.type&&"address"===y.type)z=a.MOV_ADDRESS_TO_REG;else if("register"===x.type&&"regaddress"===y.type)z=a.MOV_REGADDRESS_TO_REG;else if("address"===x.type&&"register"===y.type)z=a.MOV_REG_TO_ADDRESS;else if("regaddress"===x.type&&"register"===y.type)z=a.MOV_REG_TO_REGADDRESS;else if("register"===x.type&&"number"===y.type)z=a.MOV_NUMBER_TO_REG;else if("address"===x.type&&"number"===y.type)z=a.MOV_NUMBER_TO_ADDRESS;else{if("regaddress"!==x.type||"number"!==y.type)throw"MOV does not support this operands";z=a.MOV_NUMBER_TO_REGADDRESS}h.push(z,x.value,y.value);break;case"ADD":if(x=r(w[d]),y=r(w[e]),"register"===x.type&&"register"===y.type)z=a.ADD_REG_TO_REG;else if("register"===x.type&&"regaddress"===y.type)z=a.ADD_REGADDRESS_TO_REG;else if("register"===x.type&&"address"===y.type)z=a.ADD_ADDRESS_TO_REG;else{if("register"!==x.type||"number"!==y.type)throw"ADD does not support this operands";z=a.ADD_NUMBER_TO_REG}h.push(z,x.value,y.value);break;case"SUB":if(x=r(w[d]),y=r(w[e]),"register"===x.type&&"register"===y.type)z=a.SUB_REG_FROM_REG;else if("register"===x.type&&"regaddress"===y.type)z=a.SUB_REGADDRESS_FROM_REG;else if("register"===x.type&&"address"===y.type)z=a.SUB_ADDRESS_FROM_REG;else{if("register"!==x.type||"number"!==y.type)throw"SUB does not support this operands";z=a.SUB_NUMBER_FROM_REG}h.push(z,x.value,y.value);break;case"INC":if(x=r(w[d]),t("INC",w[e]),"register"!==x.type)throw"INC does not support this operand";z=a.INC_REG,h.push(z,x.value);break;case"DEC":if(x=r(w[d]),t("DEC",w[e]),"register"!==x.type)throw"DEC does not support this operand";z=a.DEC_REG,h.push(z,x.value);break;case"CMP":if(x=r(w[d]),y=r(w[e]),"register"===x.type&&"register"===y.type)z=a.CMP_REG_WITH_REG;else if("register"===x.type&&"regaddress"===y.type)z=a.CMP_REGADDRESS_WITH_REG;else if("register"===x.type&&"address"===y.type)z=a.CMP_ADDRESS_WITH_REG;else{if("register"!==x.type||"number"!==y.type)throw"CMP does not support this operands";z=a.CMP_NUMBER_WITH_REG}h.push(z,x.value,y.value);break;case"JMP":if(x=r(w[d]),t("JMP",w[e]),"register"===x.type)z=a.JMP_REGADDRESS;else{if("number"!==x.type)throw"JMP does not support this operands";z=a.JMP_ADDRESS}h.push(z,x.value);break;case"JC":case"JB":case"JNAE":if(x=r(w[d]),t(A,w[e]),"register"===x.type)z=a.JC_REGADDRESS;else{if("number"!==x.type)throw A+" does not support this operand";z=a.JC_ADDRESS}h.push(z,x.value);break;case"JNC":case"JNB":case"JAE":if(x=r(w[d]),t(A,w[e]),"register"===x.type)z=a.JNC_REGADDRESS;else{if("number"!==x.type)throw A+"does not support this operand";z=a.JNC_ADDRESS}h.push(z,x.value);break;case"JZ":case"JE":if(x=r(w[d]),t(A,w[e]),"register"===x.type)z=a.JZ_REGADDRESS;else{if("number"!==x.type)throw A+" does not support this operand";z=a.JZ_ADDRESS}h.push(z,x.value);break;case"JNZ":case"JNE":if(x=r(w[d]),t(A,w[e]),"register"===x.type)z=a.JNZ_REGADDRESS;else{if("number"!==x.type)throw A+" does not support this operand";z=a.JNZ_ADDRESS}h.push(z,x.value);break;case"JA":case"JNBE":if(x=r(w[d]),t(A,w[e]),"register"===x.type)z=a.JA_REGADDRESS;else{if("number"!==x.type)throw A+" does not support this operand";z=a.JA_ADDRESS}h.push(z,x.value);break;case"JNA":case"JBE":if(x=r(w[d]),t(A,w[e]),"register"===x.type)z=a.JNA_REGADDRESS;else{if("number"!==x.type)throw A+" does not support this operand";z=a.JNA_ADDRESS}h.push(z,x.value);break;case"PUSH":if(x=r(w[d]),t(A,w[e]),"register"===x.type)z=a.PUSH_REG;else if("regaddress"===x.type)z=a.PUSH_REGADDRESS;else if("address"===x.type)z=a.PUSH_ADDRESS;else{if("number"!==x.type)throw"PUSH does not support this operand";z=a.PUSH_NUMBER}h.push(z,x.value);break;case"POP":if(x=r(w[d]),t(A,w[e]),"register"!==x.type)throw"PUSH does not support this operand";z=a.POP_REG,h.push(z,x.value);break;case"CALL":if(x=r(w[d]),t(A,w[e]),"register"===x.type)z=a.CALL_REGADDRESS;else{if("number"!==x.type)throw"CALL does not support this operand";z=a.CALL_ADDRESS}h.push(z,x.value);break;case"RET":t(A,w[d]),z=a.RET,h.push(z);break;case"MUL":if(x=r(w[d]),t(A,w[e]),"register"===x.type)z=a.MUL_REG;else if("regaddress"===x.type)z=a.MUL_REGADDRESS;else if("address"===x.type)z=a.MUL_ADDRESS;else{if("number"!==x.type)throw"MULL does not support this operand";z=a.MUL_NUMBER}h.push(z,x.value);break;case"DIV":if(x=r(w[d]),t(A,w[e]),"register"===x.type)z=a.DIV_REG;else if("regaddress"===x.type)z=a.DIV_REGADDRESS;else if("address"===x.type)z=a.DIV_ADDRESS;else{if("number"!==x.type)throw"DIV does not support this operand";z=a.DIV_NUMBER}h.push(z,x.value);break;case"AND":if(x=r(w[d]),y=r(w[e]),"register"===x.type&&"register"===y.type)z=a.AND_REG_WITH_REG;else if("register"===x.type&&"regaddress"===y.type)z=a.AND_REGADDRESS_WITH_REG;else if("register"===x.type&&"address"===y.type)z=a.AND_ADDRESS_WITH_REG;else{if("register"!==x.type||"number"!==y.type)throw"AND does not support this operands";z=a.AND_NUMBER_WITH_REG}h.push(z,x.value,y.value);break;case"OR":if(x=r(w[d]),y=r(w[e]),"register"===x.type&&"register"===y.type)z=a.OR_REG_WITH_REG;else if("register"===x.type&&"regaddress"===y.type)z=a.OR_REGADDRESS_WITH_REG;else if("register"===x.type&&"address"===y.type)z=a.OR_ADDRESS_WITH_REG;else{if("register"!==x.type||"number"!==y.type)throw"OR does not support this operands";z=a.OR_NUMBER_WITH_REG}h.push(z,x.value,y.value);break;case"XOR":if(x=r(w[d]),y=r(w[e]),"register"===x.type&&"register"===y.type)z=a.XOR_REG_WITH_REG;else if("register"===x.type&&"regaddress"===y.type)z=a.XOR_REGADDRESS_WITH_REG;else if("register"===x.type&&"address"===y.type)z=a.XOR_ADDRESS_WITH_REG;else{if("register"!==x.type||"number"!==y.type)throw"XOR does not support this operands";z=a.XOR_NUMBER_WITH_REG}h.push(z,x.value,y.value);break;case"NOT":if(x=r(w[d]),t(A,w[e]),"register"!==x.type)throw"NOT does not support this operand";z=a.NOT_REG,h.push(z,x.value);break;case"SHL":case"SAL":if(x=r(w[d]),y=r(w[e]),"register"===x.type&&"register"===y.type)z=a.SHL_REG_WITH_REG;else if("register"===x.type&&"regaddress"===y.type)z=a.SHL_REGADDRESS_WITH_REG;else if("register"===x.type&&"address"===y.type)z=a.SHL_ADDRESS_WITH_REG;else{if("register"!==x.type||"number"!==y.type)throw A+" does not support this operands";z=a.SHL_NUMBER_WITH_REG}h.push(z,x.value,y.value);break;case"SHR":case"SAR":if(x=r(w[d]),y=r(w[e]),"register"===x.type&&"register"===y.type)z=a.SHR_REG_WITH_REG;else if("register"===x.type&&"regaddress"===y.type)z=a.SHR_REGADDRESS_WITH_REG;else if("register"===x.type&&"address"===y.type)z=a.SHR_ADDRESS_WITH_REG;else{if("register"!==x.type||"number"!==y.type)throw A+" does not support this operands";z=a.SHR_NUMBER_WITH_REG}h.push(z,x.value,y.value);break;default:throw"Invalid instruction: "+w[2]}}}else{var D=l[u].trim();if(""!==D&&";"!==D.slice(0,1))throw"Syntax error"}}catch(E){throw{error:E,line:u}}for(u=0,v=h.length;v>u;u++)if(!angular.isNumber(h[u])){if(!(h[u]in j))throw{error:"Undefined label: "+h[u]};h[u]=j[h[u]]}return{code:h,mapping:i,labels:j}}}}]),app.service("cpu",["opcodes","memory",function(a,b){var c={step:function(){var c=this;if(c.fault===!0)throw"FAULT. Reset to continue.";try{var d=function(a){if(0>a||a>=c.gpr.length)throw"Invalid register: "+a;return a},e=function(a){if(0>a||a>=1+c.gpr.length)throw"Invalid register: "+a;return a},f=function(a,b){if(a>=0&&ac.maxSP)throw"Stack underflow"}},g=function(a){if(a>=0&&a15&&(e-=32),b+e},i=function(a){return c.zero=!1,c.carry=!1,a>=256?(c.carry=!0,a%=256):0===a?c.zero=!0:0>a&&(c.carry=!0,a=256- -a%256),a},j=function(a){if(0>a||a>=b.data.length)throw"IP outside memory";c.ip=a},k=function(a){if(b.store(c.sp--,a),c.spc.maxSP)throw"Stack underflow";return a},m=function(a){if(0===a)throw"Division by 0";return Math.floor(c.gpr[0]/a)};if(c.ip<0||c.ip>=b.data.length)throw"Instruction pointer is outside of memory";var n,o,p,q,r,s=b.load(c.ip);switch(s){case a.NONE:return!1;case a.MOV_REG_TO_REG:n=e(b.load(++c.ip)),o=e(b.load(++c.ip)),f(n,g(o)),c.ip++;break;case a.MOV_ADDRESS_TO_REG:n=e(b.load(++c.ip)),p=b.load(++c.ip),f(n,b.load(p)),c.ip++;break;case a.MOV_REGADDRESS_TO_REG:n=e(b.load(++c.ip)),o=b.load(++c.ip),f(n,b.load(h(o))),c.ip++;break;case a.MOV_REG_TO_ADDRESS:q=b.load(++c.ip),o=e(b.load(++c.ip)),b.store(q,g(o)),c.ip++;break;case a.MOV_REG_TO_REGADDRESS:n=b.load(++c.ip),o=e(b.load(++c.ip)),b.store(h(n),g(o)),c.ip++;break;case a.MOV_NUMBER_TO_REG:n=e(b.load(++c.ip)),r=b.load(++c.ip),f(n,r),c.ip++;break;case a.MOV_NUMBER_TO_ADDRESS:q=b.load(++c.ip),r=b.load(++c.ip),b.store(q,r),c.ip++;break;case a.MOV_NUMBER_TO_REGADDRESS:n=b.load(++c.ip),r=b.load(++c.ip),b.store(h(n),r),c.ip++;break;case a.ADD_REG_TO_REG:n=e(b.load(++c.ip)),o=e(b.load(++c.ip)),f(n,i(g(n)+g(o))),c.ip++;break;case a.ADD_REGADDRESS_TO_REG:n=e(b.load(++c.ip)),o=b.load(++c.ip),f(n,i(g(n)+b.load(h(o)))),c.ip++;break;case a.ADD_ADDRESS_TO_REG:n=e(b.load(++c.ip)),p=b.load(++c.ip),f(n,i(g(n)+b.load(p))),c.ip++;break;case a.ADD_NUMBER_TO_REG:n=e(b.load(++c.ip)),r=b.load(++c.ip),f(n,i(g(n)+r)),c.ip++;break;case a.SUB_REG_FROM_REG:n=e(b.load(++c.ip)),o=e(b.load(++c.ip)),f(n,i(g(n)-c.gpr[o])),c.ip++;break;case a.SUB_REGADDRESS_FROM_REG:n=e(b.load(++c.ip)),o=b.load(++c.ip),f(n,i(g(n)-b.load(h(o)))),c.ip++;break;case a.SUB_ADDRESS_FROM_REG:n=e(b.load(++c.ip)),p=b.load(++c.ip),f(n,i(g(n)-b.load(p))),c.ip++;break;case a.SUB_NUMBER_FROM_REG:n=e(b.load(++c.ip)),r=b.load(++c.ip),f(n,i(g(n)-r)),c.ip++;break;case a.INC_REG:n=e(b.load(++c.ip)),f(n,i(g(n)+1)),c.ip++;break;case a.DEC_REG:n=e(b.load(++c.ip)),f(n,i(g(n)-1)),c.ip++;break;case a.CMP_REG_WITH_REG:n=e(b.load(++c.ip)),o=e(b.load(++c.ip)),i(g(n)-g(o)),c.ip++;break;case a.CMP_REGADDRESS_WITH_REG:n=e(b.load(++c.ip)),o=b.load(++c.ip),i(g(n)-b.load(h(o))),c.ip++;break;case a.CMP_ADDRESS_WITH_REG:n=e(b.load(++c.ip)),p=b.load(++c.ip),i(g(n)-b.load(p)),c.ip++;break;case a.CMP_NUMBER_WITH_REG:n=e(b.load(++c.ip)),r=b.load(++c.ip),i(g(n)-r),c.ip++;break;case a.JMP_REGADDRESS:n=d(b.load(++c.ip)),j(c.gpr[n]);break;case a.JMP_ADDRESS:r=b.load(++c.ip),j(r);break;case a.JC_REGADDRESS:n=d(b.load(++c.ip)),c.carry?j(c.gpr[n]):c.ip++;break;case a.JC_ADDRESS:r=b.load(++c.ip),c.carry?j(r):c.ip++;break;case a.JNC_REGADDRESS:n=d(b.load(++c.ip)),c.carry?c.ip++:j(c.gpr[n]);break;case a.JNC_ADDRESS:r=b.load(++c.ip),c.carry?c.ip++:j(r);break;case a.JZ_REGADDRESS:n=d(b.load(++c.ip)),c.zero?j(c.gpr[n]):c.ip++;break;case a.JZ_ADDRESS:r=b.load(++c.ip),c.zero?j(r):c.ip++;break;case a.JNZ_REGADDRESS:n=d(b.load(++c.ip)),c.zero?c.ip++:j(c.gpr[n]);break;case a.JNZ_ADDRESS:r=b.load(++c.ip),c.zero?c.ip++:j(r);break;case a.JA_REGADDRESS:n=d(b.load(++c.ip)),c.zero||c.carry?c.ip++:j(c.gpr[n]);break;case a.JA_ADDRESS:r=b.load(++c.ip),c.zero||c.carry?c.ip++:j(r);break;case a.JNA_REGADDRESS:n=d(b.load(++c.ip)),c.zero||c.carry?j(c.gpr[n]):c.ip++;break;case a.JNA_ADDRESS:r=b.load(++c.ip),c.zero||c.carry?j(r):c.ip++;break;case a.PUSH_REG:o=d(b.load(++c.ip)),k(c.gpr[o]),c.ip++;break;case a.PUSH_REGADDRESS:o=b.load(++c.ip),k(b.load(h(o))),c.ip++;break;case a.PUSH_ADDRESS:p=b.load(++c.ip),k(b.load(p)),c.ip++;break;case a.PUSH_NUMBER:r=b.load(++c.ip),k(r),c.ip++;break;case a.POP_REG:n=d(b.load(++c.ip)),c.gpr[n]=l(),c.ip++;break;case a.CALL_REGADDRESS:n=d(b.load(++c.ip)),k(c.ip+1),j(c.gpr[n]);break;case a.CALL_ADDRESS:r=b.load(++c.ip),k(c.ip+1),j(r);break;case a.RET:j(l());break;case a.MUL_REG:o=d(b.load(++c.ip)),c.gpr[0]=i(c.gpr[0]*c.gpr[o]),c.ip++;break;case a.MUL_REGADDRESS:o=b.load(++c.ip),c.gpr[0]=i(c.gpr[0]*b.load(h(o))),c.ip++;break;case a.MUL_ADDRESS:p=b.load(++c.ip),c.gpr[0]=i(c.gpr[0]*b.load(p)),c.ip++;break;case a.MUL_NUMBER:r=b.load(++c.ip),c.gpr[0]=i(c.gpr[0]*r),c.ip++;break;case a.DIV_REG:o=d(b.load(++c.ip)),c.gpr[0]=i(m(c.gpr[o])),c.ip++;break;case a.DIV_REGADDRESS:o=b.load(++c.ip),c.gpr[0]=i(m(b.load(h(o)))),c.ip++;break;case a.DIV_ADDRESS:p=b.load(++c.ip),c.gpr[0]=i(m(b.load(p))),c.ip++;break;case a.DIV_NUMBER:r=b.load(++c.ip),c.gpr[0]=i(m(r)),c.ip++;break;case a.AND_REG_WITH_REG:n=d(b.load(++c.ip)),o=d(b.load(++c.ip)),c.gpr[n]=i(c.gpr[n]&c.gpr[o]),c.ip++;break;case a.AND_REGADDRESS_WITH_REG:n=d(b.load(++c.ip)),o=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]&b.load(h(o))),c.ip++;break;case a.AND_ADDRESS_WITH_REG:n=d(b.load(++c.ip)),p=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]&b.load(p)),c.ip++;break;case a.AND_NUMBER_WITH_REG:n=d(b.load(++c.ip)),r=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]&r),c.ip++;break;case a.OR_REG_WITH_REG:n=d(b.load(++c.ip)),o=d(b.load(++c.ip)),c.gpr[n]=i(c.gpr[n]|c.gpr[o]),c.ip++;break;case a.OR_REGADDRESS_WITH_REG:n=d(b.load(++c.ip)),o=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]|b.load(h(o))),c.ip++;break;case a.OR_ADDRESS_WITH_REG:n=d(b.load(++c.ip)),p=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]|b.load(p)),c.ip++;break;case a.OR_NUMBER_WITH_REG:n=d(b.load(++c.ip)),r=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]|r),c.ip++;break;case a.XOR_REG_WITH_REG:n=d(b.load(++c.ip)),o=d(b.load(++c.ip)),c.gpr[n]=i(c.gpr[n]^c.gpr[o]),c.ip++;break;case a.XOR_REGADDRESS_WITH_REG:n=d(b.load(++c.ip)),o=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]^b.load(h(o))),c.ip++;break;case a.XOR_ADDRESS_WITH_REG:n=d(b.load(++c.ip)),p=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]^b.load(p)),c.ip++;break;case a.XOR_NUMBER_WITH_REG:n=d(b.load(++c.ip)),r=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]^r),c.ip++;break;case a.NOT_REG:n=d(b.load(++c.ip)),c.gpr[n]=i(~c.gpr[n]),c.ip++;break;case a.SHL_REG_WITH_REG:n=d(b.load(++c.ip)),o=d(b.load(++c.ip)),c.gpr[n]=i(c.gpr[n]<>>c.gpr[o]),c.ip++;break;case a.SHR_REGADDRESS_WITH_REG:n=d(b.load(++c.ip)),o=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]>>>b.load(h(o))),c.ip++;break;case a.SHR_ADDRESS_WITH_REG:n=d(b.load(++c.ip)),p=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]>>>b.load(p)),c.ip++;break;case a.SHR_NUMBER_WITH_REG:n=d(b.load(++c.ip)),r=b.load(++c.ip),c.gpr[n]=i(c.gpr[n]>>>r),c.ip++;break;default:throw"Invalid op code: "+s}return!0}catch(t){throw c.fault=!0,t}},reset:function(){var a=this;a.maxSP=231,a.minSP=0,a.gpr=[0,0,0,0],a.sp=a.maxSP,a.ip=0,a.zero=!1,a.carry=!1,a.fault=!1}};return c.reset(),c}]),app.service("memory",[function(){var a={data:Array(256),lastAccess:-1,load:function(a){var b=this;if(0>a||a>=b.data.length)throw"Memory access violation at "+a;return b.lastAccess=a,b.data[a]},store:function(a,b){var c=this;if(0>a||a>=c.data.length)throw"Memory access violation at "+a;c.lastAccess=a,c.data[a]=b},reset:function(){var a=this;a.lastAccess=-1;for(var b=0,c=a.data.length;c>b;b++)a.data[b]=0}};return a.reset(),a}]),app.service("opcodes",[function(){var a={NONE:0,MOV_REG_TO_REG:1,MOV_ADDRESS_TO_REG:2,MOV_REGADDRESS_TO_REG:3,MOV_REG_TO_ADDRESS:4,MOV_REG_TO_REGADDRESS:5,MOV_NUMBER_TO_REG:6,MOV_NUMBER_TO_ADDRESS:7,MOV_NUMBER_TO_REGADDRESS:8,ADD_REG_TO_REG:10,ADD_REGADDRESS_TO_REG:11,ADD_ADDRESS_TO_REG:12,ADD_NUMBER_TO_REG:13,SUB_REG_FROM_REG:14,SUB_REGADDRESS_FROM_REG:15,SUB_ADDRESS_FROM_REG:16,SUB_NUMBER_FROM_REG:17,INC_REG:18,DEC_REG:19,CMP_REG_WITH_REG:20,CMP_REGADDRESS_WITH_REG:21,CMP_ADDRESS_WITH_REG:22,CMP_NUMBER_WITH_REG:23,JMP_REGADDRESS:30,JMP_ADDRESS:31,JC_REGADDRESS:32,JC_ADDRESS:33,JNC_REGADDRESS:34,JNC_ADDRESS:35,JZ_REGADDRESS:36,JZ_ADDRESS:37,JNZ_REGADDRESS:38,JNZ_ADDRESS:39,JA_REGADDRESS:40,JA_ADDRESS:41,JNA_REGADDRESS:42,JNA_ADDRESS:43,PUSH_REG:50,PUSH_REGADDRESS:51,PUSH_ADDRESS:52,PUSH_NUMBER:53,POP_REG:54,CALL_REGADDRESS:55,CALL_ADDRESS:56,RET:57,MUL_REG:60,MUL_REGADDRESS:61,MUL_ADDRESS:62,MUL_NUMBER:63,DIV_REG:64,DIV_REGADDRESS:65,DIV_ADDRESS:66,DIV_NUMBER:67,AND_REG_WITH_REG:70,AND_REGADDRESS_WITH_REG:71,AND_ADDRESS_WITH_REG:72,AND_NUMBER_WITH_REG:73,OR_REG_WITH_REG:74,OR_REGADDRESS_WITH_REG:75,OR_ADDRESS_WITH_REG:76,OR_NUMBER_WITH_REG:77,XOR_REG_WITH_REG:78,XOR_REGADDRESS_WITH_REG:79,XOR_ADDRESS_WITH_REG:80,XOR_NUMBER_WITH_REG:81,NOT_REG:82,SHL_REG_WITH_REG:90,SHL_REGADDRESS_WITH_REG:91,SHL_ADDRESS_WITH_REG:92,SHL_NUMBER_WITH_REG:93,SHR_REG_WITH_REG:94,SHR_REGADDRESS_WITH_REG:95,SHR_ADDRESS_WITH_REG:96,SHR_NUMBER_WITH_REG:97};return a}]),app.controller("Ctrl",["$document","$scope","$timeout","cpu","memory","assembler",function(a,b,c,d,e,f){b.memory=e,b.cpu=d,b.error="",b.isRunning=!1,b.displayHex=!0,b.displayInstr=!0,b.displayA=!1,b.displayB=!1,b.displayC=!1,b.displayD=!1,b.speeds=[{speed:1,desc:"1 HZ"},{speed:4,desc:"4 HZ"},{speed:8,desc:"8 HZ"},{speed:16,desc:"16 HZ"}],b.speed=4,b.outputStartIndex=232,b.code='; Simple example\n; Writes Hello World to the output\n\n JMP start\nhello: DB "Hello World!" ; Variable\n DB 0 ; String terminator\n\nstart:\n MOV C, hello ; Point to var \n MOV D, 232 ; Point to output\n CALL print\n HLT ; Stop execution\n\nprint: ; print(C:*from, D:*to)\n PUSH A\n PUSH B\n MOV B, 0\n.loop:\n MOV A, [C] ; Get char from var\n MOV [D], A ; Write to output\n INC C\n INC D \n CMP B, [C] ; Check if end\n JNZ .loop ; jump if not\n\n POP B\n POP A\n RET',b.reset=function(){d.reset(),e.reset(),b.error="",b.selectedLine=-1},b.executeStep=function(){b.checkPrgrmLoaded()||b.assemble();try{var a=d.step();return d.ip in b.mapping&&(b.selectedLine=b.mapping[d.ip]),a}catch(c){return b.error=c,!1}};var g;b.run=function(){b.checkPrgrmLoaded()||b.assemble(),b.isRunning=!0,g=c(function(){b.executeStep()===!0?b.run():b.isRunning=!1},1e3/b.speed)},b.stop=function(){c.cancel(g),b.isRunning=!1},b.checkPrgrmLoaded=function(){for(var a=0,b=e.data.length;b>a;a++)if(0!==e.data[a])return!0;return!1},b.getChar=function(a){var b=String.fromCharCode(a);return""===b.trim()?"  ":b},b.assemble=function(){try{b.reset();var a=f.go(b.code);b.mapping=a.mapping;var c=a.code;if(b.labels=a.labels,c.length>e.data.length)throw"Binary code does not fit into the memory. Max "+e.data.length+" bytes are allowed";for(var d=0,g=c.length;g>d;d++)e.data[d]=c[d]}catch(h){void 0!==h.line?(b.error=h.line+" | "+h.error,b.selectedLine=h.line):b.error=h.error}},b.jumpToLine=function(c){a[0].getElementById("sourceCode").scrollIntoView(),b.selectedLine=b.mapping[c]},b.isInstruction=function(a){return void 0!==b.mapping&&void 0!==b.mapping[a]&&b.displayInstr},b.getMemoryCellCss=function(a){return a>=b.outputStartIndex?"output-bg":b.isInstruction(a)?"instr-bg":a>d.sp&&a<=d.maxSP?"stack-bg":""},b.getMemoryInnerCellCss=function(a){return a===d.ip?"marker marker-ip":a===d.sp?"marker marker-sp":a===d.gpr[0]&&b.displayA?"marker marker-a":a===d.gpr[1]&&b.displayB?"marker marker-b":a===d.gpr[2]&&b.displayC?"marker marker-c":a===d.gpr[3]&&b.displayD?"marker marker-d":""}}]),app.filter("flag",function(){return function(a){return a.toString().toUpperCase()}}),app.filter("number",function(){return function(a,b){if(b){var c=a.toString(16).toUpperCase();return 1==c.length?"0"+c:c}return a.toString(10)}}),app.directive("selectLine",[function(){return{restrict:"A",link:function(a,b,c,d){a.$watch("selectedLine",function(){if(a.selectedLine>=0){for(var c=b[0].value.split("\n"),d=0,e=0;e