Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

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