๋ฆฌ๋ ๋ณด๋-JIT ์ปดํ์ผ (๋ฎ์์๋ก ์ข์)
- es1024-81.2 ์ (์๋์ค์ธ ์ปดํ์ผ๋ฌ ํฌํจ)
- ํค ์ํธ ๋๋ฌ-116 ํฌ์ธํธ
- ์-121 ํฌ์ธํธ
๋ฆฌ๋ ๋ณด๋-ํด์ ๋จ (๋ฎ์์๋ก ์ข์)
- Martin Bรผttner-706654 ์ (์ฝ 2 ์๊ฐ ์ ๋).
- criptych-30379 ํฌ์ธํธ (97 ์ด)
๋น์ ์ ์๋ฌด๋ ๋น์ ์ด ๊ทธ๊ฒ์ ๋ฐ์๋ค์ด๋๋ก ์ ํํ๋ค๋ฉด ๊ฐ๋ฅํ ๊ฐ์ฅ ์์ ๋ฐ์ดํธ ์ฝ๋ ์ธํฐํ๋ฆฌํฐ / VM์ ์์ฑํ๋ ๊ฒ์ ๋๋ค. VM / ์ธํฐํ๋ฆฌํฐ๋ ์๋์ ์ง์ ๋ ์ธ์ด๋ก ์์ CISC ์ํคํ ์ฒ (์์ ํฌ๊ธฐ๊ฐ ๋ค๋ฅผ ์ ์์)๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์๋ฃ๋๋ฉด 3 ๊ฐ์ CPU ๋ ์ง์คํฐ ๊ฐ์ ์ธ์ํ์ฌ ์ฌ๋ฐ๋ฅธ ์ถ๋ ฅ์ด ์ธ์๋์์์ ์ฆ๋ช ํด์ผํฉ๋๋ค (3,126,900,366).
์ปดํ์ผ๋ฌ
์์ฒด ํ ์คํธ๋ฅผ ์ํ๋ค๋ฉด ์ปดํ์ผ๋ฌ๊ฐ ์๋์ ๊ฒ์๋์ด ์์ต๋๋ค. ๋ต์ ๊ฐ์ง๊ณ ํ ์คํธ๋ฅผ ๊ฒ์ํ์ญ์์ค.
window.compile=function(){var e=$("#text").val().toLowerCase().match(/[^\r\n]+/g);var t=[];for(var n=0;n<e.length;n++)compileLine(e[n],t);var r="";for(var n=0;n<t.length;n++)if(typeof t[n]=="string")r+="\n";else r+="0x"+t[n].toString(16)+" ";$("#compiledArray").val(r)};window.compileLine=function(e,t){var n=e.split(" ");if(n[0]=="load"){t.push(0);t.push(getInt(n[1]));t.pushArr(getInt(n[2]))}if(n[0]=="rload"){t.push(1);t.push(getInt(n[1]));t.push(getInt(n[1]))}if(n[0]=="push"){t.push(2);t.push(getInt(n[1]))}if(n[0]=="pop"){t.push(3);t.push(getInt(n[1]))}if(n[0]=="add"){t.push(4);t.push(getInt(n[1]));t.push(getInt(n[2]))}if(n[0]=="sub"){t.push(5);t.push(getInt(n[1]));t.push(getInt(n[2]))}if(n[0]=="mul"){t.push(6);t.push(getInt(n[1]));t.push(getInt(n[2]))}if(n[0]=="div"){t.push(7);t.push(getInt(n[1]));t.push(getInt(n[2]))}if(n[0]=="jmp"){t.push(8);t.pushArr(getInt(n[1]))}if(n[0]=="cmp"){t.push(9);t.push(getInt(n[1]));t.push(getInt(n[2]))}if(n[0]=="branchlt"){t.push(10);t.pushArr(getInt(n[1]))}if(n[0]=="brancheq"){t.push(11);t.pushArr(getInt(n[1]))}if(n[0]=="branchgt"){t.push(12);t.pushArr(getInt(n[1]))}if(n[0]=="branchne"){t.push(13);t.pushArr(getInt(n[1]))}t.push("NEW LINE")};window.getInt=function(e){if(e.trim().startsWith("<--"))return"COMMENT";if(e=="r0")return 0;if(e=="r1")return 1;if(e=="r2")return 2;if(e.startsWith("0x"))return parseInt(e,16);if(isNaN(parseInt(e)))alert(e);return getIntBytes(parseInt(e))};if(typeof String.prototype.startsWith!="function"){String.prototype.startsWith=function(e){return this.slice(0,e.length)==e}}Array.prototype.pushArr=function(e){this.push.apply(this,e)};window.getIntBytes=function(e){var t=[];var n=4;do{t[--n]=e&255;e=e>>8}while(n);return t}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<textarea id="text" cols="40" rows="10"></textarea>
<br/>
<button onclick="compile()">Compile</button>
<br/>
<textarea id="compiledArray" cols="40" rows="10" readonly></textarea>
โVMโ์ฌ์
VM์๋ 3 ๊ฐ์ 32 ๋นํธ ๋ถํธ์๋ ์ ์ ๋ ์ง์คํฐ R0, R1, R2๊ฐ ์์ต๋๋ค. 16 ์ง์๋ก 0x00, 0x01 ๋ฐ 0x02๋ก ํ์๋ฉ๋๋ค.
๋ค์ ์์ ์ด ์ง์๋์ด์ผํฉ๋๋ค.
ํ์์ [์ด๋ฆ] [โฆ ํผ์ฐ์ฐ์ โฆ], [16 ์ง์ ์ฐ์ฐ ์ฝ๋] [โฆ ํผ์ฐ์ฐ์ ๋ฐ๋ณต โฆ]์ ๋๋ค.
- LOAD [๋ ์ง์คํฐ] [4 ๋ฐ์ดํธ ๊ฐ], 0x00 [๋ ์ง์คํฐ] [4 ๋ฐ์ดํธ ๊ฐ]
- PUSH [๋ฑ๋ก], 0x02 [๋ฑ๋ก]
- POP [๋ฑ๋ก], 0x03 [๋ฑ๋ก]
- ADD [๋ ์ง์คํฐ, 1 ๋ฐ์ดํธ] [๋ ์ง์คํฐ, 1 ๋ฐ์ดํธ], 0x04 [๋ ์ง์คํฐ] [๋ ์ง์คํฐ]
- SUB [๋ ์ง์คํฐ, 1 ๋ฐ์ดํธ] [๋ ์ง์คํฐ, 1 ๋ฐ์ดํธ], 0x05 [๋ ์ง์คํฐ] [๋ ์ง์คํฐ]
- MUL [๋ ์ง์คํฐ, 1 ๋ฐ์ดํธ] [๋ ์ง์คํฐ, 1 ๋ฐ์ดํธ], 0x06 [๋ ์ง์คํฐ] [๋ ์ง์คํฐ]
- DIV [register, 1 byte] [register, 1 byte], 0x07 [register] [register]
- JMP [์ฝ๋ ๋ผ์ธ, 4 ๋ฐ์ดํธ], 0x08 [4 ๋ฐ์ดํธ ์ฝ๋ ๋ผ์ธ ๋ฒํธ]
- CMP [๋ ์ง์คํฐ, 1 ๋ฐ์ดํธ] [๋ ์ง์คํฐ, 1 ๋ฐ์ดํธ], 0x09 [๋ ์ง์คํฐ] [๋ ์ง์คํฐ]
- BRANCHLT [์ฝ๋ ๋ผ์ธ, 4 ๋ฐ์ดํธ], 0x0a [4 ๋ฐ์ดํธ ์ฝ๋ ๋ผ์ธ ๋ฒํธ]
๋ช ๊ฐ์ง ์ฐธ๊ณ ์ฌํญ :
- ์์ ์ํ ์ฐ์ฐ์ 2 ๊ฐ์ ๋ ์ง์คํฐ ๊ฐ์ ๋ํ์ฌ ์ถ๋ ฅ์ ์ฒซ ๋ฒ์งธ ๋ ์ง์คํฐ์ ๋ฐฐ์นํฉ๋๋ค.
- ๋น๊ต ์ฐ์ฐ์ ์ธ CMP๋ 2 ๊ฐ์ ๋ ์ง์คํฐ ๊ฐ์ ๋น๊ตํ๊ณ ๋์ค์ ๋ถ๊ธฐ ๋ช ๋ น์ด์์ ์ฌ์ฉํ ์ ์๋๋ก ์ผ๋ถ ๋ด๋ถ ํ๋๊ทธ (๊ตฌํ์ ๋ฐ๋ผ ๋ค๋ฅผ ์ ์์)์ ์ถ๋ ฅ์ ์ ์ฅํด์ผํฉ๋๋ค.
- CRAN ์ ์ BRANCH๋ฅผ ํธ์ถ ํ ๊ฒฝ์ฐ BRANCHEQ๋ฅผ ํธ์ถํ์ง ์์ผ๋ฉด โVMโ์ ๋ถ๊ธฐ๋์ง ์์์ผํฉ๋๋ค.
- PUSH / POP๋ ๋น์ฐํ ์คํ์์ ์ซ์๋ฅผ ํธ์ํ๊ฑฐ๋ ํํฉ๋๋ค.
- ์ ํ ๋ฐ ๋ถ๊ธฐ ์ฐ์ฐ์๋ ์ด์ง ์ฃผ์๊ฐ ์๋ ํน์ ์์ (์ฝ๋ ๋ผ์ธ)์ผ๋ก ์ด๋ํฉ๋๋ค.
- ์ง์ ์์ ์ ๋น๊ต๋ฅผ ์ํํ์ง ์์ต๋๋ค. ์คํ๋ ค ๋ง์ง๋ง ๋น๊ต์์ ์ถ๋ ฅ์ ๊ฐ์ ธ์ ์คํํฉ๋๋ค.
- ๋ถ๊ธฐ ๋ฐ ์ ํ ์ฐ์ฐ์๋ 0๋ถํฐ ์์ํ๋ ๋ผ์ธ ๋ฒํธ ์ธ๋ฑ์ฑ ์์คํ ์ ์ฌ์ฉํฉ๋๋ค. (์ : JMP 0์ด ์ฒซ ๋ฒ์งธ ์ค๋ก ์ด๋)
- ๋ชจ๋ ์ฐ์ฐ์ 0์ผ๋ก ์ค๋ฒ ํ๋ก์ฐ๋๊ณ ์ ์ ์ค๋ฒ ํ๋ก์ฐ์์ ์์ธ๋ฅผ ๋ฐ์์ํค์ง ์๋ ๋ถํธ์๋ ์ซ์์ ๋ํด ์ํ๋ฉ๋๋ค.
- 0์ผ๋ก ๋๋๋ ๊ฒ์ ํ์ฉ๋์ง ์์ผ๋ฏ๋ก ํ๋ก๊ทธ๋จ์ ๋์์ ์ ์๋์ง ์์ต๋๋ค. ์๋ฅผ ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ํ๋ก๊ทธ๋จ์ ์ค๋จํ์ญ์์ค.
- VM์ ์คํ์ ์ข ๋ฃํ๊ณ ํ์ฌ ์ํ๋ฅผ ๋ฐํํฉ๋๋ค.
- โERR : Division by 0โณ๋ฉ์์ง๋ฅผ ํ์ํ์ญ์์ค.
- ํ๋ก๊ทธ๋จ ์ข ๋ฃ๋ ๋ช ๋ น ํฌ์ธํฐ๊ฐ ํ๋ก๊ทธ๋จ ๋์ ๋๋ฌ ํ ๋์ ๊ฐ์ด ์ ์๋ฉ๋๋ค (๋น ๋น์ด์๋ ํ๋ก๊ทธ๋จ์ ๊ฐ์ ํ ์ ์์).
์ถ๋ ฅ
์ถ๋ ฅ์ ์ ํํ์ด ๊ฐ์ด์ด์ผํฉ๋๋ค (์ค ๋ฐ๊พธ๊ธฐ ํฌํจ).
R0 3126900366
R1 0
R2 10000
ํฌ์ธํธ
ํฌ์ธํธ๋ ๋ค์ ๊ณต์์ ๊ธฐ๋ฐ์ผ๋ก ๊ณ์ฐ๋ฉ๋๋ค.Number Of Characters * (Seconds Needed To Run / 2)
๋ค๋ฅธ ์๊ฐ์ ์ ๋ฐํ๋ ํ๋์จ์ด ์ฐจ์ด๋ฅผ ํผํ๊ธฐ ์ํด ๊ฐ ํ ์คํธ๋ ์ฐ๋ถํฌ ์๋ฒ ๋๋ Windows 8์ ๋ด ์ปดํจํฐ (i5-4210u, 8GB ๋จ)์์ ์คํ๋๋ฏ๋ก Dual G5์์๋ง ์ปดํ์ผ๋๋ ๋ฏธ์น ์ด๊ตญ์ ์ธ ๋ฐํ์์ ์ฌ์ฉํ์ง ๋ง์ญ์์ค ์ ํํ 762.66MB์ ์ฌ์ฉ ๊ฐ๋ฅํ RAM์ด์๋ Mac Pro.
ํน์ํ ๋ฐํ์ / ์ธ์ด๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ๋งํฌ๋ฅผ ๊ฒ์ํ์ญ์์ค.
- ๊ด์ฌ์๋ ์ฌ๋๋ค์ ์ํด ํ ์คํธ ์ฝ๋ (C #์ผ๋ก ์์ฑ)๋ฅผ ๊ฒ์ํ์ต๋๋ค : http://pastebin.com/WYCG5Uqu
ํ ์คํธ ํ๋ก๊ทธ๋จ
์์ด๋์ด๋ ์ฌ๊ธฐ ์์ ์ ์ผ๋ฏ๋ก ์ฝ๊ฐ ์์ ๋ ๋ฒ์ ์ ํ๋ก๊ทธ๋จ์ ์ฌ์ฉํฉ๋๋ค.
ํ๋ก๊ทธ๋จ์ ์ฌ๋ฐ๋ฅธ ์ถ๋ ฅ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. 3,126,900,366
C์์ :
int s, i, j;
for (s = 0, i = 0; i < 10000; i++) {
for (j = 0; j < 10000; j++)
s += (i * j) / 3;
}
์ฝ๋์์ : [R0์ s, j์ R1, i์ R2๋ฅผ ๋ํ๋]
LOAD R0 0
LOAD R2 0 <--outer loop value
LOAD R1 0 <--inner loop value
--Begin inner loop--
PUSH R1 <--push inner loop value to the stack
MUL R1 R2 <--(i*j)
PUSH R2
LOAD R2 3
DIV R1 R2 <-- / 3
POP R2
ADD R0 R1 <-- s+=
POP R1
PUSH R2
LOAD R2 1
ADD R1 R2 <--j++
POP R2
PUSH R2
LOAD R2 10000
CMP R1 R2 <-- j < 10000
POP R2
BRANCHLT 3 <--Go back to beginning inner loop
--Drop To outer loop--
LOAD R1 1
ADD R2 R1 <--i++
LOAD R1 10000
CMP R2 R1 <-- i < 10000
LOAD R1 0 <--Reset inner loop
BRANCHLT 2
์ด์ง / ์ก๊ฐ์ผ๋ก :
0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x02 0x00 0x00 0x00 0x00
0x00 0x01 0x00 0x00 0x00 0x00
0x02 0x01
0x06 0x01 0x02
0x02 0x02
0x00 0x02 0x00 0x00 0x00 0x03
0x07 0x01 0x02
0x03 0x02
0x04 0x00 0x01
0x03 0x01
0x02 0x02
0x00 0x02 0x00 0x00 0x00 0x01
0x04 0x01 0x02
0x03 0x02
0x02 0x02
0x00 0x02 0x00 0x00 0x27 0x10
0x09 0x01 0x02
0x03 0x02
0x0a 0x00 0x00 0x00 0x03
0x00 0x01 0x00 0x00 0x00 0x01
0x04 0x02 0x01
0x00 0x01 0x00 0x00 0x27 0x10
0x09 0x02 0x01
0x00 0x01 0x00 0x00 0x00 0x00
0x0a 0x00 0x00 0x00 0x02
๋ณด๋์ค ํฌ์ธํธ
(ํจ๊ณผ๋ ๊ณฑ์
์ผ๋ก ์ ์ฉ๋จ) ์๋ฅผ ๋ค์ด ์ธ ๊ฐ์ง ๋ชจ๋์ ํด๋น๋๋ ๊ฒฝ์ฐ ((๋ฌธ์ * 0.50) * 0.75) * 0.90
- ์ธํฐํ๋ฆฌํฐ๊ฐ ์ค์ ๋ก JIT ์ปดํ์ผ๋ฌ ์ธ ๊ฒฝ์ฐ 50 % ๊ฐ์
- ๋ฃจํ ์ธ ๋กค๋ง / ์๋ฏธ์๋ ์ต์ ํ๋ฅผ ์ ์ฉํ๋ฉด 25 % ๊ฐ์ํฉ๋๋ค.
- VM์ ํ์ฅํ๋ฉด 10 % ๊ฐ์
- BRANCHEQ [์ฝ๋ ๋ผ์ธ, 4 ๋ฐ์ดํธ] (๋์ผํ ์ง์ -opcode 0x0b)
- BRANCHGT [์ฝ๋ ๋ผ์ธ, 4 ๋ฐ์ดํธ] (๋ถ๊ธฐ๋ณด๋ค ํฐ ๊ฒฝ์ฐ-opcode 0x0c)
- BRANCHNE [์ฝ๋ ๋ผ์ธ, 4 ๋ฐ์ดํธ] (๋์ผํ์ง ์์ ์ง์ -opcode 0x0d)
- RLOAD [๋ ์ง์คํฐ 1] [๋ ์ง์คํฐ 2] (๋ ์ง์คํฐ 2์ ๊ฐ์ ์ด๋ํ์ฌ ๋ ์ง์คํฐ 1-opcode 0x01).
ํ์ฉ๋์ง ์์
- ํ ์คํธ ์ผ์ด์ค๋ฅผ ํ๋ก๊ทธ๋จ์ ์ฌ์ ์ปดํ์ผํ๋ ๊ฒ์ ๊ธ์ง๋์ด ์์ต๋๋ค. STDIN ๋๋ ํ์ผ์์ ๋ฐ์ดํธ ์ฝ๋๋ฅผ ์น์ธํด์ผํฉ๋๋ค (์ด๋ค ๊ฒ์ด ๋ ์๊ด ์์ต๋๋ค).
- ํ๋ก๊ทธ๋จ์ ์คํํ์ง ์๊ณ ์ถ๋ ฅ์ ๋ฐํํฉ๋๋ค.
- VM ์๊ตฌ ์ฌํญ์ ์์ด๋ ค๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ.
๋ต๋ณ
C, 752 (ํ๋๊ทธ ์ ์์ ๊ฒฝ์ฐ 589 + 163) * 0.5 (JIT) * 0.9 (ํ์ฅ์) * (0.75 ์ต์ ํ) * (0.64 ์ด / 2) = 81.216
C[S],J[S],i,j,k,y,c,X,Y,Z;char*R,a,b[9];main(x){R=mmap(0,S,6,34,-1,0);N=85;while(scanf("%c%s%*[ R]%d%*[ R]%d",&a,b,&x,&y)&&~getchar())a-=65,a-1?a-15?a-9?a?a-2?a-3?a-11?a-12?a-17?(N=41,v):(N=137,v):(N=137,u,N=247,g(H,4),N=139,u):(y?N=189+x,s(y):(N=51,g(G,G))):(N=137,u,N=247,g(H,6),N=139,u):(N=57,v,s(0xFC8A9F),--j):(N=1,v):(N=233,J[k++]=i,s(x)):b[1]-80?N=85+x:(N=93+x):(c=b[5],s(0x0F9EE78A),N=(c-69?c-71?c-76?1:8:11:0)+132,J[k++]=i,s(x)),C[++i]=j;U(E8,X)U(F0,Y)U(F8,Z)s(50013);i=j;while(k--)j=C[J[k]]+1,R[j-1]-233&&(j+=4),s(C[*(int*)(R+j)]-j-4);((int(*)())R)();printf("%u %u %u\n",X,Y,Z);}
์ฝ๋๋ฅผ ์ทจํฉ๋๋ค (LOAD R0
๋ฑ), ํํ ๋ฌธ์, ๋จ์ผ ๊ณต๋ฐฑ, ์ค๊ฐ์ ๋น ์ค, ์ฃผ์ ์์ ๋ฑ์ ํฉ๋๋ค. ํํ ์ค ๋ฐ๊ฟ์ด ํ์ํฉ๋๋ค.
๊ทธ๋ฐ ๋ค์ 80386 ๋ฐ์ดํธ ์ฝ๋๋ก ๋ณํ๋์ด ์คํ๋ฉ๋๋ค.
๋ก๋ 0
๋ ์ง์คํฐ์ ์ํด ๊ต์ฒด xor
์์ฒด ๋ ์ง์คํฐ๋ฅผ ๋ณด๋ด๊ณ ๋์ mov
๋ณด๋ด๊ณ 0
์์ฑ ๋ฐ์ดํธ์์ 3 ๋ฐ์ดํธ ์งง๋ค ๋ ์ง์คํฐ๋ก, ๋งค์ฐ ๊ทผ์ํ๊ฒ ๋ ๋น ๋ฅผ ์์๋ค.
๋ค์๊ณผ ๊ฐ์ด ์ปดํ์ผํ์ญ์์ค.
gcc -m32 -D"g(a,b)=(N=192|b<<3|a)"-D"s(b)=(*(int*)(R+j)=b,j+=4)"-DN=R[j++]-D"G=((x+1)|4)"
-D"H=((y+1)|4)"-DS=9999-D"u=g(0,G)"-D"v=g(G,H)"-D"U(b,c)=s(0xA3##b##89),--j,s(&c);"
bytecode.c -o bytecode
POSIX ํธํ OS๊ฐ ํ์ํฉ๋๋ค.
STDIN์์ ์
๋ ฅ์ ์ฝ์ต๋๋ค (์ฌ์ฉ ./bytecode < file
ํ์ผ์์ ํ์ดํ๋ก ).
ํ ์คํธ ํ๋ก๊ทธ๋จ์ ๊ฒฐ๊ณผ ๋ฐ์ดํธ ์ฝ๋ :
; start
0: 55 push %ebp
; LOAD R0 0
1: 33 ed xor %ebp,%ebp
; LOAD R2 0
3: 33 ff xor %edi,%edi
; LOAD R1 0
5: 33 f6 xor %esi,%esi
; PUSH $1
7: 56 push %esi
; MUL R1 R2
8: 89 f0 mov %esi,%eax
a: f7 e7 mul %edi
c: 8b f0 mov %eax,%esi
; PUSH R2
e: 57 push %edi
; LOAD R2 3
f: bf 03 00 00 00 mov $0x3,%edi
; DIV R1 R2
14: 89 f0 mov %esi,%eax
16: f7 f7 div %edi
18: 8b f0 mov %eax,%esi
; POP R2
1a: 5f pop %edi
; ADD R0 R1
1b: 01 f5 add %esi,%ebp
; POP R1
1d: 5e pop %esi
; PUSH R2
1e: 57 push %edi
; LOAD R2 1
1f: bf 01 00 00 00 mov $0x1,%edi
; ADD R1 R2
24: 01 fe add %edi,%esi
; POP R2
26: 5f pop %edi
; PUSH R2
27: 57 push %edi
; LOAD R2 10000
28: bf 10 27 00 00 mov $0x2710,%ed
; CMP R1 R2
2d: 39 fe cmp %edi,%esi
2f: 9f lahf
30: 8a fc mov %ah,%bh
; POP R2
32: 5f pop %edi
; BRANCHLT 3
33: 8a e7 mov %bh,%ah
35: 9e sahf
36: 0f 8c cb ff ff ff jl 0x7
; LOAD R1 1
3c: be 01 00 00 00 mov $0x1,%esi
; ADD R2 R1
41: 01 f7 add %esi,%edi
; LOAD R1 10000
43: be 10 27 00 00 mov $0x2710,%es
; CMP R2 R1
48: 39 f7 cmp %esi,%edi
4a: 9f lahf
4b: 8a fc mov %ah,%bh
; LOAD R1 0
4d: 33 f6 xor %esi,%esi
; BRANCHLT 2
4f: 8a e7 mov %bh,%ah
51: 9e sahf
52: 0f 8c ad ff ff ff jl 0x5
; copy R0 to X
58: 89 e8 mov %ebp,%eax
5a: a3 28 5b 42 00 mov %eax,0x425b
; copy R1 to Y
5f: 89 f0 mov %esi,%eax
61: a3 38 55 44 00 mov %eax,0x4455
; copy R2 to Z
66: 89 f8 mov %edi,%eax
68: a3 40 55 44 00 mov %eax,0x4455
; exit
6d: 5d pop %ebp
6e: c3 ret
์ธ ๊ณจํ ๋ :
C[9999],J[9999],i,j,k,y,c,X,Y,Z;
char *R,a,b[9];
main(x){
// 6 is PROC_WRITE|PROC_EXEC
// 34 is MAP_ANON|MAP_PRIVATE
R=mmap(0,'~~',6,34,-1,0);
N=0x55;
while(scanf("%c%s%*[ R]%d%*[ R]%d",&a,b,&x,&y)&&~getchar())
a-=65,
a-1? // B[RANCH**]
a-15? // P[USH/OP]
a-9? // J[MP]
a? // A[DD]
a-2? // C[MP]
a-3? // D[IV]
a-11? // L[OAD]
a-12? // M[UL]
a-17? // R[LOAD]
// SUB
(N=0x29,g(G,H))
:(N=0x89,g(G,H))
:(N=0x89,g(0,G),N=0xF7,g(H,4),N=0x8B,g(0,G))
:(y?N=0xBD+x,s(y):(N=0x33,g(G,G)))
:(N=0x89,g(0,G),N=0xF7,g(H,6),N=0x8B,g(0,G))
:(N=0x39,g(G,H),s(0xfc8a9f),--j)
:(N=0x1,g(G,H))
:(N=0xE9,J[k++]=i,s(x))
:b[1]-80?
N=0x55+x // PUSH
:(N=0x5D+x) // POP
:(c=b[5],s(0x0f9ee78a),N=(
c-69? // EQ
c-71? // GT
c-76? // LT
1 // NE
:8
:11
:0
)+0x84,J[k++]=i,s(x)),
C[++i]=j
;
// transfer registers to X,Y,Z
s(0xA3E889),--j,s(&X);
s(0xA3F089),--j,s(&Y);
s(0xA3F889),--j,s(&Z);
// pop and ret
s(0xC35D);
i=j;
// fix distances for jmp/branch**
while(k--)
j=C[J[k]]+1,R[j-1]-0xE9&&(j+=4),
s(C[*(int*)(R+j)]-j-4);
// call
((int(*)())R)();
// output
printf("%u %u %u\n",X,Y,Z);
}
๋ต๋ณ
C, ์ ์ = 854 ๋ฐ์ดํธ ร (~ 0.8 ์ด / 2) ร 0.5 [JIT] ร 0.9 [ํ์ฅ] = ~ 154 ๋ฐ์ดํธ ์ด
#define G getchar()
#define L for(i=0;i<3;++i)
#define N*(int*)
#define M(x)"P\x8a\xe7\x9e\xf"#x" KL"
*T[1<<20],**t=T,*F[1<<20],**f=F,R[3],r[]={1,6,7};char*I[]={"L\xb8 GGJH","I\x8b\xc0HHGH","H\x50GG","H\x58GG","I\3\xc0HHGH","I\53\xc0HHGH","M\x8b\xc0\xf7\xe0\x8b\xc0IHLGJ","O\63\xd2\x8b\xc0\xf7\xf0\x8b\xc0IJNGL","L\xe9 KH","L\73\xc0\x9f\x8a\xfcHHGH",M(\x82),M(\x84),M(\x87),M(\x85)},C[1<<24],*c=C;main(i,o,l,g){N c=0xb7ec8b60;c[4]=70;c+=5;while((o=G)>=0){char*s=I[o];l=*s-'G';memcpy(c,s+1,l);for(s+=l+1;o=*s++;){o-='G';if(o<3){g=r[G];c[*s++-'G']|=g<<3*(o&1);if(o>1)c[*s++-'G']|=g<<3;}else{if(o>3)*f++=c+*s-'G';for(i=4;i;--i)c[*s-'G'+i-1]=G;++s;}}*t++=c;c+=l;}*t=c;while(f>F)--f,**f=(int)T[**f]-(int)*f-4;L N&c[7*i]=0x5893e|r[i]<<19,N&c[3+7*i]=R+i;N&c[21]=0xc361e58b;mprotect((int)C>>12<<12,1<<24,7);((void(*)())C)();L printf("R%d %u\n",i,R[i]);}
gcc vm.c -ovm -m32 -w
x86 POSIX ํธํ OS์์ ์ปดํ์ผํ์ญ์์ค .
์ ์คํ ./vm < program
, ์ด๋ program
๋ฐ์ด๋๋ฆฌ ํ๋ก๊ทธ๋จ ํ์ผ์
๋๋ค.
์๋๋ฅผ ๊ฐ๋ค. ์ด ํ๋ก๊ทธ๋จ์ ์ ๋ ฅ ํ๋ก๊ทธ๋จ์ x86 ๋จธ์ ์ฝ๋๋ก ๋งค์ฐ ๊ฐ๋จํ๊ฒ ๋ณํํ์ฌ CPU๊ฐ ๋๋จธ์ง ์์ ์ ์ํํ๋๋กํฉ๋๋ค.
์๋ฅผ ๋ค์ด, ๋ค์์ ํ
์คํธ ํ๋ก๊ทธ๋จ์ ๋ฒ์ญ์
๋๋ค.
ecx
, esi
๋ฐ edi
์ ํด๋นR0
, R1
๋ฐ R2
๊ฐ๊ฐ์ ; bh
์ํ ํ๋๊ทธ๋ฅผ ๋ณด์ ํฉ๋๋ค. eax
๋ฐ edx
์คํฌ๋์น ๋ ์ง์คํฐ์ด๊ณ ; ์ฝ ์คํ์ VM์ ์คํ์ ํด๋นํฉ๋๋ค.
# Prologue
0: 60 pusha
1: 8b ec mov ebp,esp
3: b7 46 mov bh,0x46
# LOAD R0 0
5: b9 00 00 00 00 mov ecx,0x0
# LOAD R2 0 <--outer loop value
a: bf 00 00 00 00 mov edi,0x0
# LOAD R1 0 <--inner loop value
f: be 00 00 00 00 mov esi,0x0
# --Begin inner loop--
# PUSH R1 <--push inner loop value to the stack
14: 56 push esi
# MUL R1 R2 <--(i*j)
15: 8b c6 mov eax,esi
15: f7 e7 mul edi
19: 8b f0 mov esi,eax
# PUSH R2
1b: 57 push edi
# LOAD R2 3
1c: bf 03 00 00 00 mov edi,0x3
# DIV R1 R2 <-- / 3
21: 33 d2 xor edx,edx
23: 8b c6 mov eax,esi
25: f7 f7 div edi
27: 8b f0 mov esi,eax
# POP R2
29: 5f pop edi
# ADD R0 R1 <-- s+=
2a: 03 ce add ecx,esi
# POP R1
2c: 5e pop esi
# PUSH R2
2d: 57 push edi
# LOAD R2 1
2e: bf 01 00 00 00 mov edi,0x1
# ADD R1 R2 <--j++
33: 03 f7 add esi,edi
# POP R2
35: 5f pop edi
# PUSH R2
36: 57 push edi
# LOAD R2 10000
37: bf 10 27 00 00 mov edi,0x2710
# CMP R1 R2 <-- j < 10000
3c: 3b f7 cmp esi,edi
3e: 9f lahf
3f: 8a fc mov bh,ah
# POP R2
41: 5f pop edi
# BRANCHLT 4 <--Go back to beginning inner loop
42: 8a e7 mov ah,bh
44: 9e sahf
45: 0f 82 c9 ff ff ff jb 0x14
# --Drop To outer loop--
# LOAD R1 1
4b: be 01 00 00 00 mov esi,0x1
# ADD R2 R1 <--i++
50: 03 fe add edi,esi
# LOAD R1 10000
52: be 10 27 00 00 mov esi,0x2710
# CMP R2 R1 <-- i < 10000
57: 3b fe cmp edi,esi
59: 9f lahf
5a: 8a fc mov bh,ah
# LOAD R1 0 <--Reset inner loop
5c: be 00 00 00 00 mov esi,0x0
# BRANCHLT 3
61: 8a e7 mov ah,bh
63: 9e sahf
64: 0f 82 a5 ff ff ff jb 0xf
# Epilogue
6a: 3e 89 0d 60 ac 04 09 mov DWORD PTR ds:0x904ac60,ecx
71: 3e 89 35 64 ac 04 09 mov DWORD PTR ds:0x904ac64,esi
78: 3e 89 3d 68 ac 04 09 mov DWORD PTR ds:0x904ac68,edi
7f: 8b e5 mov esp,ebp
81: 61 popa
82: c3 ret
์ธ ๊ณจํ
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/mman.h>
#define MAX_INST_COUNT (1 << 20)
#define MAX_CODE_SIZE (8 * MAX_INST_COUNT)
#define PAGE_SIZE (1 << 12)
uintptr_t *targets[MAX_INST_COUNT], **targets_ptr = targets;
int32_t *fixups[MAX_INST_COUNT], **fixups_ptr = fixups;
char code[MAX_CODE_SIZE], *code_ptr = code;
uint32_t R[3];
const char* inst_defs[] = {
/* LOAD */ "\5\xb8 \1\0\4\1",
/* RLOAD */ "\2\x8b\xc0\2\1\1\1",
/* PUSH */ "\1\x50\1\0",
/* POP */ "\1\x58\1\0",
/* ADD */ "\2\x03\xc0\2\1\1\1",
/* SUB */ "\2\x2b\xc0\2\1\1\1",
/* MUL */ "\6\x8b\xc0\xf7\xe0\x8b\xc0\3\1\5\1\3",
/* DIV */ "\x8\x33\xd2\x8b\xc0\xf7\xf0\x8b\xc0\3\3\7\1\5",
/* JMP */ "\5\xe9 \5\1",
/* CMP */ "\5\x3b\xc0\x9f\x8a\xfc\2\1\1\1",
/* BRANCHLT */ "\x9\x8a\xe7\x9e\x0f\x82 \5\5",
/* BRANCHEQ */ "\x9\x8a\xe7\x9e\x0f\x84 \5\5",
/* BRANCHGT */ "\x9\x8a\xe7\x9e\x0f\x87 \5\5",
/* BRANCHNE */ "\x9\x8a\xe7\x9e\x0f\x85 \5\5"
};
int main() {
int i;
{
const char prologue[] =
/* PUSHAD */ "\x60"
/* MOV EBP, ESP */ "\x8b\xec"
/* MOV BH, 46h */ "\xb7\x46"
;
memcpy(code_ptr, prologue, sizeof(prologue) - 1);
code_ptr += sizeof(prologue) - 1;
}
{
const char reg[] = {1, 6, 7};
char r;
int op;
while ((op = getchar()) != EOF) {
const char* def = inst_defs[op];
int len = def[0];
memcpy(code_ptr, def + 1, len);
for (def += len + 1; *def; ) {
switch (*def++) {
case 1: code_ptr[*def++] |= reg[getchar()]; break;
case 2: code_ptr[*def++] |= reg[getchar()] << 3; break;
case 3:
r = reg[getchar()];
code_ptr[*def++] |= r; code_ptr[*def++] |= r << 3;
break;
case 5: *fixups_ptr = code_ptr + *def; ++fixups_ptr;
case 4:
for (i = 4; i; --i) code_ptr[*def + i - 1] = getchar();
++def;
break;
}
}
*targets_ptr = code_ptr; ++targets_ptr;
code_ptr += len;
}
*targets_ptr = code_ptr; ++targets_ptr;
while (fixups_ptr != fixups) {
--fixups_ptr;
**fixups_ptr = (char*)targets[**fixups_ptr] - (char*)*fixups_ptr - 4;
}
}
{
const char epilogue[] =
/* MOV R[0], ECX */ "\x3e\x89\x0d "
/* MOV R[1], ESI */ "\x3e\x89\x35 "
/* MOV R[2], EDI */ "\x3e\x89\x3d "
/* MOV ESP, EBP */ "\x8b\xe5"
/* POPAD */ "\x61"
/* RET */ "\xc3"
;
memcpy(code_ptr, epilogue, sizeof(epilogue) - 1);
for (i = 0; i < 3; ++i) *(uintptr_t*)&code_ptr[3 + 7 * i] = &R[i];
code_ptr += sizeof(epilogue) - 1;
}
mprotect(
(uintptr_t)code / PAGE_SIZE * PAGE_SIZE, MAX_CODE_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC
);
{ void (*program)(void) = code; program(); }
for (i = 0; i < 3; ++i) printf("R%d %u\n", i, R[i]);
return 0;
}
๋ต๋ณ
CJam, 222 (187) 185 ๋ฐ์ดํธ (* ๋๋ฌด ๋๋ ค / 2)
CJam์์ ๋ฐ์ดํธ ์ฝ๋ VM์ ์์ฑํ์ฌ ์ผ๋ง๋ ์งง์ ์ง ์๊ณ ์ถ์์ต๋๋ค. 200 ๋ฐ์ดํธ ๋ฏธ๋ง์ ๊ฝค ๊ด์ฐฎ์ ๊ฒ ๊ฐ์ต๋๋ค. CJam ์์ฒด๊ฐ ํด์๋๊ธฐ ๋๋ฌธ์ ์๋๊ฐ ๋๋ฆฝ๋๋ค. ํ ์คํธ ํ๋ก๊ทธ๋จ์ ์คํํ๋ ๋ฐ ์ค๋ ์๊ฐ์ด ๊ฑธ๋ฆฝ๋๋ค.
304402480 6b:P;q:iD-);{(_P=@/(\L*@@+\}h;]:P;TTT]:R;{_Rf=~}:Q;{4G#%R@0=@t:R;}:O;{TP=("R\(\GG*bt:R; ~R= R\~@t:R; Q+O Q4G#+-O Q*O Q/O ~(:T; Rf=~-:U; GG*bU0<{(:T}*;"S/=~T):TP,<}g3,{'R\_S\R=N}/
๊ทธ๊ฒ์ ์คํํ๋ ค๋ฉด ์ด sourceforge ๋งํฌ ์์ Java ์ธํฐํ๋ฆฌํฐ๋ฅผ ๋ค์ด๋ก๋ ํ๊ณ ์ฝ๋๋ฅผ ์ ์ฅํ๊ณ ๋ค์์ผ๋ก vm.cjam
์คํํ์ญ์์ค.
java -jar cjam-0.6.2.jar vm.cjam
ํ๋ก๊ทธ๋จ์ STDIN์ ๋ฐ์ดํธ ์ฝ๋๋ฅผ ์์ํฉ๋๋ค. PowerShell์์ ํํ ์ค ๋ฐ๊ฟ์ ์ถ๊ฐํ๊ณ ๋ณํํ์ง ์๊ณ ๋ฐ์ด๋๋ฆฌ ๋ฐ์ดํฐ๋ฅผ ํ๋ก๊ทธ๋จ์ ํ์ดํํ๋ ๋ฐฉ๋ฒ์ ์์ง ์ฐพ์ง ๋ชปํ์ต๋๋ค.0x0a
์ 0x0d 0x0a
์ ๋ง ์ง์ฆ๋์ด๋ค. ์ฝ๋์๋ 4 ๋ฐ์ดํธ๊ฐ ํฌํจ๋์ด ์์ต๋๋ค.D-);
ํฌํจ๋์ง ์์ ํฌํจ๋์ด ์์ต๋๋ค. . ๋๊ตฐ๊ฐ๊ฐ ๊ทธ์ ๋ํ ํด๊ฒฐ์ฑ
์ ์๊ณ ์๋ค๋ฉด ์๋ ค์ฃผ์ญ์์ค.
์ฝ๊ฐ ๊ณจํผ๋์ง ์์ :
304402480 6b:P; "Create lookup table for instruction sizes. Store in P.";
q:i "Read program and convert bytes to integers.";
D-); "Remove spurious carriage returns. This shouldn't be necessary.";
{(_P=@/(\L*@@+\}h;]:P; "Split into instructions. Store in P.";
"We'll use T for the instruction pointer as it's initialised to 0.";
"Likewise, we'll use U for the CMP flag.";
TTT]:R; "Store [0 0 0] in R for the registers.";
{_Rf=~}:Q; "Register lookup block.";
{4G#%R@0=@t:R;}:O; "Save in register block.";
{TP=("R\(\GG*bt:R;
~R=
R\~@t:R;
Q+O
Q4G#+-O
Q*O
Q/O
~(:T;
Rf=~-:U;
GG*bU0<{(:T}*;"N/=~T):TP,<}g "Run program.";
3,{'R\_S\R=N}/
๋ด์ผ ์ ์ ํ ์ค๋ช ์ ์ถ๊ฐํ๊ฒ ์ต๋๋ค.
์ฆ, ๋ชจ๋ ๋ ์ง์คํฐ, ๋ช ๋ น์ด ํฌ์ธํฐ ๋ฐ ๋น๊ต ํ๋๊ทธ๋ฅผ ๋ณ์์ ์ ์ฅํ์ฌ CJam์ ์คํ์ VM์ ์คํ์ผ๋ก ์์ ๋กญ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ต๋ณ
ํ์ด์ฌ / C ++, ์ ์ = 56.66
1435 ์ * .234 / 2 ์ด * .5 [JIT] * .75 [์ต์ ํ] * .90 [์ถ๊ฐ ์ง์นจ]
์ ๋ ฅ ํ๋ก๊ทธ๋จ์ c ++๋ก ์ปดํ์ผํ๊ณ gcc๋ฅผ ์คํ ํ ๋ค์ ๊ฒฐ๊ณผ๋ฅผ ์คํํฉ๋๋ค. ๋๋ถ๋ถ์ ์๊ฐ์ gcc ๋ด๋ถ์์ ์๋น๋ฉ๋๋ค.
๋ด๊ฐํ๋ ํ ๊ฐ์ง ์ต์ ํ๋ ์คํ ์ฐ์ฐ์ด ์๋ฏธ ์ ์ผ๋ก ํ์ฉ๋๋ ๊ฒฝ์ฐ ๋ช ์ ์ ๋ณ์๋ก ์ค์ด๋ ๊ฒ์ ๋๋ค. ์ปดํ์ผ ๋ ์ฝ๋์ ๋ฐํ์๋ณด๋ค ์ฝ 10 ๋ฐฐ ๋ ๋์ ๋ฐํ์์ ์ ๊ณตํฉ๋๋ค (์ค์ ๋ก ๊ฒฐ๊ณผ ๋ฐ์ด๋๋ฆฌ๋ฅผ ์คํํ๋ ๋ฐ ์ฝ .056 ์ด). ๋๋ gcc๊ฐ ๋ฌด์์ํ๊ณ ์๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ง๋ง ๊ทธ ๊ฐ์ ์ ์ป๋๋ค.
import sys,os
x=map(ord,sys.stdin.read())
w=lambda x:(x[0]<<24)+(x[1]<<16)+(x[2]<<8)+x[3]
I=[]
while x:
if x[0]==0:f='r%d=%d'%(x[1],w(x[2:]));n=6
if x[0]==1:f='r%d=r%d'%(x[1],x[2]);n=3
if x[0]==2:f='P%d'%x[1];n=2
if x[0]==3:f='O%d'%x[1];n=2
if x[0]==4:f='r%d=r%d+r%d'%(x[1],x[1],x[2]);n=3
if x[0]==5:f='r%d=r%d-r%d'%(x[1],x[1],x[2]);n=3
if x[0]==6:f='r%d=r%d*r%d'%(x[1],x[1],x[2]);n=3
if x[0]==7:f='r%d=r%d/r%d'%(x[1],x[1],x[2]);n=3
if x[0]==8:f='goto L%d'%w(x[1:]);n=5
if x[0]==9:f='a=r%d;b=r%d'%(x[1],x[2]);n=3
if x[0]==10:f='if(a<b)goto L%d'%w(x[1:]);n=5
if x[0]==11:f='if(a==b)goto L%d'%w(x[1:]);n=5
if x[0]==12:f='if(a>b)goto L%d'%w(x[1:]);n=5
if x[0]==13:f='if(a!=b)goto L%d'%w(x[1:]);n=5
I+=[f];x=x[n:]
D=[]
d=0
for f in I:D+=[d];d+='P'==f[0];d-='O'==f[0]
J=[]
if all(d==D[int(f[f.find('L')+1:])]for f,d in zip(I,D)if f[0]in'gi'):
H='uint32_t '+','.join('s%d'%i for i in range(max(D)))+';'
for f,d in zip(I,D):
if f[0]=='P':f='s%d=r'%d+f[1:]
if f[0]=='O':f='r'+f[1:]+'=s%d'%(d-1)
J+=[f]
else:
H='std::vector<uint32_t>s;'
for f,d in zip(I,D):
if f[0]=='P':f='s.push_back(r'+f[1:]+')'
if f[0]=='O':f='r'+f[1:]+'=s.back();s.pop_back()'
J+=[f]
P='#include<vector>\n#include<cstdint>\nuint32_t r0,r1,r2,a,b;'+H+'int main(){'
for i,f in enumerate(J):P+='L%d:'%i+f+';'
P+=r'printf("R0 %u\nR1 %u\nR2 %u\n",r0,r1,r2);}'
c=open("t.cc", "w")
c.write(P)
c.close()
os.system("g++ -O1 t.cc")
os.system("./a.out")
ํ์คํ ๋ ๋ง์ ๊ณจํ๋ฅผ ์ณค๋ค.
๋ต๋ณ
Lua 5.2 (๋๋ LuaJIT), 740 ๋ฐ์ดํธ
๋จผ์ ์ต์ํ์ ๊ณจํ ๋ง ์๋ํ์ญ์์ค. ์ด ๋ฒ์ ์ (์ ์ด๋ ํ ์คํธ ํ๋ก๊ทธ๋จ์์) ์๋ํ๋ฉฐ ์ถ๊ฐ opcode๋ฅผ ๊ตฌํํ์ง๋ง ์๋ช ๋์ง ์์ ์ํ ์๊ตฌ ์ฌํญ์์ง์งํ์ง ์์ผ๋ฉฐ ํนํ ๋น ๋ฅด์ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ณด๋์ค๋ก VM์์ VM์ด ์คํ ์ค์ด๋ฉฐ ํด์ (PUC-Lua๋ก ์คํ) ๋๋ JIT ์ ๋ ฌ (LuaJIT์ผ๋ก ์คํ; ์ฌ์ ํ ํด์๋์ง๋ง ์ธํฐํ๋ฆฌํฐ๋ ํ์ฌ ํด์ ๊ฐ๋ฅํ๋๋ก ์์ฑ๋์์ต๋๋ค) ์ ํฉ).
ํธ์ง : ๋ ํฐ ๊ณจํ ์ฌ์ ํ ๊ณจํ.
ํธ์ง : ์ฃผ์ ์ค๋ฅ๊ฐ ์์ ๋์์ผ๋ฉฐ ์ด์ ์ฐ์ ์ unsigned long
๋ฒ์๋ก ์ ํ ํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ป๊ฒ ๋ ํฌ๊ธฐ๋ฅผ ๋ฒ์ด๋์ง ๋ชปํ์ง๋ง ์ฌ์ ํ ์๋ชป๋ ๋๋ต์ํ๊ณ ์์ต๋๋ค.
ํธ์ง : ๊ฒฐ๊ณผ๋ ์ ํํ์ง๋ง ์ถ๋ ฅ์ ์ฌ๋ฐ๋ฅด์ง ์์ต๋๋ค. %u
๋์ ์ธ์๋ก ์ ํํ๋ฉด %d
๋ชจ๋ ์ ์์
๋๋ค. ๋ํ ํฌ๊ธฐ ์ ์๋๋ฅผ ๋ค์ ํฅ์์ํค๊ธฐ ์ํด ๋ณ์์ ๋ํ ํ
์ด๋ธ ๊ธฐ๋ฐ ๋ ์ง์คํฐ๋ฅผ ์ ํํ์ต๋๋ค .
ํธ์ง : Lua 5.2์ goto
๋ฌธ (LuaJIT์์๋ ์ฌ์ฉ ๊ฐ๋ฅ)์ ์ฌ์ฉํ์ฌ ์ธํฐํ๋ฆฌํฐ๋ฅผ โJIT-to-Luaโ๋ก ๊ต์ฒดํ์ฌ Lua VM ์์ฒด์์ ์ง์ ์คํํ๋ ์ฝ๋๋ฅผ ์์ฑํ์ต๋๋ค. ์ด๊ฒ์ด ์ค์ ๋ก JIT๋ก ๊ณ์ฐ๋๋์ง ํ์คํ์ง ์์ง๋ง ์๋๊ฐ ํฅ์๋ฉ๋๋ค.
U,S,P,F=table.unpack,table.insert,table.remove,math.floor X,r0,r1,r2,p,m,s=2^32,0,0,0,1,0,{}C={{'r%u=%u',1,4},{'r%u=r%u',1,1},{'S(s,r%u)',1},{'r%u=P(s)',1},{'r%u=(r%u+r%u)%%X',1,0,1},{'r%u=(r%u-r%u)%%X',1,0,1},{'r%u=(r%u*r%u)%%X',1,0,1},{'r%u=F(r%u/r%u)%%X',1,0,1},{'goto L%u',4},{'m=r%u-r%u',1,1},{'if m<0 then goto L%u end',4},{'if m==0 then goto L%u end',4},{'if m>0 then goto L%u end',4},{'if m~=0 then goto L%u end',4}}t={io.open(arg[1],'rb'):read('*a'):byte(1,-1)}i,n,r=1,0,{}while i<=#t do c,i,x,a=C[t[i]+1],i+1,0,{}for j=2,#c do y=c[j]if y>0 then x=0 for k=1,y do i,x=i+1,x*256+t[i]end end S(a,x)end S(r,('::L%d::'):format(n))n=n+1 S(r,c[1]:format(U(a)))end load(table.concat(r,' '))()print(('R0 %u\nR1 %u\nR2 %u'):format(r0,r1,r2))
์๋ณธ์ ์ฝ์ ์์๋ ๋ฒ์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
U,S,P,F=table.unpack,table.insert,table.remove,math.floor
X,r0,r1,r2,p,m,s=2^32,0,0,0,1,0,{}
C={
{'r%u=%u',1,4},
{'r%u=r%u',1,1},
{'S(s,r%u)',1},
{'r%u=P(s)',1},
{'r%u=(r%u+r%u)%%X',1,0,1},
{'r%u=(r%u-r%u)%%X',1,0,1},
{'r%u=(r%u*r%u)%%X',1,0,1},
{'r%u=F(r%u/r%u)%%X',1,0,1},
{'goto L%u',4},
{'m=r%u-r%u',1,1},
{'if m<0 then goto L%u end',4},
{'if m==0 then goto L%u end',4},
{'if m>0 then goto L%u end',4},
{'if m~=0 then goto L%u end',4},
}
t={io.open(arg[1],'rb'):read('*a'):byte(1,-1)}
i,n,r=1,0,{}
while i<=#t do
c,i,x,a=C[t[i]+1],i+1,0,{}
for j=2,#c do
y=c[j]
if y>0 then
x=0
for k=1,y do
i,x=i+1,x*256+t[i]
end
end
S(a,x)
end
S(r,('::L%d::'):format(n))
n=n+1
S(r,c[1]:format(U(a)))
end
load(table.concat(r,' '))()
print(('R0 %u\nR1 %u\nR2 %u'):format(r0,r1,r2))
๋ต๋ณ
์จ#
1505 1475 ๋ฐ์ดํธ
์ด๊ฒ์ C #์ผ๋ก ์์ฑ๋ ์ธํฐํ๋ฆฌํฐ์ ๋ด ๋ฒ์ ์ผ๋ก, ๋ ๋ง์ ๊ฒ์ ์๊ฐํ๊ณ ์ต์ ํ ํ ์ ์์ง๋ง ์ค์ ๋ก๋ ์ด๋์ ์๋์ง ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.)
๊ณจํ ๋ฒ์ :
using System;using System.Collections.Generic;using System.IO;using System.Linq;class M{static void Main(string[]a){if(a.Length==1&&File.Exists(a[0])){B.E(B.P(File.ReadAllLines(a[0])));Console.WriteLine(B.O);}}}class B{public enum I{L=0x00,P=0x02,Q=0x03,A=0x04,S=0x05,M=0x06,D=0x07,J=0x08,C=0x09,BL=0x0a,BE=0x0b,BG=0x0c,BN=0x0d}public enum R{A,B,C}enum C{N,L,E,G}public static Dictionary<R,uint>r=new Dictionary<R,uint>{{R.A,0},{R.B,0},{R.C,0}};public static Stack<uint>s=new Stack<uint>();static C c=C.N;public static string O{get{return string.Format("R0 {0}\nR1 {1}\nR2 {2}",r[R.A],r[R.B],r[R.C]);}}public static void E(byte[][]l){for(uint i=0;i<l.Length;i++){var q=l[i];switch((I)q[0]){case I.L:r[(R)q[1]]=U(q,2);break;case I.P:r[(R)q[1]]=s.Pop();break;case I.Q:s.Push(r[(R)q[1]]);r[(R)q[1]]=0;break;case I.A:s.Push(r[(R)q[1]]+r[(R)q[2]]);break;case I.S:s.Push(r[(R)q[1]]-r[(R)q[2]]);break;case I.M:s.Push(r[(R)q[1]]*r[(R)q[2]]);break;case I.D:s.Push(r[(R)q[1]]/r[(R)q[2]]);break;case I.J:i=U(q,1)-1;break;case I.C:{uint x=r[(R)q[1]],y=r[(R)q[2]];c=x<y?C.L:x>y?C.G:C.E;}break;case I.BL:if(c==C.L)i=U(q,1)-1;break;case I.BG:if(c==C.G)i=U(q,1)-1;break;case I.BE:if(c==C.E)i=U(q,1)-1;break;case I.BN:if(c!=C.E)i=U(q,1)-1;break;}}}public static byte[][]P(string[]c){return c.Where(l=>!l.StartsWith("#")).Select(r=>r.Split(' ').Where(b=>b.Length>0).Select(b=>Convert.ToByte(b,16)).ToArray()).Where(l=>l.Length>0).ToArray();}static uint U(byte[]b,int i){return(uint)(b[i]<<24|b[i+1]<<16|b[i+2]<<8|b[i+3]);}}
ํธ์งํ๋ค
๋ถํ์ public
ํ๊ณ private
์์ ์๋ฅผ ์ ๊ฑฐํ์ต๋๋ค .
using System;using System.Collections.Generic;using System.IO;using System.Linq;class M{static void Main(string[]a){if(a.Length==1&&File.Exists(a[0])){B.E(B.P(File.ReadAllLines(a[0])));Console.Write(B.O);}}}class B{enum I{L=0x00,P=0x02,Q=0x03,A=0x04,S=0x05,M=0x06,D=0x07,J=0x08,C=0x09,BL=0x0a,BE=0x0b,BG=0x0c,BN=0x0d}enum R{A,B,C}enum C{N,L,E,G}static Dictionary<R,uint>r=new Dictionary<R,uint>{{R.A,0},{R.B,0},{R.C,0}};static Stack<uint>s=new Stack<uint>();static C c=C.N;public static string O{get{return string.Format("R0 {0}\nR1 {1}\nR2 {2}\n",r[R.A],r[R.B],r[R.C]);}}public static void E(byte[][]l){for(uint i=0;i<l.Length;i++){var q=l[i];switch((I)q[0]){case I.L:r[(R)q[1]]=U(q,2);break;case I.P:r[(R)q[1]]=s.Pop();break;case I.Q:s.Push(r[(R)q[1]]);r[(R)q[1]]=0;break;case I.A:s.Push(r[(R)q[1]]+r[(R)q[2]]);break;case I.S:s.Push(r[(R)q[1]]-r[(R)q[2]]);break;case I.M:s.Push(r[(R)q[1]]*r[(R)q[2]]);break;case I.D:s.Push(r[(R)q[1]]/r[(R)q[2]]);break;case I.J:i=U(q,1)-1;break;case I.C:{uint x=r[(R)q[1]],y=r[(R)q[2]];c=x<y?C.L:x>y?C.G:C.E;}break;case I.BL:if(c==C.L)i=U(q,1)-1;break;case I.BG:if(c==C.G)i=U(q,1)-1;break;case I.BE:if(c==C.E)i=U(q,1)-1;break;case I.BN:if(c!=C.E)i=U(q,1)-1;break;}}}public static byte[][]P(string[]c){return c.Where(l=>!l.StartsWith("#")).Select(r=>r.Split(' ').Where(b=>b.Length>0).Select(b=>Convert.ToByte(b,16)).ToArray()).Where(l=>l.Length>0).ToArray();}static uint U(byte[]b,int i){return(uint)(b[i]<<24|b[i+1]<<16|b[i+2]<<8|b[i+3]);}}
executable.exe filename
์ด๋์๋ ๋ถ๋ฌfilename
ํด์ ํ ์ฝ๋๊ฐ ๋ค์ด์๋ ํ์ผ์ด์๋
๋ด โํ ์คํธ ํ๋ก๊ทธ๋จโ:
# LOAD R0 5
# CMP R0 R1
# BRANCHEQ 13
# LOAD R1 1
# LOAD R2 1
# CMP R0 R2
# MUL R1 R2
# LOAD R1 1
# ADD R2 R1
# PUSH R2
# PUSH R1
# BRANCHEQ 13
# JMP 5
# POP R2
# POP R0
# POP R1
# PUSH R0
0x0 0x0 0x0 0x0 0x0 0x5
0x9 0x0 0x1
0xb 0x0 0x0 0x0 0xd
0x0 0x1 0x0 0x0 0x0 0x1
0x0 0x2 0x0 0x0 0x0 0x1
0x9 0x0 0x2
0x6 0x1 0x2
0x0 0x1 0x0 0x0 0x0 0x1
0x4 0x2 0x1
0x2 0x2
0x2 0x1
0xb 0x0 0x0 0x0 0xd
0x8 0x0 0x0 0x0 0x5
0x3 0x2
0x3 0x0
0x3 0x1
0x2 0x0
๋ ๊ธด ์ด๋ฆ์ ๋ณ์, ํด๋์ค๋ก ํด์๋์ง ์์ ํด์๊ธฐ โฆ
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Program
{
static void Main(string[] args)
{
if (args.Length == 1 && File.Exists(args[0]))
{
var code = ByteCodeInterpreter.ParseCode(File.ReadAllLines(args[0]));
ByteCodeInterpreter.Execute(code);
Console.WriteLine(ByteCodeInterpreter.Output);
}
}
}
public static class ByteCodeInterpreter
{
public enum Instruction : byte
{
LOAD = 0x00,
PUSH = 0x02,
POP = 0x03,
ADD = 0x04,
SUB = 0x05,
MUL = 0x06,
DIV = 0x07,
JMP = 0x08,
CMP = 0x09,
BRANCHLT = 0x0a,
BRANCHEQ = 0x0b,
BRANCHGT = 0x0c,
BRANCHNE = 0x0d
}
public enum Register : byte
{
R0 = 0x00,
R1 = 0x01,
R2 = 0x02
}
private enum CompareFlag : byte
{
NONE = 0x00,
LT = 0x01,
EQ = 0x02,
GT = 0x03,
}
public static readonly Dictionary<Register, uint> register = new Dictionary<Register, uint>
{
{Register.R0, 0},
{Register.R1, 0},
{Register.R2, 0}
};
public static readonly Stack<uint> stack = new Stack<uint>();
private static CompareFlag compareFlag = CompareFlag.NONE;
public static string Output
{
get
{
return string.Format("R0 {0}\nR1 {1}\nR2 {2}", register[Register.R0], register[Register.R1],
register[Register.R2]);
}
}
public static void Execute(byte[][] lines)
{
for (uint i = 0; i < lines.Length; i++)
{
var line = lines[i];
switch ((Instruction)line[0])
{
case Instruction.LOAD:
register[(Register)line[1]] = GetUint(line, 2);
break;
case Instruction.PUSH:
register[(Register)line[1]] = stack.Pop();
break;
case Instruction.POP:
stack.Push(register[(Register)line[1]]);
register[(Register)line[1]] = 0;
break;
case Instruction.ADD:
stack.Push(register[(Register)line[1]] + register[(Register)line[2]]);
break;
case Instruction.SUB:
stack.Push(register[(Register)line[1]] - register[(Register)line[2]]);
break;
case Instruction.MUL:
stack.Push(register[(Register)line[1]] * register[(Register)line[2]]);
break;
case Instruction.DIV:
stack.Push(register[(Register)line[1]] / register[(Register)line[2]]);
break;
case Instruction.JMP:
i = GetUint(line, 1) - 1;
break;
case Instruction.CMP:
{
uint v0 = register[(Register)line[1]], v1 = register[(Register)line[2]];
if (v0 < v1)
compareFlag = CompareFlag.LT;
else if (v0 > v1)
compareFlag = CompareFlag.GT;
else
compareFlag = CompareFlag.EQ;
}
break;
case Instruction.BRANCHLT:
if (compareFlag == CompareFlag.LT)
i = GetUint(line, 1) - 1;
break;
case Instruction.BRANCHGT:
if (compareFlag == CompareFlag.GT)
i = GetUint(line, 1) - 1;
break;
case Instruction.BRANCHEQ:
if (compareFlag == CompareFlag.EQ)
i = GetUint(line, 1) - 1;
break;
case Instruction.BRANCHNE:
if (compareFlag != CompareFlag.EQ)
i = GetUint(line, 1) - 1;
break;
}
}
}
public static byte[][] ParseCode(string[] code)
{
return
code.Where(line => !line.StartsWith("#"))
.Select(line => line.Split(' ').Where(b => b.Length > 0).Select(b => Convert.ToByte(b, 16)).ToArray())
.Where(line => line.Length > 0)
.ToArray();
}
private static uint GetUint(byte[] bytes, int index)
{
return (uint)(bytes[index] << 24 | bytes[index + 1] << 16 | bytes[index + 2] << 8 | bytes[index + 3]);
}
}