575 lines
20 KiB
Plaintext
575 lines
20 KiB
Plaintext
|
(*
|
||
|
BSD 2-Clause License
|
||
|
|
||
|
Copyright (c) 2020, Anton Krotov
|
||
|
All rights reserved.
|
||
|
*)
|
||
|
|
||
|
(*
|
||
|
RVM32I executor and disassembler
|
||
|
|
||
|
for win32 only
|
||
|
|
||
|
Usage:
|
||
|
RVM32I.exe <program file> -run [program parameters]
|
||
|
RVM32I.exe <program file> -dis <output file>
|
||
|
*)
|
||
|
|
||
|
MODULE RVM32I;
|
||
|
|
||
|
IMPORT SYSTEM, File, Args, Out, API, HOST, RTL;
|
||
|
|
||
|
|
||
|
CONST
|
||
|
|
||
|
opSTOP = 0; opRET = 1; opENTER = 2; opNEG = 3; opNOT = 4; opABS = 5;
|
||
|
opXCHG = 6; opLDR8 = 7; opLDR16 = 8; opLDR32 = 9; opPUSH = 10; opPUSHC = 11;
|
||
|
opPOP = 12; opJGZ = 13; opJZ = 14; opJNZ = 15; opLLA = 16; opJGA = 17;
|
||
|
opJLA = 18; opJMP = 19; opCALL = 20; opCALLI = 21;
|
||
|
|
||
|
opMOV = 22; opMUL = 24; opADD = 26; opSUB = 28; opDIV = 30; opMOD = 32;
|
||
|
opSTR8 = 34; opSTR16 = 36; opSTR32 = 38; opINCL = 40; opEXCL = 42;
|
||
|
opIN = 44; opAND = 46; opOR = 48; opXOR = 50; opASR = 52; opLSR = 54;
|
||
|
opLSL = 56; opROR = 58; opMIN = 60; opMAX = 62; opEQ = 64; opNE = 66;
|
||
|
opLT = 68; opLE = 70; opGT = 72; opGE = 74; opBT = 76;
|
||
|
|
||
|
opMOVC = 23; opMULC = 25; opADDC = 27; opSUBC = 29; opDIVC = 31; opMODC = 33;
|
||
|
opSTR8C = 35; opSTR16C = 37; opSTR32C = 39; opINCLC = 41; opEXCLC = 43;
|
||
|
opINC = 45; opANDC = 47; opORC = 49; opXORC = 51; opASRC = 53; opLSRC = 55;
|
||
|
opLSLC = 57; opRORC = 59; opMINC = 61; opMAXC = 63; opEQC = 65; opNEC = 67;
|
||
|
opLTC = 69; opLEC = 71; opGTC = 73; opGEC = 75; opBTC = 77;
|
||
|
|
||
|
opLEA = 78; opLABEL = 79; opSYSCALL = 80;
|
||
|
|
||
|
|
||
|
ACC = 0; BP = 3; SP = 4;
|
||
|
|
||
|
Types = 0;
|
||
|
Strings = 1;
|
||
|
Global = 2;
|
||
|
Heap = 3;
|
||
|
Stack = 4;
|
||
|
|
||
|
|
||
|
TYPE
|
||
|
|
||
|
COMMAND = POINTER TO RECORD
|
||
|
|
||
|
op, param1, param2: INTEGER;
|
||
|
next: COMMAND
|
||
|
|
||
|
END;
|
||
|
|
||
|
|
||
|
VAR
|
||
|
|
||
|
R: ARRAY 32 OF INTEGER;
|
||
|
|
||
|
Sections: ARRAY 5 OF RECORD address: INTEGER; name: ARRAY 16 OF CHAR END;
|
||
|
|
||
|
first, last: COMMAND;
|
||
|
|
||
|
Labels: ARRAY 30000 OF COMMAND;
|
||
|
|
||
|
F: INTEGER; buf: ARRAY 65536 OF BYTE; cnt: INTEGER;
|
||
|
|
||
|
|
||
|
PROCEDURE syscall (ptr: INTEGER);
|
||
|
VAR
|
||
|
fn, p1, p2, p3, p4, r: INTEGER;
|
||
|
|
||
|
proc2: PROCEDURE (a, b: INTEGER): INTEGER;
|
||
|
proc3: PROCEDURE (a, b, c: INTEGER): INTEGER;
|
||
|
proc4: PROCEDURE (a, b, c, d: INTEGER): INTEGER;
|
||
|
|
||
|
BEGIN
|
||
|
SYSTEM.GET(ptr, fn);
|
||
|
SYSTEM.GET(ptr + 4, p1);
|
||
|
SYSTEM.GET(ptr + 8, p2);
|
||
|
SYSTEM.GET(ptr + 12, p3);
|
||
|
SYSTEM.GET(ptr + 16, p4);
|
||
|
CASE fn OF
|
||
|
| 0: HOST.ExitProcess(p1)
|
||
|
| 1: SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.GetCurrentDirectory));
|
||
|
r := proc2(p1, p2)
|
||
|
| 2: SYSTEM.PUT(SYSTEM.ADR(proc3), SYSTEM.ADR(HOST.GetArg));
|
||
|
r := proc3(p1 + 2, p2, p3)
|
||
|
| 3: SYSTEM.PUT(SYSTEM.ADR(proc4), SYSTEM.ADR(HOST.FileRead));
|
||
|
SYSTEM.PUT(ptr, proc4(p1, p2, p3, p4))
|
||
|
| 4: SYSTEM.PUT(SYSTEM.ADR(proc4), SYSTEM.ADR(HOST.FileWrite));
|
||
|
SYSTEM.PUT(ptr, proc4(p1, p2, p3, p4))
|
||
|
| 5: SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.FileCreate));
|
||
|
SYSTEM.PUT(ptr, proc2(p1, p2))
|
||
|
| 6: HOST.FileClose(p1)
|
||
|
| 7: SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.FileOpen));
|
||
|
SYSTEM.PUT(ptr, proc2(p1, p2))
|
||
|
| 8: HOST.OutChar(CHR(p1))
|
||
|
| 9: SYSTEM.PUT(ptr, HOST.GetTickCount())
|
||
|
|10: SYSTEM.PUT(ptr, HOST.UnixTime())
|
||
|
|11: SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.isRelative));
|
||
|
SYSTEM.PUT(ptr, proc2(p1, p2))
|
||
|
|12: SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.chmod));
|
||
|
r := proc2(p1, p2)
|
||
|
END
|
||
|
END syscall;
|
||
|
|
||
|
|
||
|
PROCEDURE exec;
|
||
|
VAR
|
||
|
cmd: COMMAND;
|
||
|
param1, param2: INTEGER;
|
||
|
temp: INTEGER;
|
||
|
|
||
|
BEGIN
|
||
|
cmd := first;
|
||
|
WHILE cmd # NIL DO
|
||
|
param1 := cmd.param1;
|
||
|
param2 := cmd.param2;
|
||
|
CASE cmd.op OF
|
||
|
|opSTOP: cmd := last
|
||
|
|opRET: SYSTEM.MOVE(R[SP], SYSTEM.ADR(cmd), 4); INC(R[SP], 4)
|
||
|
|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
|
||
|
|opPOP: SYSTEM.GET32(R[SP], R[param1]); INC(R[SP], 4)
|
||
|
|opNEG: R[param1] := -R[param1]
|
||
|
|opNOT: R[param1] := ORD(-BITS(R[param1]))
|
||
|
|opABS: R[param1] := ABS(R[param1])
|
||
|
|opXCHG: temp := R[param1]; R[param1] := R[param2]; R[param2] := temp
|
||
|
|opLDR8: SYSTEM.GET8(R[param2], R[param1]); R[param1] := R[param1] MOD 256;
|
||
|
|opLDR16: SYSTEM.GET16(R[param2], R[param1]); R[param1] := R[param1] MOD 65536;
|
||
|
|opLDR32: SYSTEM.GET32(R[param2], R[param1])
|
||
|
|opPUSH: DEC(R[SP], 4); SYSTEM.PUT32(R[SP], R[param1])
|
||
|
|opPUSHC: DEC(R[SP], 4); SYSTEM.PUT32(R[SP], param1)
|
||
|
|opJGZ: IF R[param1] > 0 THEN cmd := Labels[cmd.param2] END
|
||
|
|opJZ: IF R[param1] = 0 THEN cmd := Labels[cmd.param2] END
|
||
|
|opJNZ: IF R[param1] # 0 THEN cmd := Labels[cmd.param2] END
|
||
|
|opLLA: SYSTEM.MOVE(SYSTEM.ADR(Labels[cmd.param2]), SYSTEM.ADR(R[param1]), 4)
|
||
|
|opJGA: IF R[ACC] > param1 THEN cmd := Labels[cmd.param2] END
|
||
|
|opJLA: IF R[ACC] < param1 THEN cmd := Labels[cmd.param2] END
|
||
|
|opJMP: cmd := Labels[cmd.param1]
|
||
|
|opCALL: DEC(R[SP], 4); SYSTEM.MOVE(SYSTEM.ADR(cmd), R[SP], 4); cmd := Labels[cmd.param1]
|
||
|
|opCALLI: DEC(R[SP], 4); SYSTEM.MOVE(SYSTEM.ADR(cmd), R[SP], 4); SYSTEM.MOVE(SYSTEM.ADR(R[param1]), SYSTEM.ADR(cmd), 4)
|
||
|
|opMOV: R[param1] := R[param2]
|
||
|
|opMOVC: R[param1] := param2
|
||
|
|opMUL: R[param1] := R[param1] * R[param2]
|
||
|
|opMULC: R[param1] := R[param1] * param2
|
||
|
|opADD: INC(R[param1], R[param2])
|
||
|
|opADDC: INC(R[param1], param2)
|
||
|
|opSUB: DEC(R[param1], R[param2])
|
||
|
|opSUBC: DEC(R[param1], param2)
|
||
|
|opDIV: R[param1] := R[param1] DIV R[param2]
|
||
|
|opDIVC: R[param1] := R[param1] DIV param2
|
||
|
|opMOD: R[param1] := R[param1] MOD R[param2]
|
||
|
|opMODC: R[param1] := R[param1] MOD param2
|
||
|
|opSTR8: SYSTEM.PUT8(R[param1], R[param2])
|
||
|
|opSTR8C: SYSTEM.PUT8(R[param1], param2)
|
||
|
|opSTR16: SYSTEM.PUT16(R[param1], R[param2])
|
||
|
|opSTR16C: SYSTEM.PUT16(R[param1], param2)
|
||
|
|opSTR32: SYSTEM.PUT32(R[param1], R[param2])
|
||
|
|opSTR32C: SYSTEM.PUT32(R[param1], param2)
|
||
|
|opINCL: SYSTEM.GET32(R[param1], temp); SYSTEM.PUT32(R[param1], ORD(BITS(temp) + {R[param2]}))
|
||
|
|opINCLC: SYSTEM.GET32(R[param1], temp); SYSTEM.PUT32(R[param1], ORD(BITS(temp) + {param2}))
|
||
|
|opEXCL: SYSTEM.GET32(R[param1], temp); SYSTEM.PUT32(R[param1], ORD(BITS(temp) - {R[param2]}))
|
||
|
|opEXCLC: SYSTEM.GET32(R[param1], temp); SYSTEM.PUT32(R[param1], ORD(BITS(temp) - {param2}))
|
||
|
|opIN: R[param1] := ORD(R[param1] IN BITS(R[param2]))
|
||
|
|opINC: R[param1] := ORD(R[param1] IN BITS(param2))
|
||
|
|opAND: R[param1] := ORD(BITS(R[param1]) * BITS(R[param2]))
|
||
|
|opANDC: R[param1] := ORD(BITS(R[param1]) * BITS(param2))
|
||
|
|opOR: R[param1] := ORD(BITS(R[param1]) + BITS(R[param2]))
|
||
|
|opORC: R[param1] := ORD(BITS(R[param1]) + BITS(param2))
|
||
|
|opXOR: R[param1] := ORD(BITS(R[param1]) / BITS(R[param2]))
|
||
|
|opXORC: R[param1] := ORD(BITS(R[param1]) / BITS(param2))
|
||
|
|opASR: R[param1] := ASR(R[param1], R[param2])
|
||
|
|opASRC: R[param1] := ASR(R[param1], param2)
|
||
|
|opLSR: R[param1] := LSR(R[param1], R[param2])
|
||
|
|opLSRC: R[param1] := LSR(R[param1], param2)
|
||
|
|opLSL: R[param1] := LSL(R[param1], R[param2])
|
||
|
|opLSLC: R[param1] := LSL(R[param1], param2)
|
||
|
|opROR: R[param1] := ROR(R[param1], R[param2])
|
||
|
|opRORC: R[param1] := ROR(R[param1], param2)
|
||
|
|opMIN: R[param1] := MIN(R[param1], R[param2])
|
||
|
|opMINC: R[param1] := MIN(R[param1], param2)
|
||
|
|opMAX: R[param1] := MAX(R[param1], R[param2])
|
||
|
|opMAXC: R[param1] := MAX(R[param1], param2)
|
||
|
|opEQ: R[param1] := ORD(R[param1] = R[param2])
|
||
|
|opEQC: R[param1] := ORD(R[param1] = param2)
|
||
|
|opNE: R[param1] := ORD(R[param1] # R[param2])
|
||
|
|opNEC: R[param1] := ORD(R[param1] # param2)
|
||
|
|opLT: R[param1] := ORD(R[param1] < R[param2])
|
||
|
|opLTC: R[param1] := ORD(R[param1] < param2)
|
||
|
|opLE: R[param1] := ORD(R[param1] <= R[param2])
|
||
|
|opLEC: R[param1] := ORD(R[param1] <= param2)
|
||
|
|opGT: R[param1] := ORD(R[param1] > R[param2])
|
||
|
|opGTC: R[param1] := ORD(R[param1] > param2)
|
||
|
|opGE: R[param1] := ORD(R[param1] >= R[param2])
|
||
|
|opGEC: R[param1] := ORD(R[param1] >= param2)
|
||
|
|opBT: R[param1] := ORD((R[param1] < R[param2]) & (R[param1] >= 0))
|
||
|
|opBTC: R[param1] := ORD((R[param1] < param2) & (R[param1] >= 0))
|
||
|
|opLEA: R[param1 MOD 256] := Sections[param1 DIV 256].address + param2
|
||
|
|opLABEL:
|
||
|
|opSYSCALL: syscall(R[param1])
|
||
|
END;
|
||
|
cmd := cmd.next
|
||
|
END
|
||
|
END exec;
|
||
|
|
||
|
|
||
|
PROCEDURE disasm (name: ARRAY OF CHAR; t_count, c_count, glob, heap: INTEGER);
|
||
|
VAR
|
||
|
cmd: COMMAND;
|
||
|
param1, param2, i, t, ptr: INTEGER;
|
||
|
b: BYTE;
|
||
|
|
||
|
|
||
|
PROCEDURE String (s: ARRAY OF CHAR);
|
||
|
VAR
|
||
|
n: INTEGER;
|
||
|
|
||
|
BEGIN
|
||
|
n := LENGTH(s);
|
||
|
IF n > LEN(buf) - cnt THEN
|
||
|
ASSERT(File.Write(F, SYSTEM.ADR(buf[0]), cnt) = cnt);
|
||
|
cnt := 0
|
||
|
END;
|
||
|
SYSTEM.MOVE(SYSTEM.ADR(s[0]), SYSTEM.ADR(buf[0]) + cnt, n);
|
||
|
INC(cnt, n)
|
||
|
END String;
|
||
|
|
||
|
|
||
|
PROCEDURE Ln;
|
||
|
BEGIN
|
||
|
String(0DX + 0AX)
|
||
|
END Ln;
|
||
|
|
||
|
|
||
|
PROCEDURE hexdgt (n: INTEGER): CHAR;
|
||
|
BEGIN
|
||
|
IF n < 10 THEN
|
||
|
INC(n, ORD("0"))
|
||
|
ELSE
|
||
|
INC(n, ORD("A") - 10)
|
||
|
END
|
||
|
|
||
|
RETURN CHR(n)
|
||
|
END hexdgt;
|
||
|
|
||
|
|
||
|
PROCEDURE Hex (x: INTEGER);
|
||
|
VAR
|
||
|
str: ARRAY 11 OF CHAR;
|
||
|
n: INTEGER;
|
||
|
|
||
|
BEGIN
|
||
|
n := 10;
|
||
|
str[10] := 0X;
|
||
|
WHILE n > 2 DO
|
||
|
str[n - 1] := hexdgt(x MOD 16);
|
||
|
x := x DIV 16;
|
||
|
DEC(n)
|
||
|
END;
|
||
|
str[1] := "x";
|
||
|
str[0] := "0";
|
||
|
String(str)
|
||
|
END Hex;
|
||
|
|
||
|
|
||
|
PROCEDURE Byte (x: BYTE);
|
||
|
VAR
|
||
|
str: ARRAY 5 OF CHAR;
|
||
|
|
||
|
BEGIN
|
||
|
str[4] := 0X;
|
||
|
str[3] := hexdgt(x MOD 16);
|
||
|
str[2] := hexdgt(x DIV 16);
|
||
|
str[1] := "x";
|
||
|
str[0] := "0";
|
||
|
String(str)
|
||
|
END Byte;
|
||
|
|
||
|
|
||
|
PROCEDURE Reg (n: INTEGER);
|
||
|
VAR
|
||
|
s: ARRAY 2 OF CHAR;
|
||
|
BEGIN
|
||
|
IF n = BP THEN
|
||
|
String("BP")
|
||
|
ELSIF n = SP THEN
|
||
|
String("SP")
|
||
|
ELSE
|
||
|
String("R");
|
||
|
s[1] := 0X;
|
||
|
IF n >= 10 THEN
|
||
|
s[0] := CHR(n DIV 10 + ORD("0"));
|
||
|
String(s)
|
||
|
END;
|
||
|
s[0] := CHR(n MOD 10 + ORD("0"));
|
||
|
String(s)
|
||
|
END
|
||
|
END Reg;
|
||
|
|
||
|
|
||
|
PROCEDURE Reg2 (r1, r2: INTEGER);
|
||
|
BEGIN
|
||
|
Reg(r1); String(", "); Reg(r2)
|
||
|
END Reg2;
|
||
|
|
||
|
|
||
|
PROCEDURE RegC (r, c: INTEGER);
|
||
|
BEGIN
|
||
|
Reg(r); String(", "); Hex(c)
|
||
|
END RegC;
|
||
|
|
||
|
|
||
|
PROCEDURE RegL (r, label: INTEGER);
|
||
|
BEGIN
|
||
|
Reg(r); String(", L"); Hex(label)
|
||
|
END RegL;
|
||
|
|
||
|
|
||
|
BEGIN
|
||
|
Sections[Types].name := "TYPES";
|
||
|
Sections[Strings].name := "STRINGS";
|
||
|
Sections[Global].name := "GLOBAL";
|
||
|
Sections[Heap].name := "HEAP";
|
||
|
Sections[Stack].name := "STACK";
|
||
|
|
||
|
F := File.Create(name);
|
||
|
ASSERT(F > 0);
|
||
|
cnt := 0;
|
||
|
String("CODE:"); Ln;
|
||
|
cmd := first;
|
||
|
WHILE cmd # NIL DO
|
||
|
param1 := cmd.param1;
|
||
|
param2 := cmd.param2;
|
||
|
CASE cmd.op OF
|
||
|
|opSTOP: String("STOP")
|
||
|
|opRET: String("RET")
|
||
|
|opENTER: String("ENTER "); Hex(param1)
|
||
|
|opPOP: String("POP "); Reg(param1)
|
||
|
|opNEG: String("NEG "); Reg(param1)
|
||
|
|opNOT: String("NOT "); Reg(param1)
|
||
|
|opABS: String("ABS "); Reg(param1)
|
||
|
|opXCHG: String("XCHG "); Reg2(param1, param2)
|
||
|
|opLDR8: String("LDR8 "); Reg2(param1, param2)
|
||
|
|opLDR16: String("LDR16 "); Reg2(param1, param2)
|
||
|
|opLDR32: String("LDR32 "); Reg2(param1, param2)
|
||
|
|opPUSH: String("PUSH "); Reg(param1)
|
||
|
|opPUSHC: String("PUSH "); Hex(param1)
|
||
|
|opJGZ: String("JGZ "); RegL(param1, param2)
|
||
|
|opJZ: String("JZ "); RegL(param1, param2)
|
||
|
|opJNZ: String("JNZ "); RegL(param1, param2)
|
||
|
|opLLA: String("LLA "); RegL(param1, param2)
|
||
|
|opJGA: String("JGA "); Hex(param1); String(", L"); Hex(param2)
|
||
|
|opJLA: String("JLA "); Hex(param1); String(", L"); Hex(param2)
|
||
|
|opJMP: String("JMP L"); Hex(param1)
|
||
|
|opCALL: String("CALL L"); Hex(param1)
|
||
|
|opCALLI: String("CALL "); Reg(param1)
|
||
|
|opMOV: String("MOV "); Reg2(param1, param2)
|
||
|
|opMOVC: String("MOV "); RegC(param1, param2)
|
||
|
|opMUL: String("MUL "); Reg2(param1, param2)
|
||
|
|opMULC: String("MUL "); RegC(param1, param2)
|
||
|
|opADD: String("ADD "); Reg2(param1, param2)
|
||
|
|opADDC: String("ADD "); RegC(param1, param2)
|
||
|
|opSUB: String("SUB "); Reg2(param1, param2)
|
||
|
|opSUBC: String("SUB "); RegC(param1, param2)
|
||
|
|opDIV: String("DIV "); Reg2(param1, param2)
|
||
|
|opDIVC: String("DIV "); RegC(param1, param2)
|
||
|
|opMOD: String("MOD "); Reg2(param1, param2)
|
||
|
|opMODC: String("MOD "); RegC(param1, param2)
|
||
|
|opSTR8: String("STR8 "); Reg2(param1, param2)
|
||
|
|opSTR8C: String("STR8 "); RegC(param1, param2)
|
||
|
|opSTR16: String("STR16 "); Reg2(param1, param2)
|
||
|
|opSTR16C: String("STR16 "); RegC(param1, param2)
|
||
|
|opSTR32: String("STR32 "); Reg2(param1, param2)
|
||
|
|opSTR32C: String("STR32 "); RegC(param1, param2)
|
||
|
|opINCL: String("INCL "); Reg2(param1, param2)
|
||
|
|opINCLC: String("INCL "); RegC(param1, param2)
|
||
|
|opEXCL: String("EXCL "); Reg2(param1, param2)
|
||
|
|opEXCLC: String("EXCL "); RegC(param1, param2)
|
||
|
|opIN: String("IN "); Reg2(param1, param2)
|
||
|
|opINC: String("IN "); RegC(param1, param2)
|
||
|
|opAND: String("AND "); Reg2(param1, param2)
|
||
|
|opANDC: String("AND "); RegC(param1, param2)
|
||
|
|opOR: String("OR "); Reg2(param1, param2)
|
||
|
|opORC: String("OR "); RegC(param1, param2)
|
||
|
|opXOR: String("XOR "); Reg2(param1, param2)
|
||
|
|opXORC: String("XOR "); RegC(param1, param2)
|
||
|
|opASR: String("ASR "); Reg2(param1, param2)
|
||
|
|opASRC: String("ASR "); RegC(param1, param2)
|
||
|
|opLSR: String("LSR "); Reg2(param1, param2)
|
||
|
|opLSRC: String("LSR "); RegC(param1, param2)
|
||
|
|opLSL: String("LSL "); Reg2(param1, param2)
|
||
|
|opLSLC: String("LSL "); RegC(param1, param2)
|
||
|
|opROR: String("ROR "); Reg2(param1, param2)
|
||
|
|opRORC: String("ROR "); RegC(param1, param2)
|
||
|
|opMIN: String("MIN "); Reg2(param1, param2)
|
||
|
|opMINC: String("MIN "); RegC(param1, param2)
|
||
|
|opMAX: String("MAX "); Reg2(param1, param2)
|
||
|
|opMAXC: String("MAX "); RegC(param1, param2)
|
||
|
|opEQ: String("EQ "); Reg2(param1, param2)
|
||
|
|opEQC: String("EQ "); RegC(param1, param2)
|
||
|
|opNE: String("NE "); Reg2(param1, param2)
|
||
|
|opNEC: String("NE "); RegC(param1, param2)
|
||
|
|opLT: String("LT "); Reg2(param1, param2)
|
||
|
|opLTC: String("LT "); RegC(param1, param2)
|
||
|
|opLE: String("LE "); Reg2(param1, param2)
|
||
|
|opLEC: String("LE "); RegC(param1, param2)
|
||
|
|opGT: String("GT "); Reg2(param1, param2)
|
||
|
|opGTC: String("GT "); RegC(param1, param2)
|
||
|
|opGE: String("GE "); Reg2(param1, param2)
|
||
|
|opGEC: String("GE "); RegC(param1, param2)
|
||
|
|opBT: String("BT "); Reg2(param1, param2)
|
||
|
|opBTC: String("BT "); RegC(param1, param2)
|
||
|
|opLEA: String("LEA "); Reg(param1 MOD 256); String(", "); String(Sections[param1 DIV 256].name); String(" + "); Hex(param2)
|
||
|
|opLABEL: String("L"); Hex(param1); String(":")
|
||
|
|opSYSCALL: String("SYSCALL "); Reg(param1)
|
||
|
END;
|
||
|
Ln;
|
||
|
cmd := cmd.next
|
||
|
END;
|
||
|
|
||
|
String("TYPES:");
|
||
|
ptr := Sections[Types].address;
|
||
|
FOR i := 0 TO t_count - 1 DO
|
||
|
IF i MOD 4 = 0 THEN
|
||
|
Ln; String("WORD ")
|
||
|
ELSE
|
||
|
String(", ")
|
||
|
END;
|
||
|
SYSTEM.GET32(ptr, t); INC(ptr, 4);
|
||
|
Hex(t)
|
||
|
END;
|
||
|
Ln;
|
||
|
|
||
|
String("STRINGS:");
|
||
|
ptr := Sections[Strings].address;
|
||
|
FOR i := 0 TO c_count - 1 DO
|
||
|
IF i MOD 8 = 0 THEN
|
||
|
Ln; String("BYTE ")
|
||
|
ELSE
|
||
|
String(", ")
|
||
|
END;
|
||
|
SYSTEM.GET8(ptr, b); INC(ptr);
|
||
|
Byte(b)
|
||
|
END;
|
||
|
Ln;
|
||
|
|
||
|
String("GLOBAL:"); Ln;
|
||
|
String("WORDS "); Hex(glob); Ln;
|
||
|
String("HEAP:"); Ln;
|
||
|
String("WORDS "); Hex(heap); Ln;
|
||
|
String("STACK:"); Ln;
|
||
|
String("WORDS 8"); Ln;
|
||
|
|
||
|
ASSERT(File.Write(F, SYSTEM.ADR(buf[0]), cnt) = cnt);
|
||
|
File.Close(F)
|
||
|
END disasm;
|
||
|
|
||
|
|
||
|
PROCEDURE GetCommand (adr: INTEGER): COMMAND;
|
||
|
VAR
|
||
|
op, param1, param2: INTEGER;
|
||
|
res: COMMAND;
|
||
|
|
||
|
BEGIN
|
||
|
op := 0; param1 := 0; param2 := 0;
|
||
|
SYSTEM.GET32(adr, op);
|
||
|
SYSTEM.GET32(adr + 4, param1);
|
||
|
SYSTEM.GET32(adr + 8, param2);
|
||
|
NEW(res);
|
||
|
res.op := op;
|
||
|
res.param1 := param1;
|
||
|
res.param2 := param2;
|
||
|
res.next := NIL
|
||
|
|
||
|
RETURN res
|
||
|
END GetCommand;
|
||
|
|
||
|
|
||
|
PROCEDURE main;
|
||
|
VAR
|
||
|
name, param: ARRAY 1024 OF CHAR;
|
||
|
cmd: COMMAND;
|
||
|
file, fsize, n: INTEGER;
|
||
|
|
||
|
descr: ARRAY 12 OF INTEGER;
|
||
|
|
||
|
offTypes, offStrings, GlobalSize, HeapStackSize, DescrSize: INTEGER;
|
||
|
|
||
|
BEGIN
|
||
|
Out.Open;
|
||
|
Args.GetArg(1, name);
|
||
|
F := File.Open(name, File.OPEN_R);
|
||
|
IF F > 0 THEN
|
||
|
DescrSize := LEN(descr) * SYSTEM.SIZE(INTEGER);
|
||
|
fsize := File.Seek(F, 0, File.SEEK_END);
|
||
|
ASSERT(fsize > DescrSize);
|
||
|
file := API._NEW(fsize);
|
||
|
ASSERT(file # 0);
|
||
|
n := File.Seek(F, 0, File.SEEK_BEG);
|
||
|
ASSERT(fsize = File.Read(F, file, fsize));
|
||
|
File.Close(F);
|
||
|
|
||
|
SYSTEM.MOVE(file + fsize - DescrSize, SYSTEM.ADR(descr[0]), DescrSize);
|
||
|
offTypes := descr[0];
|
||
|
ASSERT(offTypes < fsize - DescrSize);
|
||
|
ASSERT(offTypes > 0);
|
||
|
ASSERT(offTypes MOD 12 = 0);
|
||
|
offStrings := descr[1];
|
||
|
ASSERT(offStrings < fsize - DescrSize);
|
||
|
ASSERT(offStrings > 0);
|
||
|
ASSERT(offStrings MOD 4 = 0);
|
||
|
ASSERT(offStrings > offTypes);
|
||
|
GlobalSize := descr[2];
|
||
|
ASSERT(GlobalSize > 0);
|
||
|
HeapStackSize := descr[3];
|
||
|
ASSERT(HeapStackSize > 0);
|
||
|
|
||
|
Sections[Types].address := API._NEW(offStrings - offTypes);
|
||
|
ASSERT(Sections[Types].address # 0);
|
||
|
SYSTEM.MOVE(file + offTypes, Sections[Types].address, offStrings - offTypes);
|
||
|
|
||
|
Sections[Strings].address := API._NEW(fsize - offStrings - DescrSize);
|
||
|
ASSERT(Sections[Strings].address # 0);
|
||
|
SYSTEM.MOVE(file + offStrings, Sections[Strings].address, fsize - offStrings - DescrSize);
|
||
|
|
||
|
Sections[Global].address := API._NEW(GlobalSize * 4);
|
||
|
ASSERT(Sections[Global].address # 0);
|
||
|
|
||
|
Sections[Heap].address := API._NEW(HeapStackSize * 4);
|
||
|
ASSERT(Sections[Heap].address # 0);
|
||
|
|
||
|
Sections[Stack].address := Sections[Heap].address + HeapStackSize * 4 - 32;
|
||
|
|
||
|
n := offTypes DIV 12;
|
||
|
first := GetCommand(file + offTypes - n * 12);
|
||
|
last := first;
|
||
|
DEC(n);
|
||
|
WHILE n > 0 DO
|
||
|
cmd := GetCommand(file + offTypes - n * 12);
|
||
|
IF cmd.op = opLABEL THEN
|
||
|
Labels[cmd.param1] := cmd
|
||
|
END;
|
||
|
last.next := cmd;
|
||
|
last := cmd;
|
||
|
DEC(n)
|
||
|
END;
|
||
|
file := API._DISPOSE(file);
|
||
|
Args.GetArg(2, param);
|
||
|
IF param = "-dis" THEN
|
||
|
Args.GetArg(3, name);
|
||
|
IF name # "" THEN
|
||
|
disasm(name, (offStrings - offTypes) DIV 4, fsize - offStrings - DescrSize, GlobalSize, HeapStackSize)
|
||
|
END
|
||
|
ELSIF param = "-run" THEN
|
||
|
exec
|
||
|
END
|
||
|
ELSE
|
||
|
Out.String("file not found"); Out.Ln
|
||
|
END
|
||
|
END main;
|
||
|
|
||
|
|
||
|
BEGIN
|
||
|
ASSERT(RTL.bit_depth = 32);
|
||
|
main
|
||
|
END RVM32I.
|