ilasmでstack machine その19

# 概要
ilasmでstack machineやってみた。
練習問題やってみた。

# 練習問題
ilasmが動く、インタープリタを書け。
fizzbuzzを動作させよ。

# 方針
- Plunker、使う。

- 命令セット

|ニーモニック		|意味							|stackの状態
|:--|:--|:--|
|nop					|何もしない。				|	変化無し
|ldc.i4 1			|stackに整数 1を積む。			|1個増える
|ldstr "fizzbuzz"	|stackに「fizzbuzz」を積む。		|1個増える
|ldloc i				|stackに変数iの値を積む。		|1個増える
|stloc i				|変数iにstackを移動。			|1個減る
|call void [mscorlib] System.Console::WriteLine(int32)	|stackを数値印刷。	|1個減る
|call void [mscorlib] System.Console::WriteLine(string)	|stackを文字印刷。	|1個減る
|callvirt instance int32 [mscorlib]System.Random::Next(int32)| 乱数を積む  |1個減る
|beq bye				|セカンドとトップを比べて等しいならbyeに飛ぶ。	|2個減る
|bgt bye				|セカンドとトップを比べて小さいならbyeに飛ぶ。	|2個減る
|blt bye				|セカンドとトップを比べて大きいならbyeに飛ぶ。	|2個減る
|br tugi				|tugiへ飛ぶ。					|変化無し
|brfalse fizzbuzz	|ゼロで無いならfizzbuzzに飛ぶ。	|1個減る
|brtrue fizzbuzz		|ゼロならfizzbuzzに飛ぶ。		|1個減る
|dup					|stackにコピーを積む。			|1個増える
|drop				|stackを一個減らす。				|1個減る
|add					|セカンドとトップの加算を求める。	|1個減る
|sub					|セカンドとトップの減算を求める。	|1個減る
|mul					|セカンドとトップの乗算を求める。	|1個減る
|div					|セカンドとトップの除算を求める。	|1個減る
|rem					|セカンドとトップの剰余を求める。	|1個減る

# サンプルコード


```

var out = document.getElementById("out");
var src = document.getElementById("src"); 

function run() {
  var str = src.value;
  str = str.replace(/\t/g, " ");
  str = str.replace(/  /g, " ");
  str = str.replace(/  /g, " ");
  str = str.replace(/  /g, " ");
  var codes = str.split("\n");  
  var pc = 0;  
  var sp = 0;
  var len = codes.length;
  var i;
  var label = {};
  var val = {};
  var ram = [];
  var res = "";
  for (i = 0; i < len; i++)
  {
    if (codes[i].indexOf(":") > -1) 
    {
      label[codes[i]] = i;
    }
  }
  while (i > 0)
  {
    //alert(pc);
    var code = codes[pc].split(" ");
    switch (code[1])
    {
    case "drop":
      sp--;
      pc++;
    break;
    case "dup":
      ram[sp] = ram[sp - 1];
      sp++;
      pc++;
    break;
    case "ldstr":
      ram[sp] = code[2];
      sp++;
      pc++;
    break;
    case "ldc.i4":
      ram[sp] = code[2];
      sp++;
      pc++;
    break;
    case "stloc":  
      sp--;
      val[code[2]] = ram[sp];
      pc++;
    break;
    case "ldloc":
      ram[sp] = val[code[2]];
      sp++;  
      pc++;
    break; 
    case "call":
      sp--;
      res += ram[sp] + "\n";
      pc++;
    break;
    case "brtrue": 
      sp--;
      if (ram[sp] == 1)
      {
        pc = label[code[2] + ":"];
      }
      else
      {
        pc++;
      }
    break;
    case "brfalse": 
      sp--;
      if (ram[sp] == 0)
      {
        pc = label[code[2] + ":"];
      }
      else
      {
        pc++;
      }
    break;
    case "bgt":  
      sp--;
      if (parseInt(ram[sp - 1]) > parseInt(ram[sp]))
      {
        sp--;
        pc = label[code[2] + ":"];
      }
      else
      {
        sp--;
        pc++;
      }
    break;
    case "add":  
      sp--;
      ram[sp - 1] = parseInt(ram[sp - 1]) + parseInt(ram[sp]);
      pc++;
    break;
    case "mul":  
      sp--;
      ram[sp - 1] = parseInt(ram[sp - 1]) * parseInt(ram[sp]);
      pc++;
    break;
    case "sub":  
      sp--;
      ram[sp - 1] = parseInt(ram[sp - 1]) - parseInt(ram[sp]);
      pc++;
    break;
    case "div":  
      sp--;
      ram[sp - 1] = parseInt(ram[sp - 1]) / parseInt(ram[sp]);
      pc++;
    break;
    case "rem":  
      sp--;
      ram[sp - 1] = parseInt(ram[sp - 1]) % parseInt(ram[sp]);
      pc++;
    break;
    case "br": 
      pc = label[code[2] + ":"];
    break;
    case "ret":  
      i = 0;
    break;
    case undefined:
      pc++;
    break;
    default:
      alert(code[1]);
      pc++;
    break;
    }
  }
  //alert("ok");
  out.value = res;
}




```

# 投入したソース

fizzbuzz

```
    ldc.i4 100
    stloc n
    ldc.i4 1
    stloc i
loop:
    ldloc i
    ldloc n
    bgt bye
    ldloc i
    ldc.i4 15
    rem
    brfalse fb
    ldloc i
    ldc.i4 5
    rem
    brfalse b
    ldloc i
    ldc.i4 3
    rem
    brfalse f
    ldloc i
    call void [mscorlib] System.Console::WriteLine(int32)
    br tugi
fb:
    ldstr "fizzbuzz"
    br print
b:
    ldstr "buzz"
    br print
f:
    ldstr "fizz"
print:
    call void [mscorlib] System.Console::WriteLine(string)
tugi:
    ldloc i
    ldc.i4 1
    add
    stloc i
    br loop
bye:
    ret

```

# 実行結果

```
1
2
"fizz"
4
"buzz"
"fizz"
7
8
"fizz"
"buzz"
11
"fizz"
13
14
"fizzbuzz"
16
17
"fizz"
19
"buzz"
"fizz"
22
23
"fizz"
"buzz"
26
"fizz"
28
29
"fizzbuzz"
31
32
"fizz"
34
"buzz"
"fizz"
37
38
"fizz"
"buzz"
41
"fizz"
43
44
"fizzbuzz"
46
47
"fizz"
49
"buzz"
"fizz"
52
53
"fizz"
"buzz"
56
"fizz"
58
59
"fizzbuzz"
61
62
"fizz"
64
"buzz"
"fizz"
67
68
"fizz"
"buzz"
71
"fizz"
73
74
"fizzbuzz"
76
77
"fizz"
79
"buzz"
"fizz"
82
83
"fizz"
"buzz"
86
"fizz"
88
89
"fizzbuzz"
91
92
"fizz"
94
"buzz"
"fizz"
97
98
"fizz"
"buzz"

```

# 成果物

https://embed.plnkr.co/plunk/wgdy3IHxNUfayPeW

以上