fork download
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string>
  4. #include <vector>
  5. #include <map>
  6. #include <sstream>
  7. #include <fstream>
  8. namespace VM{
  9. enum OpCode{
  10. NOP,
  11. PRINT_CCHAR,
  12. PRINT_CBYTE,
  13. PRINT_CHAR,
  14. PRINT_INT,
  15. JMP,
  16. JEQ,
  17. SET_BYTE,
  18. SET_INT,
  19. INC,
  20. ADD,
  21. MOV
  22. };
  23. class VirtualMachine{
  24. public:
  25. void load(const std::string &program){
  26. m_program = program;
  27. m_programCounter = 0;
  28. }
  29.  
  30. unsigned char fetch(){
  31. return m_program[m_programCounter++];
  32. }
  33.  
  34. int fetchInt(){
  35. int i = fetch();
  36. i = i *256 + fetch();
  37. i = i *256 + fetch();
  38. return i * 256 + fetch();
  39. }
  40.  
  41. void step(){
  42. OpCode op = (OpCode)fetch();
  43. switch(op){
  44. case NOP:
  45. break;
  46. case PRINT_CCHAR:
  47. printf("%c",fetch());
  48. break;
  49. case PRINT_CHAR:
  50. printf("%c",(char) m_memory[fetch()]);
  51. break;
  52. case PRINT_CBYTE:
  53. printf("%d",(int)fetch());
  54. break;
  55. case PRINT_INT:
  56. printf("%d",m_memory[fetch()]);
  57. break;
  58. case JMP:
  59. m_programCounter = fetchInt();
  60. break;
  61. case JEQ:
  62. {
  63. int a = m_memory[fetch()];
  64. int b = m_memory[fetch()];
  65. unsigned char target = fetchInt();
  66. if(a == b){
  67. m_programCounter = target;
  68. }
  69. break;
  70. }
  71. case SET_BYTE:
  72. {
  73. unsigned char addr = fetch();
  74. m_memory[addr] = fetch();
  75. break;
  76. }
  77. case SET_INT:
  78. {
  79. unsigned char addr = fetch();
  80. m_memory[addr] = fetchInt();
  81. break;
  82. }
  83. case INC:
  84. m_memory[fetch()]++;
  85. break;
  86. case ADD:
  87. {
  88. unsigned char addr1 = fetch();
  89. unsigned char addr2 = fetch();
  90. m_memory[addr1] += m_memory[addr2];
  91. break;
  92. }
  93. case MOV:
  94. {
  95. unsigned char addr1 = fetch();
  96. unsigned char addr2 = fetch();
  97. m_memory[addr1] = m_memory[addr2];
  98. break;
  99. }
  100. }
  101.  
  102.  
  103. }
  104.  
  105. void run(){
  106. while(m_programCounter < m_program.size()){
  107. step();
  108. }
  109. }
  110. private:
  111. std::string m_program;
  112. size_t m_programCounter;
  113. int m_memory[256];
  114. };
  115.  
  116. class Assembler{
  117. public:
  118. void assemble(const std::string &source){
  119. m_bytecode = "";
  120. m_pos = 0;
  121. m_labels.clear();
  122. m_labelRefs.clear();
  123.  
  124. std::vector<std::string> lines = tokenize(source,"\n");
  125. for(std::vector<std::string>::iterator it = lines.begin();it!=lines.end();it++){
  126. const std::string &line = *it;
  127.  
  128. std::vector<std::string> tokens = tokenize(line," \t");
  129.  
  130. const std::string &op = tokens[0];
  131.  
  132. if(op[0] == '#'){
  133. m_labels[op] = m_pos;
  134. }
  135.  
  136. if(op == "NOP"){
  137. pushChar(NOP);
  138. }else if(op == "PRINT_CCHAR"){
  139. pushChar(PRINT_CCHAR);
  140. pushChar(toInt(tokens[1]));
  141. }else if(op == "PRINT_CBYTE"){
  142. pushChar(PRINT_CBYTE);
  143. pushChar(toInt(tokens[1]));
  144. }else if(op == "PRINT_CHAR"){
  145. pushChar(PRINT_CHAR);
  146. pushChar(toInt(tokens[1]));
  147. }else if(op == "PRINT_INT"){
  148. pushChar(PRINT_INT);
  149. pushChar(toInt(tokens[1]));
  150. }else if(op == "JMP"){
  151. pushChar(JMP);
  152. pushLabel(tokens[1]);
  153. }else if(op == "JEQ"){
  154. pushChar(JEQ);
  155. pushChar(toInt(tokens[1]));
  156. pushChar(toInt(tokens[2]));
  157. pushLabel(tokens[3]);
  158. }else if(op == "SET_BYTE"){
  159. pushChar(SET_BYTE);
  160. pushChar(toInt(tokens[1]));
  161. pushChar(toInt(tokens[2]));
  162. }else if(op == "SET_INT"){
  163. pushChar(SET_INT);
  164. pushChar(toInt(tokens[1]));
  165. pushInt(toInt(tokens[2]));
  166. }else if(op == "INC"){
  167. pushChar(INC);
  168. pushChar(toInt(tokens[1]));
  169. }else if(op == "ADD"){
  170. pushChar(ADD);
  171. pushChar(toInt(tokens[1]));
  172. pushChar(toInt(tokens[2]));
  173. }else if(op == "MOV"){
  174. pushChar(MOV);
  175. pushChar(toInt(tokens[1]));
  176. pushChar(toInt(tokens[2]));
  177. }
  178.  
  179. }
  180.  
  181. for(std::vector<LabelReference>::iterator it = m_labelRefs.begin();it!=m_labelRefs.end();it++){
  182. const LabelReference &ref = *it;
  183. std::map<std::string,int>::iterator label = m_labels.find(ref.name);
  184. if(label == m_labels.end()){
  185. printf("error: label %s not found.\n",ref.name.c_str());
  186. }else{
  187. int i = (*label).second;
  188.  
  189. m_bytecode[ref.position] = (i & 0xff000000) >> 24;
  190. m_bytecode[ref.position+1] = (i & 0x00ff0000) >> 16;
  191. m_bytecode[ref.position+2] = (i & 0x0000ff00) >> 8;
  192. m_bytecode[ref.position+3] = (i & 0x000000ff) >> 0;
  193. }
  194. }
  195.  
  196. }
  197.  
  198. const std::string &getBytecode() const{
  199. return m_bytecode;
  200. }
  201. private:
  202.  
  203. std::string m_bytecode;
  204. size_t m_pos;
  205. std::map<std::string,int> m_labels;
  206.  
  207. struct LabelReference{
  208. std::string name;
  209. int position;
  210. };
  211. std::vector<LabelReference> m_labelRefs;
  212.  
  213. void pushChar(char c){
  214. m_bytecode.push_back(c);
  215. m_pos++;
  216. }
  217.  
  218. void pushLabel(const std::string &str){
  219. if(str[0] == '#'){
  220. LabelReference ref;
  221. ref.name = str;
  222. ref.position = m_pos;
  223. m_labelRefs.push_back(ref);
  224. pushInt(0x1a);
  225. }else{
  226. pushInt(toInt(str));
  227. }
  228. }
  229.  
  230. void pushInt(int i){
  231. m_bytecode.push_back((i & 0xff000000) >> 24);
  232. m_bytecode.push_back((i & 0x00ff0000) >> 16);
  233. m_bytecode.push_back((i & 0x0000ff00) >> 8);
  234. m_bytecode.push_back((i & 0x000000ff) >> 0);
  235. m_pos+= 4;
  236. }
  237.  
  238. int toInt(const std::string &str){
  239. int i;
  240.  
  241. const char *fmt = "%d";
  242. if(str[0] == '0'){
  243. if(str[1] == 'x' || str[1] == 'X'){
  244. fmt = "%x";
  245. }else{
  246. fmt = "%o";
  247. }
  248. }
  249.  
  250. sscanf(str.c_str(),fmt,&i);
  251. return i;
  252. }
  253.  
  254. std::vector<std::string> tokenize(const std::string &str, const char * delimiters){
  255. std::vector<std::string> rst;
  256. std::string::size_type lastPos = 0;
  257. std::string::size_type pos = str.find_first_of(delimiters,0);
  258.  
  259. while(pos != std::string::npos){
  260. if(pos-lastPos){
  261. rst.push_back(str.substr(lastPos,pos - lastPos));
  262. }
  263. lastPos = pos + 1;
  264. pos = str.find_first_of(delimiters,lastPos);
  265. }
  266. rst.push_back(str.substr(lastPos));
  267. return rst;
  268. }
  269. };
  270. }
  271.  
  272. int main(int argc, const char* argv[])
  273. {
  274. using namespace VM;
  275. VirtualMachine vm;
  276. Assembler a;
  277.  
  278. /*std::ifstream t(argv[1]);
  279. std::stringstream buffer;
  280. buffer << t.rdbuf();*/
  281.  
  282. a.assemble(
  283. "SET_BYTE 0 1 \n"
  284. "SET_BYTE 1 10 \n"
  285. "#FOR_I\n"
  286. "JEQ 0 1 #FOR_I_END\n"
  287. "SET_BYTE 2 1 \n"
  288. "SET_BYTE 3 10\n"
  289. "SET_BYTE 4 0\n"
  290. "#FOR_J\n"
  291. "JEQ 2 3 #FOR_J_END\n"
  292. "ADD 4 0\n"
  293. "PRINT_INT 0\n"
  294. "PRINT_CCHAR 0x20\n"
  295. "PRINT_CCHAR 0x2a\n"
  296. "PRINT_CCHAR 0x20\n"
  297. "PRINT_INT 2\n"
  298. "PRINT_CCHAR 0x20\n"
  299. "PRINT_CCHAR 0x3d\n"
  300. "PRINT_CCHAR 0x20\n"
  301. "PRINT_INT 4\n"
  302. "PRINT_CCHAR 0x0a\n"
  303. "INC 2\n"
  304. "JMP #FOR_J\n"
  305. "#FOR_J_END\n"
  306. "INC 0\n"
  307. "JMP #FOR_I\n"
  308. "#FOR_I_END"
  309. );
  310. vm.load(a.getBytecode());
  311. vm.run();
  312. system("pause");
  313. return 0;
  314. }
  315.  
  316.  
Success #stdin #stdout 0.01s 5312KB
stdin
Standard input is empty
stdout
1 * 1 = 1
1 * 2 = 2
1 * 3 = 3
1 * 4 = 4
1 * 5 = 5
1 * 6 = 6
1 * 7 = 7
1 * 8 = 8
1 * 9 = 9
2 * 1 = 2
2 * 2 = 4
2 * 3 = 6
2 * 4 = 8
2 * 5 = 10
2 * 6 = 12
2 * 7 = 14
2 * 8 = 16
2 * 9 = 18
3 * 1 = 3
3 * 2 = 6
3 * 3 = 9
3 * 4 = 12
3 * 5 = 15
3 * 6 = 18
3 * 7 = 21
3 * 8 = 24
3 * 9 = 27
4 * 1 = 4
4 * 2 = 8
4 * 3 = 12
4 * 4 = 16
4 * 5 = 20
4 * 6 = 24
4 * 7 = 28
4 * 8 = 32
4 * 9 = 36
5 * 1 = 5
5 * 2 = 10
5 * 3 = 15
5 * 4 = 20
5 * 5 = 25
5 * 6 = 30
5 * 7 = 35
5 * 8 = 40
5 * 9 = 45
6 * 1 = 6
6 * 2 = 12
6 * 3 = 18
6 * 4 = 24
6 * 5 = 30
6 * 6 = 36
6 * 7 = 42
6 * 8 = 48
6 * 9 = 54
7 * 1 = 7
7 * 2 = 14
7 * 3 = 21
7 * 4 = 28
7 * 5 = 35
7 * 6 = 42
7 * 7 = 49
7 * 8 = 56
7 * 9 = 63
8 * 1 = 8
8 * 2 = 16
8 * 3 = 24
8 * 4 = 32
8 * 5 = 40
8 * 6 = 48
8 * 7 = 56
8 * 8 = 64
8 * 9 = 72
9 * 1 = 9
9 * 2 = 18
9 * 3 = 27
9 * 4 = 36
9 * 5 = 45
9 * 6 = 54
9 * 7 = 63
9 * 8 = 72
9 * 9 = 81