RVMxI.ob07 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. (*
  2. BSD 2-Clause License
  3. Copyright (c) 2020-2021, Anton Krotov
  4. All rights reserved.
  5. *)
  6. (*
  7. RVMxI executor and disassembler
  8. Usage:
  9. RVMxI.exe <program file> -run [program parameters]
  10. RVMxI.exe <program file> -dis <output file>
  11. *)
  12. MODULE RVMxI;
  13. IMPORT SYSTEM, File, Args, Out, API, HOST;
  14. CONST
  15. szWORD = HOST.bit_depth DIV 8;
  16. opSTOP = 0; opRET = 1; opENTER = 2; opNEG = 3; opNOT = 4; opNOP = 5;
  17. opXCHG = 6; opLDB = 7; opLDH = 8; opLDW = 9; opPUSH = 10; opPUSHC = 11;
  18. opPOP = 12; opLABEL = 13; opLEA = 14; opLLA = 15;
  19. opLDD = 16; (* 17, 18 *)
  20. opJMP = 19; opCALL = 20; opCALLI = 21;
  21. opMOV = 22; opMUL = 24; opADD = 26; opSUB = 28; opDIV = 30; opMOD = 32;
  22. opSTB = 34; opSTH = 36; opSTW = 38; opSTD = 40; (* 42, 44 *)
  23. opAND = 46; opOR = 48; opXOR = 50; opASR = 52; opLSR = 54;
  24. opLSL = 56; opROR = 58; (* 60, 62 *) opCMP = 64;
  25. opMOVC = 23; opMULC = 25; opADDC = 27; opSUBC = 29; opDIVC = 31; opMODC = 33;
  26. opSTBC = 35; opSTHC = 37; opSTWC = 39; opSTDC = 41; (* 43, 45 *)
  27. opANDC = 47; opORC = 49; opXORC = 51; opASRC = 53; opLSRC = 55;
  28. opLSLC = 57; opRORC = 59; (* 61, 63 *) opCMPC = 65;
  29. opBIT = 66; opSYSCALL = 67; opJBT = 68; opADDRC = 69;
  30. opJEQ = 70; opJNE = 71; opJLT = 72; opJGE = 73; opJGT = 74; opJLE = 75;
  31. opSEQ = 76; opSNE = 77; opSLT = 78; opSGE = 79; opSGT = 80; opSLE = 81;
  32. nREG = 16;
  33. ACC = 0; BP = 3; SP = 4;
  34. Types = 0;
  35. Strings = 1;
  36. Global = 2;
  37. Heap = 3;
  38. Stack = 4;
  39. TYPE
  40. COMMAND = POINTER TO RECORD
  41. op, param1, param2: INTEGER;
  42. next, prev: COMMAND
  43. END;
  44. LABELS = ARRAY 30000 OF COMMAND;
  45. SECTIONS = ARRAY 5 OF INTEGER;
  46. VAR
  47. Sections: SECTIONS;
  48. first, last: COMMAND;
  49. Labels: LABELS;
  50. F: INTEGER; buf: ARRAY 65536 OF BYTE; cnt: INTEGER;
  51. PROCEDURE syscall (ptr: INTEGER);
  52. VAR
  53. fn, r, n: INTEGER;
  54. proc2: PROCEDURE (a, b: INTEGER): INTEGER;
  55. proc3: PROCEDURE (a, b, c: INTEGER): INTEGER;
  56. proc4: PROCEDURE (a, b, c, d: INTEGER): INTEGER;
  57. r1, r2: REAL;
  58. PROCEDURE GetInt (ptr, n: INTEGER): INTEGER;
  59. BEGIN
  60. SYSTEM.GET(ptr + SYSTEM.SIZE(INTEGER) * n, n)
  61. RETURN n
  62. END GetInt;
  63. PROCEDURE GetReal (ptr, n: INTEGER): REAL;
  64. VAR
  65. r: REAL;
  66. BEGIN
  67. SYSTEM.GET(ptr + SYSTEM.SIZE(INTEGER) * n, r)
  68. RETURN r
  69. END GetReal;
  70. BEGIN
  71. fn := GetInt(ptr, 0);
  72. CASE fn OF
  73. | 0:
  74. HOST.ExitProcess(GetInt(ptr, 1))
  75. | 1:
  76. SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.GetCurrentDirectory));
  77. r := proc2(GetInt(ptr, 1), GetInt(ptr, 2))
  78. | 2:
  79. n := GetInt(ptr, 1);
  80. SYSTEM.PUT(SYSTEM.ADR(proc3), SYSTEM.ADR(HOST.GetArg));
  81. r := proc3(n - ORD(n = 0) + 2, GetInt(ptr, 2), GetInt(ptr, 3))
  82. | 3:
  83. SYSTEM.PUT(SYSTEM.ADR(proc4), SYSTEM.ADR(HOST.FileRead));
  84. SYSTEM.PUT(ptr, proc4(GetInt(ptr, 1), GetInt(ptr, 2), GetInt(ptr, 3), GetInt(ptr, 4)))
  85. | 4:
  86. SYSTEM.PUT(SYSTEM.ADR(proc4), SYSTEM.ADR(HOST.FileWrite));
  87. SYSTEM.PUT(ptr, proc4(GetInt(ptr, 1), GetInt(ptr, 2), GetInt(ptr, 3), GetInt(ptr, 4)))
  88. | 5:
  89. SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.FileCreate));
  90. SYSTEM.PUT(ptr, proc2(GetInt(ptr, 1), GetInt(ptr, 2)))
  91. | 6:
  92. HOST.FileClose(GetInt(ptr, 1))
  93. | 7:
  94. SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.FileOpen));
  95. SYSTEM.PUT(ptr, proc2(GetInt(ptr, 1), GetInt(ptr, 2)))
  96. | 8:
  97. HOST.OutChar(CHR(GetInt(ptr, 1)))
  98. | 9:
  99. SYSTEM.PUT(ptr, HOST.GetTickCount())
  100. |10:
  101. SYSTEM.PUT(ptr, HOST.UnixTime())
  102. |11:
  103. SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.isRelative));
  104. SYSTEM.PUT(ptr, proc2(GetInt(ptr, 1), GetInt(ptr, 2)))
  105. |12:
  106. SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.chmod));
  107. r := proc2(GetInt(ptr, 1), GetInt(ptr, 2))
  108. |100..103:
  109. r1 := GetReal(ptr, 1);
  110. r2 := GetReal(ptr, 2);
  111. CASE fn OF
  112. |100: SYSTEM.PUT(ptr, r2 * r1)
  113. |101: SYSTEM.PUT(ptr, r2 / r1)
  114. |102: SYSTEM.PUT(ptr, r2 + r1)
  115. |103: SYSTEM.PUT(ptr, r2 - r1)
  116. END
  117. |104:
  118. r1 := GetReal(ptr, 2);
  119. r2 := GetReal(ptr, 3);
  120. CASE GetInt(ptr, 1) OF
  121. |0: SYSTEM.PUT(ptr, ORD(r2 = r1))
  122. |1: SYSTEM.PUT(ptr, ORD(r2 # r1))
  123. |2: SYSTEM.PUT(ptr, ORD(r2 < r1))
  124. |3: SYSTEM.PUT(ptr, ORD(r2 <= r1))
  125. |4: SYSTEM.PUT(ptr, ORD(r2 > r1))
  126. |5: SYSTEM.PUT(ptr, ORD(r2 >= r1))
  127. END
  128. |105:
  129. SYSTEM.PUT(ptr, FLOOR(GetReal(ptr, 1)))
  130. |106:
  131. SYSTEM.PUT(ptr, FLT(GetInt(ptr, 1)))
  132. END
  133. END syscall;
  134. PROCEDURE exec (VAR Labels: LABELS; first, last: COMMAND; Sections: SECTIONS);
  135. VAR
  136. cmd: COMMAND;
  137. param1, param2, i: INTEGER;
  138. R: ARRAY nREG OF INTEGER;
  139. fe, fl, fb: BOOLEAN;
  140. BEGIN
  141. FOR i := 0 TO LEN(Labels) - 1 DO
  142. cmd := Labels[i];
  143. IF cmd # NIL THEN
  144. REPEAT
  145. cmd := cmd.next
  146. UNTIL cmd.op # opLABEL;
  147. Labels[i] := cmd
  148. END
  149. END;
  150. cmd := first;
  151. WHILE cmd # NIL DO
  152. IF cmd.op = opLABEL THEN
  153. cmd.prev.next := cmd.next;
  154. cmd.next.prev := cmd.prev
  155. END;
  156. cmd := cmd.next
  157. END;
  158. FOR i := 0 TO LEN(Labels) - 1 DO
  159. IF Labels[i] # NIL THEN
  160. Labels[i] := Labels[i].prev
  161. END
  162. END;
  163. cmd := first;
  164. WHILE cmd # NIL DO
  165. param1 := cmd.param1;
  166. param2 := cmd.param2;
  167. CASE cmd.op OF
  168. |opSTOP: cmd := last
  169. |opRET: SYSTEM.GET(R[SP], cmd); INC(R[SP], szWORD)
  170. |opENTER: DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], R[BP]); R[BP] := R[SP];
  171. WHILE param1 > 0 DO DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], 0); DEC(param1) END
  172. |opPOP: SYSTEM.GET(R[SP], R[param1]); INC(R[SP], szWORD)
  173. |opPUSH: DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], R[param1])
  174. |opPUSHC: DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], param1)
  175. |opCALL: DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], cmd); cmd := Labels[param1]
  176. |opCALLI: DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], cmd); SYSTEM.GET(SYSTEM.ADR(R[param1]), cmd)
  177. |opNEG: R[param1] := -R[param1]
  178. |opNOT: R[param1] := ORD(-BITS(R[param1]))
  179. |opNOP:
  180. |opXCHG: i := R[param1]; R[param1] := R[param2]; R[param2] := i
  181. |opLDB: i := param1 MOD 256; SYSTEM.GET8(R[param1 DIV 256] + param2, R[i]); R[i] := R[i] MOD 256
  182. |opLDH: i := param1 MOD 256; SYSTEM.GET16(R[param1 DIV 256] + param2, R[i]); R[i] := R[i] MOD 65536
  183. |opLDW: SYSTEM.GET32(R[param1 DIV 256] + param2, R[param1 MOD 256]);
  184. $IF (CPU_X8664)
  185. R[param1 MOD 256] := R[param1 MOD 256] MOD 100000000H
  186. $END
  187. |opLDD: SYSTEM.GET(R[param1 DIV 256] + param2, R[param1 MOD 256])
  188. |opLLA: SYSTEM.GET(SYSTEM.ADR(Labels[param2]), R[param1])
  189. |opJMP: cmd := Labels[param1]
  190. |opMOV: R[param1] := R[param2]
  191. |opMOVC: R[param1] := param2
  192. |opMUL: R[param1] := R[param1] * R[param2]
  193. |opMULC: R[param1] := R[param1] * param2
  194. |opADD: INC(R[param1], R[param2])
  195. |opADDC: INC(R[param1], param2)
  196. |opSUB: DEC(R[param1], R[param2])
  197. |opSUBC: DEC(R[param1], param2)
  198. |opDIV: R[param1] := R[param1] DIV R[param2]
  199. |opDIVC: R[param1] := R[param1] DIV param2
  200. |opMOD: R[param1] := R[param1] MOD R[param2]
  201. |opMODC: R[param1] := R[param1] MOD param2
  202. |opSTB: SYSTEM.PUT8(R[param1 DIV 256] + param2, R[param1 MOD 256])
  203. |opSTH: SYSTEM.PUT16(R[param1 DIV 256] + param2, R[param1 MOD 256])
  204. |opSTW: SYSTEM.PUT32(R[param1 DIV 256] + param2, R[param1 MOD 256])
  205. |opSTD: SYSTEM.PUT(R[param1 DIV 256] + param2, R[param1 MOD 256])
  206. |opSTBC: SYSTEM.PUT8(R[param1], param2)
  207. |opSTHC: SYSTEM.PUT16(R[param1], param2)
  208. |opSTWC: SYSTEM.PUT32(R[param1], param2)
  209. |opSTDC: SYSTEM.PUT(R[param1], param2)
  210. |opAND: R[param1] := ORD(BITS(R[param1]) * BITS(R[param2]))
  211. |opANDC: R[param1] := ORD(BITS(R[param1]) * BITS(param2))
  212. |opOR: R[param1] := ORD(BITS(R[param1]) + BITS(R[param2]))
  213. |opORC: R[param1] := ORD(BITS(R[param1]) + BITS(param2))
  214. |opXOR: R[param1] := ORD(BITS(R[param1]) / BITS(R[param2]))
  215. |opXORC: R[param1] := ORD(BITS(R[param1]) / BITS(param2))
  216. |opASR: R[param1] := ASR(R[param1], R[param2])
  217. |opASRC: R[param1] := ASR(R[param1], param2)
  218. |opLSR: R[param1] := LSR(R[param1], R[param2])
  219. |opLSRC: R[param1] := LSR(R[param1], param2)
  220. |opLSL: R[param1] := LSL(R[param1], R[param2])
  221. |opLSLC: R[param1] := LSL(R[param1], param2)
  222. |opROR: R[param1] := ROR(R[param1], R[param2])
  223. |opRORC: R[param1] := ROR(R[param1], param2)
  224. |opLEA: R[param1 MOD 256] := Sections[param1 DIV 256] + param2
  225. (*|opLABEL:*)
  226. |opSYSCALL: syscall(R[param1])
  227. |opADDRC: R[param1 MOD 256] := R[param1 DIV 256] + param2
  228. |opCMP: fl := R[param1] < R[param2]; fe := R[param1] = R[param2]; fb := fl & (R[param1] >= 0)
  229. |opCMPC: fl := R[param1] < param2; fe := R[param1] = param2; fb := fl & (R[param1] >= 0)
  230. |opJEQ: IF fe THEN cmd := Labels[param1] END
  231. |opJNE: IF ~fe THEN cmd := Labels[param1] END
  232. |opJLT: IF fl THEN cmd := Labels[param1] END
  233. |opJLE: IF fl OR fe THEN cmd := Labels[param1] END
  234. |opJGT: IF ~fl & ~fe THEN cmd := Labels[param1] END
  235. |opJGE: IF ~fl THEN cmd := Labels[param1] END
  236. |opSEQ: R[param1] := ORD(fe)
  237. |opSNE: R[param1] := ORD(~fe)
  238. |opSLT: R[param1] := ORD(fl)
  239. |opSLE: R[param1] := ORD(fl OR fe)
  240. |opSGT: R[param1] := ORD(~fl & ~fe)
  241. |opSGE: R[param1] := ORD(~fl)
  242. |opJBT: IF fb THEN cmd := Labels[param1] END
  243. |opBIT: R[param1] := ORD({R[param2]})
  244. END;
  245. cmd := cmd.next
  246. END
  247. END exec;
  248. PROCEDURE disasm (name: ARRAY OF CHAR; t_count, c_count, glob, heap: INTEGER);
  249. VAR
  250. cmd: COMMAND;
  251. param1, param2, i, t, ptr: INTEGER;
  252. b: BYTE;
  253. Names: ARRAY 5, 16 OF CHAR;
  254. PROCEDURE String (s: ARRAY OF CHAR);
  255. VAR
  256. n: INTEGER;
  257. BEGIN
  258. n := LENGTH(s);
  259. IF n > LEN(buf) - cnt THEN
  260. ASSERT(File.Write(F, SYSTEM.ADR(buf[0]), cnt) = cnt);
  261. cnt := 0
  262. END;
  263. SYSTEM.MOVE(SYSTEM.ADR(s[0]), SYSTEM.ADR(buf[0]) + cnt, n);
  264. INC(cnt, n)
  265. END String;
  266. PROCEDURE Ln;
  267. BEGIN
  268. String(0DX + 0AX)
  269. END Ln;
  270. PROCEDURE hexdgt (n: INTEGER): CHAR;
  271. BEGIN
  272. IF n < 10 THEN
  273. INC(n, ORD("0"))
  274. ELSE
  275. INC(n, ORD("A") - 10)
  276. END
  277. RETURN CHR(n)
  278. END hexdgt;
  279. PROCEDURE Hex (x: INTEGER);
  280. VAR
  281. str: ARRAY 19 OF CHAR;
  282. n: INTEGER;
  283. BEGIN
  284. n := szWORD * 2 + 2;
  285. str[n] := 0X;
  286. WHILE n > 2 DO
  287. str[n - 1] := hexdgt(x MOD 16);
  288. x := x DIV 16;
  289. DEC(n)
  290. END;
  291. str[1] := "x";
  292. str[0] := "0";
  293. String(str)
  294. END Hex;
  295. PROCEDURE Byte (x: BYTE);
  296. VAR
  297. str: ARRAY 5 OF CHAR;
  298. BEGIN
  299. str[4] := 0X;
  300. str[3] := hexdgt(x MOD 16);
  301. str[2] := hexdgt(x DIV 16);
  302. str[1] := "x";
  303. str[0] := "0";
  304. String(str)
  305. END Byte;
  306. PROCEDURE Reg (n: INTEGER);
  307. VAR
  308. s: ARRAY 2 OF CHAR;
  309. BEGIN
  310. IF n = BP THEN
  311. String("BP")
  312. ELSIF n = SP THEN
  313. String("SP")
  314. ELSE
  315. String("R");
  316. s[1] := 0X;
  317. IF n >= 10 THEN
  318. s[0] := CHR(n DIV 10 + ORD("0"));
  319. String(s)
  320. END;
  321. s[0] := CHR(n MOD 10 + ORD("0"));
  322. String(s)
  323. END
  324. END Reg;
  325. PROCEDURE Reg2 (r1, r2: INTEGER);
  326. BEGIN
  327. Reg(r1); String(", "); Reg(r2)
  328. END Reg2;
  329. PROCEDURE RegC (r, c: INTEGER);
  330. BEGIN
  331. Reg(r); String(", "); Hex(c)
  332. END RegC;
  333. PROCEDURE RegL (r, label: INTEGER);
  334. BEGIN
  335. Reg(r); String(", L"); Hex(label)
  336. END RegL;
  337. BEGIN
  338. Names[Types] := "TYPES";
  339. Names[Strings] := "STRINGS";
  340. Names[Global] := "GLOBAL";
  341. Names[Heap] := "HEAP";
  342. Names[Stack] := "STACK";
  343. F := File.Create(name);
  344. ASSERT(F > 0);
  345. cnt := 0;
  346. String("CODE:"); Ln;
  347. cmd := first;
  348. WHILE cmd # NIL DO
  349. param1 := cmd.param1;
  350. param2 := cmd.param2;
  351. CASE cmd.op OF
  352. |opSTOP: String("STOP")
  353. |opRET: String("RET")
  354. |opENTER: String("ENTER "); Hex(param1)
  355. |opPOP: String("POP "); Reg(param1)
  356. |opNEG: String("NEG "); Reg(param1)
  357. |opNOT: String("NOT "); Reg(param1)
  358. |opNOP: String("NOP")
  359. |opXCHG: String("XCHG "); Reg2(param1, param2)
  360. |opLDB: String("LDB "); Reg(param1 MOD 256); String(", ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("]")
  361. |opLDH: String("LDH "); Reg(param1 MOD 256); String(", ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("]")
  362. |opLDW: String("LDW "); Reg(param1 MOD 256); String(", ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("]")
  363. |opLDD: String("LDD "); Reg(param1 MOD 256); String(", ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("]")
  364. |opPUSH: String("PUSH "); Reg(param1)
  365. |opPUSHC: String("PUSH "); Hex(param1)
  366. |opLLA: String("LLA "); RegL(param1, param2)
  367. |opJMP: String("JMP L"); Hex(param1)
  368. |opCALL: String("CALL L"); Hex(param1)
  369. |opCALLI: String("CALL "); Reg(param1)
  370. |opMOV: String("MOV "); Reg2(param1, param2)
  371. |opMOVC: String("MOV "); RegC(param1, param2)
  372. |opMUL: String("MUL "); Reg2(param1, param2)
  373. |opMULC: String("MUL "); RegC(param1, param2)
  374. |opADD: String("ADD "); Reg2(param1, param2)
  375. |opADDC: String("ADD "); RegC(param1, param2)
  376. |opSUB: String("SUB "); Reg2(param1, param2)
  377. |opSUBC: String("SUB "); RegC(param1, param2)
  378. |opDIV: String("DIV "); Reg2(param1, param2)
  379. |opDIVC: String("DIV "); RegC(param1, param2)
  380. |opMOD: String("MOD "); Reg2(param1, param2)
  381. |opMODC: String("MOD "); RegC(param1, param2)
  382. |opSTB: String("STB ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("], "); Reg(param1 MOD 256)
  383. |opSTH: String("STH ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("], "); Reg(param1 MOD 256)
  384. |opSTW: String("STW ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("], "); Reg(param1 MOD 256)
  385. |opSTD: String("STD ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("], "); Reg(param1 MOD 256)
  386. |opSTBC: String("STB ["); Reg(param1); String("], "); Hex(param2)
  387. |opSTHC: String("STH ["); Reg(param1); String("], "); Hex(param2)
  388. |opSTWC: String("STW ["); Reg(param1); String("], "); Hex(param2)
  389. |opSTDC: String("STD ["); Reg(param1); String("], "); Hex(param2)
  390. |opAND: String("AND "); Reg2(param1, param2)
  391. |opANDC: String("AND "); RegC(param1, param2)
  392. |opOR: String("OR "); Reg2(param1, param2)
  393. |opORC: String("OR "); RegC(param1, param2)
  394. |opXOR: String("XOR "); Reg2(param1, param2)
  395. |opXORC: String("XOR "); RegC(param1, param2)
  396. |opASR: String("ASR "); Reg2(param1, param2)
  397. |opASRC: String("ASR "); RegC(param1, param2)
  398. |opLSR: String("LSR "); Reg2(param1, param2)
  399. |opLSRC: String("LSR "); RegC(param1, param2)
  400. |opLSL: String("LSL "); Reg2(param1, param2)
  401. |opLSLC: String("LSL "); RegC(param1, param2)
  402. |opROR: String("ROR "); Reg2(param1, param2)
  403. |opRORC: String("ROR "); RegC(param1, param2)
  404. |opLEA: String("LEA "); Reg(param1 MOD 256); String(", "); String(Names[param1 DIV 256]); String(" + "); Hex(param2)
  405. |opADDRC: String("ADD "); Reg(param1 MOD 256); String(", "); Reg(param1 DIV 256); String(", "); Hex(param2)
  406. |opLABEL: String("L"); Hex(param1); String(":")
  407. |opSYSCALL: String("SYSCALL "); Reg(param1)
  408. |opCMP: String("CMP "); Reg2(param1, param2)
  409. |opCMPC: String("CMP "); RegC(param1, param2)
  410. |opJEQ: String("JEQ L"); Hex(param1)
  411. |opJNE: String("JNE L"); Hex(param1)
  412. |opJLT: String("JLT L"); Hex(param1)
  413. |opJLE: String("JLE L"); Hex(param1)
  414. |opJGT: String("JGT L"); Hex(param1)
  415. |opJGE: String("JGE L"); Hex(param1)
  416. |opSEQ: String("SEQ "); Reg(param1)
  417. |opSNE: String("SNE "); Reg(param1)
  418. |opSLT: String("SLT "); Reg(param1)
  419. |opSLE: String("SLE "); Reg(param1)
  420. |opSGT: String("SGT "); Reg(param1)
  421. |opSGE: String("SGE "); Reg(param1)
  422. |opJBT: String("JBT L"); Hex(param1)
  423. |opBIT: String("BIT "); Reg2(param1, param2)
  424. END;
  425. Ln;
  426. cmd := cmd.next
  427. END;
  428. String("TYPES:");
  429. ptr := Sections[Types];
  430. FOR i := 0 TO t_count - 1 DO
  431. IF i MOD 4 = 0 THEN
  432. Ln; String("WORD ")
  433. ELSE
  434. String(", ")
  435. END;
  436. SYSTEM.GET(ptr, t); INC(ptr, szWORD);
  437. Hex(t)
  438. END;
  439. Ln;
  440. String("STRINGS:");
  441. ptr := Sections[Strings];
  442. FOR i := 0 TO c_count - 1 DO
  443. IF i MOD 8 = 0 THEN
  444. Ln; String("BYTE ")
  445. ELSE
  446. String(", ")
  447. END;
  448. SYSTEM.GET8(ptr, b); INC(ptr);
  449. Byte(b)
  450. END;
  451. Ln;
  452. String("GLOBAL:"); Ln;
  453. String("WORDS "); Hex(glob); Ln;
  454. String("HEAP:"); Ln;
  455. String("WORDS "); Hex(heap); Ln;
  456. String("STACK:"); Ln;
  457. String("WORDS 8"); Ln;
  458. ASSERT(File.Write(F, SYSTEM.ADR(buf[0]), cnt) = cnt);
  459. File.Close(F)
  460. END disasm;
  461. PROCEDURE GetCommand (adr: INTEGER): COMMAND;
  462. VAR
  463. op, param1, param2: INTEGER;
  464. res: COMMAND;
  465. BEGIN
  466. op := 0; param1 := 0; param2 := 0;
  467. SYSTEM.GET(adr, op);
  468. SYSTEM.GET(adr + szWORD, param1);
  469. SYSTEM.GET(adr + szWORD * 2, param2);
  470. NEW(res);
  471. res.op := op;
  472. res.param1 := param1;
  473. res.param2 := param2;
  474. res.next := NIL
  475. RETURN res
  476. END GetCommand;
  477. PROCEDURE main;
  478. VAR
  479. name, param: ARRAY 1024 OF CHAR;
  480. cmd: COMMAND;
  481. file, fsize, n: INTEGER;
  482. descr: ARRAY 12 OF INTEGER;
  483. offTypes, offStrings, GlobalSize, HeapStackSize, DescrSize: INTEGER;
  484. BEGIN
  485. Out.Open;
  486. Args.GetArg(1, name);
  487. F := File.Open(name, File.OPEN_R);
  488. IF F > 0 THEN
  489. DescrSize := LEN(descr) * SYSTEM.SIZE(INTEGER);
  490. fsize := File.Seek(F, 0, File.SEEK_END);
  491. ASSERT(fsize > DescrSize);
  492. file := API._NEW(fsize);
  493. ASSERT(file # 0);
  494. n := File.Seek(F, 0, File.SEEK_BEG);
  495. ASSERT(fsize = File.Read(F, file, fsize));
  496. File.Close(F);
  497. SYSTEM.MOVE(file + fsize - DescrSize, SYSTEM.ADR(descr[0]), DescrSize);
  498. offTypes := descr[0];
  499. ASSERT(offTypes < fsize - DescrSize);
  500. ASSERT(offTypes > 0);
  501. ASSERT(offTypes MOD (3 * szWORD) = 0);
  502. offStrings := descr[1];
  503. ASSERT(offStrings < fsize - DescrSize);
  504. ASSERT(offStrings > 0);
  505. ASSERT(offStrings MOD szWORD = 0);
  506. ASSERT(offStrings > offTypes);
  507. GlobalSize := descr[2];
  508. ASSERT(GlobalSize > 0);
  509. HeapStackSize := descr[3];
  510. ASSERT(HeapStackSize > 0);
  511. Sections[Types] := API._NEW(offStrings - offTypes);
  512. ASSERT(Sections[Types] # 0);
  513. SYSTEM.MOVE(file + offTypes, Sections[Types], offStrings - offTypes);
  514. Sections[Strings] := API._NEW(fsize - offStrings - DescrSize);
  515. ASSERT(Sections[Strings] # 0);
  516. SYSTEM.MOVE(file + offStrings, Sections[Strings], fsize - offStrings - DescrSize);
  517. Sections[Global] := API._NEW(GlobalSize * szWORD);
  518. ASSERT(Sections[Global] # 0);
  519. Sections[Heap] := API._NEW(HeapStackSize * szWORD);
  520. ASSERT(Sections[Heap] # 0);
  521. Sections[Stack] := Sections[Heap] + HeapStackSize * szWORD - szWORD*8;
  522. n := offTypes DIV (3 * szWORD);
  523. first := GetCommand(file + offTypes - n * (3 * szWORD));
  524. first.prev := NIL;
  525. last := first;
  526. DEC(n);
  527. WHILE n > 0 DO
  528. cmd := GetCommand(file + offTypes - n * (3 * szWORD));
  529. IF cmd.op = opLABEL THEN
  530. Labels[cmd.param1] := cmd
  531. END;
  532. last.next := cmd;
  533. cmd.prev := last;
  534. last := cmd;
  535. DEC(n)
  536. END;
  537. file := API._DISPOSE(file);
  538. Args.GetArg(2, param);
  539. IF param = "-dis" THEN
  540. Args.GetArg(3, name);
  541. IF name # "" THEN
  542. disasm(name, (offStrings - offTypes) DIV szWORD, fsize - offStrings - DescrSize, GlobalSize, HeapStackSize)
  543. END
  544. ELSIF param = "-run" THEN
  545. exec(Labels, first, last, Sections)
  546. END
  547. ELSE
  548. Out.String("file not found"); Out.Ln
  549. END
  550. END main;
  551. BEGIN
  552. main
  553. END RVMxI.