Subversion Repositories Kolibri OS

Rev

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

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