forked from KolibriOS/kolibrios
Oberon07: update by akron1
git-svn-id: svn://kolibrios.org@8863 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
1cff99b570
commit
dbc78b92ce
Binary file not shown.
@ -1,575 +0,0 @@
|
|||||||
(*
|
|
||||||
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.
|
|
@ -1,668 +0,0 @@
|
|||||||
(*
|
|
||||||
BSD 2-Clause License
|
|
||||||
|
|
||||||
Copyright (c) 2020-2021, Anton Krotov
|
|
||||||
All rights reserved.
|
|
||||||
*)
|
|
||||||
|
|
||||||
(*
|
|
||||||
RVMxI executor and disassembler
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
RVMxI.exe <program file> -run [program parameters]
|
|
||||||
RVMxI.exe <program file> -dis <output file>
|
|
||||||
*)
|
|
||||||
|
|
||||||
MODULE RVMxI;
|
|
||||||
|
|
||||||
IMPORT SYSTEM, File, Args, Out, API, HOST;
|
|
||||||
|
|
||||||
|
|
||||||
CONST
|
|
||||||
|
|
||||||
szWORD = HOST.bit_depth DIV 8;
|
|
||||||
|
|
||||||
opSTOP = 0; opRET = 1; opENTER = 2; opNEG = 3; opNOT = 4; opNOP = 5;
|
|
||||||
opXCHG = 6; opLDB = 7; opLDH = 8; opLDW = 9; opPUSH = 10; opPUSHC = 11;
|
|
||||||
opPOP = 12; opLABEL = 13; opLEA = 14; opLLA = 15;
|
|
||||||
opLDD = 16; (* 17, 18 *)
|
|
||||||
opJMP = 19; opCALL = 20; opCALLI = 21;
|
|
||||||
|
|
||||||
opMOV = 22; opMUL = 24; opADD = 26; opSUB = 28; opDIV = 30; opMOD = 32;
|
|
||||||
opSTB = 34; opSTH = 36; opSTW = 38; opSTD = 40; (* 42, 44 *)
|
|
||||||
opAND = 46; opOR = 48; opXOR = 50; opASR = 52; opLSR = 54;
|
|
||||||
opLSL = 56; opROR = 58; (* 60, 62 *) opCMP = 64;
|
|
||||||
|
|
||||||
opMOVC = 23; opMULC = 25; opADDC = 27; opSUBC = 29; opDIVC = 31; opMODC = 33;
|
|
||||||
opSTBC = 35; opSTHC = 37; opSTWC = 39; opSTDC = 41; (* 43, 45 *)
|
|
||||||
opANDC = 47; opORC = 49; opXORC = 51; opASRC = 53; opLSRC = 55;
|
|
||||||
opLSLC = 57; opRORC = 59; (* 61, 63 *) opCMPC = 65;
|
|
||||||
|
|
||||||
opBIT = 66; opSYSCALL = 67; opJBT = 68; opADDRC = 69;
|
|
||||||
|
|
||||||
opJEQ = 70; opJNE = 71; opJLT = 72; opJGE = 73; opJGT = 74; opJLE = 75;
|
|
||||||
opSEQ = 76; opSNE = 77; opSLT = 78; opSGE = 79; opSGT = 80; opSLE = 81;
|
|
||||||
|
|
||||||
|
|
||||||
nREG = 16;
|
|
||||||
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, prev: COMMAND
|
|
||||||
|
|
||||||
END;
|
|
||||||
|
|
||||||
LABELS = ARRAY 30000 OF COMMAND;
|
|
||||||
|
|
||||||
SECTIONS = ARRAY 5 OF INTEGER;
|
|
||||||
|
|
||||||
|
|
||||||
VAR
|
|
||||||
|
|
||||||
Sections: SECTIONS;
|
|
||||||
|
|
||||||
first, last: COMMAND;
|
|
||||||
|
|
||||||
Labels: LABELS;
|
|
||||||
|
|
||||||
F: INTEGER; buf: ARRAY 65536 OF BYTE; cnt: INTEGER;
|
|
||||||
|
|
||||||
|
|
||||||
PROCEDURE syscall (ptr: INTEGER);
|
|
||||||
VAR
|
|
||||||
fn, r, n: INTEGER;
|
|
||||||
|
|
||||||
proc2: PROCEDURE (a, b: INTEGER): INTEGER;
|
|
||||||
proc3: PROCEDURE (a, b, c: INTEGER): INTEGER;
|
|
||||||
proc4: PROCEDURE (a, b, c, d: INTEGER): INTEGER;
|
|
||||||
|
|
||||||
r1, r2: REAL;
|
|
||||||
|
|
||||||
|
|
||||||
PROCEDURE GetInt (ptr, n: INTEGER): INTEGER;
|
|
||||||
BEGIN
|
|
||||||
SYSTEM.GET(ptr + SYSTEM.SIZE(INTEGER) * n, n)
|
|
||||||
RETURN n
|
|
||||||
END GetInt;
|
|
||||||
|
|
||||||
|
|
||||||
PROCEDURE GetReal (ptr, n: INTEGER): REAL;
|
|
||||||
VAR
|
|
||||||
r: REAL;
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
SYSTEM.GET(ptr + SYSTEM.SIZE(INTEGER) * n, r)
|
|
||||||
RETURN r
|
|
||||||
END GetReal;
|
|
||||||
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
fn := GetInt(ptr, 0);
|
|
||||||
CASE fn OF
|
|
||||||
| 0:
|
|
||||||
HOST.ExitProcess(GetInt(ptr, 1))
|
|
||||||
|
|
||||||
| 1:
|
|
||||||
SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.GetCurrentDirectory));
|
|
||||||
r := proc2(GetInt(ptr, 1), GetInt(ptr, 2))
|
|
||||||
|
|
||||||
| 2:
|
|
||||||
n := GetInt(ptr, 1);
|
|
||||||
SYSTEM.PUT(SYSTEM.ADR(proc3), SYSTEM.ADR(HOST.GetArg));
|
|
||||||
r := proc3(n - ORD(n = 0) + 2, GetInt(ptr, 2), GetInt(ptr, 3))
|
|
||||||
|
|
||||||
| 3:
|
|
||||||
SYSTEM.PUT(SYSTEM.ADR(proc4), SYSTEM.ADR(HOST.FileRead));
|
|
||||||
SYSTEM.PUT(ptr, proc4(GetInt(ptr, 1), GetInt(ptr, 2), GetInt(ptr, 3), GetInt(ptr, 4)))
|
|
||||||
|
|
||||||
| 4:
|
|
||||||
SYSTEM.PUT(SYSTEM.ADR(proc4), SYSTEM.ADR(HOST.FileWrite));
|
|
||||||
SYSTEM.PUT(ptr, proc4(GetInt(ptr, 1), GetInt(ptr, 2), GetInt(ptr, 3), GetInt(ptr, 4)))
|
|
||||||
|
|
||||||
| 5:
|
|
||||||
SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.FileCreate));
|
|
||||||
SYSTEM.PUT(ptr, proc2(GetInt(ptr, 1), GetInt(ptr, 2)))
|
|
||||||
|
|
||||||
| 6:
|
|
||||||
HOST.FileClose(GetInt(ptr, 1))
|
|
||||||
|
|
||||||
| 7:
|
|
||||||
SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.FileOpen));
|
|
||||||
SYSTEM.PUT(ptr, proc2(GetInt(ptr, 1), GetInt(ptr, 2)))
|
|
||||||
|
|
||||||
| 8:
|
|
||||||
HOST.OutChar(CHR(GetInt(ptr, 1)))
|
|
||||||
|
|
||||||
| 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(GetInt(ptr, 1), GetInt(ptr, 2)))
|
|
||||||
|
|
||||||
|12:
|
|
||||||
SYSTEM.PUT(SYSTEM.ADR(proc2), SYSTEM.ADR(HOST.chmod));
|
|
||||||
r := proc2(GetInt(ptr, 1), GetInt(ptr, 2))
|
|
||||||
|
|
||||||
|100..103:
|
|
||||||
r1 := GetReal(ptr, 1);
|
|
||||||
r2 := GetReal(ptr, 2);
|
|
||||||
CASE fn OF
|
|
||||||
|100: SYSTEM.PUT(ptr, r2 * r1)
|
|
||||||
|101: SYSTEM.PUT(ptr, r2 / r1)
|
|
||||||
|102: SYSTEM.PUT(ptr, r2 + r1)
|
|
||||||
|103: SYSTEM.PUT(ptr, r2 - r1)
|
|
||||||
END
|
|
||||||
|
|
||||||
|104:
|
|
||||||
r1 := GetReal(ptr, 2);
|
|
||||||
r2 := GetReal(ptr, 3);
|
|
||||||
CASE GetInt(ptr, 1) OF
|
|
||||||
|0: SYSTEM.PUT(ptr, ORD(r2 = r1))
|
|
||||||
|1: SYSTEM.PUT(ptr, ORD(r2 # r1))
|
|
||||||
|2: SYSTEM.PUT(ptr, ORD(r2 < r1))
|
|
||||||
|3: SYSTEM.PUT(ptr, ORD(r2 <= r1))
|
|
||||||
|4: SYSTEM.PUT(ptr, ORD(r2 > r1))
|
|
||||||
|5: SYSTEM.PUT(ptr, ORD(r2 >= r1))
|
|
||||||
END
|
|
||||||
|
|
||||||
|105:
|
|
||||||
SYSTEM.PUT(ptr, FLOOR(GetReal(ptr, 1)))
|
|
||||||
|
|
||||||
|106:
|
|
||||||
SYSTEM.PUT(ptr, FLT(GetInt(ptr, 1)))
|
|
||||||
|
|
||||||
END
|
|
||||||
END syscall;
|
|
||||||
|
|
||||||
|
|
||||||
PROCEDURE exec (VAR Labels: LABELS; first, last: COMMAND; Sections: SECTIONS);
|
|
||||||
VAR
|
|
||||||
cmd: COMMAND;
|
|
||||||
param1, param2, i: INTEGER;
|
|
||||||
R: ARRAY nREG OF INTEGER;
|
|
||||||
|
|
||||||
fe, fl, fb: BOOLEAN;
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
FOR i := 0 TO LEN(Labels) - 1 DO
|
|
||||||
cmd := Labels[i];
|
|
||||||
IF cmd # NIL THEN
|
|
||||||
REPEAT
|
|
||||||
cmd := cmd.next
|
|
||||||
UNTIL cmd.op # opLABEL;
|
|
||||||
Labels[i] := cmd
|
|
||||||
END
|
|
||||||
END;
|
|
||||||
|
|
||||||
cmd := first;
|
|
||||||
WHILE cmd # NIL DO
|
|
||||||
IF cmd.op = opLABEL THEN
|
|
||||||
cmd.prev.next := cmd.next;
|
|
||||||
cmd.next.prev := cmd.prev
|
|
||||||
END;
|
|
||||||
cmd := cmd.next
|
|
||||||
END;
|
|
||||||
|
|
||||||
FOR i := 0 TO LEN(Labels) - 1 DO
|
|
||||||
IF Labels[i] # NIL THEN
|
|
||||||
Labels[i] := Labels[i].prev
|
|
||||||
END
|
|
||||||
END;
|
|
||||||
|
|
||||||
cmd := first;
|
|
||||||
WHILE cmd # NIL DO
|
|
||||||
param1 := cmd.param1;
|
|
||||||
param2 := cmd.param2;
|
|
||||||
|
|
||||||
CASE cmd.op OF
|
|
||||||
|opSTOP: cmd := last
|
|
||||||
|opRET: SYSTEM.GET(R[SP], cmd); INC(R[SP], szWORD)
|
|
||||||
|opENTER: DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], R[BP]); R[BP] := R[SP];
|
|
||||||
WHILE param1 > 0 DO DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], 0); DEC(param1) END
|
|
||||||
|opPOP: SYSTEM.GET(R[SP], R[param1]); INC(R[SP], szWORD)
|
|
||||||
|opPUSH: DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], R[param1])
|
|
||||||
|opPUSHC: DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], param1)
|
|
||||||
|opCALL: DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], cmd); cmd := Labels[param1]
|
|
||||||
|opCALLI: DEC(R[SP], szWORD); SYSTEM.PUT(R[SP], cmd); SYSTEM.GET(SYSTEM.ADR(R[param1]), cmd)
|
|
||||||
|opNEG: R[param1] := -R[param1]
|
|
||||||
|opNOT: R[param1] := ORD(-BITS(R[param1]))
|
|
||||||
|opNOP:
|
|
||||||
|opXCHG: i := R[param1]; R[param1] := R[param2]; R[param2] := i
|
|
||||||
|opLDB: i := param1 MOD 256; SYSTEM.GET8(R[param1 DIV 256] + param2, R[i]); R[i] := R[i] MOD 256
|
|
||||||
|opLDH: i := param1 MOD 256; SYSTEM.GET16(R[param1 DIV 256] + param2, R[i]); R[i] := R[i] MOD 65536
|
|
||||||
|opLDW: SYSTEM.GET32(R[param1 DIV 256] + param2, R[param1 MOD 256]);
|
|
||||||
$IF (CPU_X8664)
|
|
||||||
R[param1 MOD 256] := R[param1 MOD 256] MOD 100000000H
|
|
||||||
$END
|
|
||||||
|opLDD: SYSTEM.GET(R[param1 DIV 256] + param2, R[param1 MOD 256])
|
|
||||||
|opLLA: SYSTEM.GET(SYSTEM.ADR(Labels[param2]), R[param1])
|
|
||||||
|opJMP: cmd := Labels[param1]
|
|
||||||
|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
|
|
||||||
|opSTB: SYSTEM.PUT8(R[param1 DIV 256] + param2, R[param1 MOD 256])
|
|
||||||
|opSTH: SYSTEM.PUT16(R[param1 DIV 256] + param2, R[param1 MOD 256])
|
|
||||||
|opSTW: SYSTEM.PUT32(R[param1 DIV 256] + param2, R[param1 MOD 256])
|
|
||||||
|opSTD: SYSTEM.PUT(R[param1 DIV 256] + param2, R[param1 MOD 256])
|
|
||||||
|opSTBC: SYSTEM.PUT8(R[param1], param2)
|
|
||||||
|opSTHC: SYSTEM.PUT16(R[param1], param2)
|
|
||||||
|opSTWC: SYSTEM.PUT32(R[param1], param2)
|
|
||||||
|opSTDC: SYSTEM.PUT(R[param1], 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)
|
|
||||||
|opLEA: R[param1 MOD 256] := Sections[param1 DIV 256] + param2
|
|
||||||
(*|opLABEL:*)
|
|
||||||
|opSYSCALL: syscall(R[param1])
|
|
||||||
|opADDRC: R[param1 MOD 256] := R[param1 DIV 256] + param2
|
|
||||||
|opCMP: fl := R[param1] < R[param2]; fe := R[param1] = R[param2]; fb := fl & (R[param1] >= 0)
|
|
||||||
|opCMPC: fl := R[param1] < param2; fe := R[param1] = param2; fb := fl & (R[param1] >= 0)
|
|
||||||
|opJEQ: IF fe THEN cmd := Labels[param1] END
|
|
||||||
|opJNE: IF ~fe THEN cmd := Labels[param1] END
|
|
||||||
|opJLT: IF fl THEN cmd := Labels[param1] END
|
|
||||||
|opJLE: IF fl OR fe THEN cmd := Labels[param1] END
|
|
||||||
|opJGT: IF ~fl & ~fe THEN cmd := Labels[param1] END
|
|
||||||
|opJGE: IF ~fl THEN cmd := Labels[param1] END
|
|
||||||
|opSEQ: R[param1] := ORD(fe)
|
|
||||||
|opSNE: R[param1] := ORD(~fe)
|
|
||||||
|opSLT: R[param1] := ORD(fl)
|
|
||||||
|opSLE: R[param1] := ORD(fl OR fe)
|
|
||||||
|opSGT: R[param1] := ORD(~fl & ~fe)
|
|
||||||
|opSGE: R[param1] := ORD(~fl)
|
|
||||||
|opJBT: IF fb THEN cmd := Labels[param1] END
|
|
||||||
|opBIT: R[param1] := ORD({R[param2]})
|
|
||||||
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;
|
|
||||||
Names: ARRAY 5, 16 OF CHAR;
|
|
||||||
|
|
||||||
|
|
||||||
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 19 OF CHAR;
|
|
||||||
n: INTEGER;
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
n := szWORD * 2 + 2;
|
|
||||||
str[n] := 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
|
|
||||||
Names[Types] := "TYPES";
|
|
||||||
Names[Strings] := "STRINGS";
|
|
||||||
Names[Global] := "GLOBAL";
|
|
||||||
Names[Heap] := "HEAP";
|
|
||||||
Names[Stack] := "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)
|
|
||||||
|opNOP: String("NOP")
|
|
||||||
|opXCHG: String("XCHG "); Reg2(param1, param2)
|
|
||||||
|opLDB: String("LDB "); Reg(param1 MOD 256); String(", ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("]")
|
|
||||||
|opLDH: String("LDH "); Reg(param1 MOD 256); String(", ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("]")
|
|
||||||
|opLDW: String("LDW "); Reg(param1 MOD 256); String(", ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("]")
|
|
||||||
|opLDD: String("LDD "); Reg(param1 MOD 256); String(", ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("]")
|
|
||||||
|opPUSH: String("PUSH "); Reg(param1)
|
|
||||||
|opPUSHC: String("PUSH "); Hex(param1)
|
|
||||||
|opLLA: String("LLA "); RegL(param1, 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)
|
|
||||||
|opSTB: String("STB ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("], "); Reg(param1 MOD 256)
|
|
||||||
|opSTH: String("STH ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("], "); Reg(param1 MOD 256)
|
|
||||||
|opSTW: String("STW ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("], "); Reg(param1 MOD 256)
|
|
||||||
|opSTD: String("STD ["); Reg(param1 DIV 256); String(" + "); Hex(param2); String("], "); Reg(param1 MOD 256)
|
|
||||||
|opSTBC: String("STB ["); Reg(param1); String("], "); Hex(param2)
|
|
||||||
|opSTHC: String("STH ["); Reg(param1); String("], "); Hex(param2)
|
|
||||||
|opSTWC: String("STW ["); Reg(param1); String("], "); Hex(param2)
|
|
||||||
|opSTDC: String("STD ["); Reg(param1); String("], "); Hex(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)
|
|
||||||
|opLEA: String("LEA "); Reg(param1 MOD 256); String(", "); String(Names[param1 DIV 256]); String(" + "); Hex(param2)
|
|
||||||
|opADDRC: String("ADD "); Reg(param1 MOD 256); String(", "); Reg(param1 DIV 256); String(", "); Hex(param2)
|
|
||||||
|opLABEL: String("L"); Hex(param1); String(":")
|
|
||||||
|opSYSCALL: String("SYSCALL "); Reg(param1)
|
|
||||||
|opCMP: String("CMP "); Reg2(param1, param2)
|
|
||||||
|opCMPC: String("CMP "); RegC(param1, param2)
|
|
||||||
|opJEQ: String("JEQ L"); Hex(param1)
|
|
||||||
|opJNE: String("JNE L"); Hex(param1)
|
|
||||||
|opJLT: String("JLT L"); Hex(param1)
|
|
||||||
|opJLE: String("JLE L"); Hex(param1)
|
|
||||||
|opJGT: String("JGT L"); Hex(param1)
|
|
||||||
|opJGE: String("JGE L"); Hex(param1)
|
|
||||||
|opSEQ: String("SEQ "); Reg(param1)
|
|
||||||
|opSNE: String("SNE "); Reg(param1)
|
|
||||||
|opSLT: String("SLT "); Reg(param1)
|
|
||||||
|opSLE: String("SLE "); Reg(param1)
|
|
||||||
|opSGT: String("SGT "); Reg(param1)
|
|
||||||
|opSGE: String("SGE "); Reg(param1)
|
|
||||||
|opJBT: String("JBT L"); Hex(param1)
|
|
||||||
|opBIT: String("BIT "); Reg2(param1, param2)
|
|
||||||
END;
|
|
||||||
Ln;
|
|
||||||
cmd := cmd.next
|
|
||||||
END;
|
|
||||||
|
|
||||||
String("TYPES:");
|
|
||||||
ptr := Sections[Types];
|
|
||||||
FOR i := 0 TO t_count - 1 DO
|
|
||||||
IF i MOD 4 = 0 THEN
|
|
||||||
Ln; String("WORD ")
|
|
||||||
ELSE
|
|
||||||
String(", ")
|
|
||||||
END;
|
|
||||||
SYSTEM.GET(ptr, t); INC(ptr, szWORD);
|
|
||||||
Hex(t)
|
|
||||||
END;
|
|
||||||
Ln;
|
|
||||||
|
|
||||||
String("STRINGS:");
|
|
||||||
ptr := Sections[Strings];
|
|
||||||
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.GET(adr, op);
|
|
||||||
SYSTEM.GET(adr + szWORD, param1);
|
|
||||||
SYSTEM.GET(adr + szWORD * 2, 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 (3 * szWORD) = 0);
|
|
||||||
offStrings := descr[1];
|
|
||||||
ASSERT(offStrings < fsize - DescrSize);
|
|
||||||
ASSERT(offStrings > 0);
|
|
||||||
ASSERT(offStrings MOD szWORD = 0);
|
|
||||||
ASSERT(offStrings > offTypes);
|
|
||||||
GlobalSize := descr[2];
|
|
||||||
ASSERT(GlobalSize > 0);
|
|
||||||
HeapStackSize := descr[3];
|
|
||||||
ASSERT(HeapStackSize > 0);
|
|
||||||
|
|
||||||
Sections[Types] := API._NEW(offStrings - offTypes);
|
|
||||||
ASSERT(Sections[Types] # 0);
|
|
||||||
SYSTEM.MOVE(file + offTypes, Sections[Types], offStrings - offTypes);
|
|
||||||
|
|
||||||
Sections[Strings] := API._NEW(fsize - offStrings - DescrSize);
|
|
||||||
ASSERT(Sections[Strings] # 0);
|
|
||||||
SYSTEM.MOVE(file + offStrings, Sections[Strings], fsize - offStrings - DescrSize);
|
|
||||||
|
|
||||||
Sections[Global] := API._NEW(GlobalSize * szWORD);
|
|
||||||
ASSERT(Sections[Global] # 0);
|
|
||||||
|
|
||||||
Sections[Heap] := API._NEW(HeapStackSize * szWORD);
|
|
||||||
ASSERT(Sections[Heap] # 0);
|
|
||||||
|
|
||||||
Sections[Stack] := Sections[Heap] + HeapStackSize * szWORD - szWORD*8;
|
|
||||||
|
|
||||||
n := offTypes DIV (3 * szWORD);
|
|
||||||
|
|
||||||
first := GetCommand(file + offTypes - n * (3 * szWORD));
|
|
||||||
first.prev := NIL;
|
|
||||||
last := first;
|
|
||||||
DEC(n);
|
|
||||||
WHILE n > 0 DO
|
|
||||||
cmd := GetCommand(file + offTypes - n * (3 * szWORD));
|
|
||||||
IF cmd.op = opLABEL THEN
|
|
||||||
Labels[cmd.param1] := cmd
|
|
||||||
END;
|
|
||||||
last.next := cmd;
|
|
||||||
cmd.prev := last;
|
|
||||||
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 szWORD, fsize - offStrings - DescrSize, GlobalSize, HeapStackSize)
|
|
||||||
END
|
|
||||||
ELSIF param = "-run" THEN
|
|
||||||
exec(Labels, first, last, Sections)
|
|
||||||
END
|
|
||||||
ELSE
|
|
||||||
Out.String("file not found"); Out.Ln
|
|
||||||
END
|
|
||||||
END main;
|
|
||||||
|
|
||||||
|
|
||||||
BEGIN
|
|
||||||
main
|
|
||||||
END RVMxI.
|
|
@ -1,270 +0,0 @@
|
|||||||
|
|
||||||
Экспериментальная 32/64-битная виртуальная машина RVMxI
|
|
||||||
---------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Использование
|
|
||||||
|
|
||||||
Скомпилировать исполнитель/дизассемблер в .\tools\RVMxI.ob07
|
|
||||||
для Windows32/64 Console или Linux32/64:
|
|
||||||
|
|
||||||
Compiler.exe .\tools\RVMxI.ob07 win32con -nochk a -out RVMxI.exe
|
|
||||||
Compiler.exe .\tools\RVMxI.ob07 win64con -nochk a -out RVMxI.exe
|
|
||||||
Compiler ./tools/RVMxI.ob07 linux32exe -nochk a -out RVMxI
|
|
||||||
Compiler ./tools/RVMxI.ob07 linux64exe -nochk a -out RVMxI
|
|
||||||
|
|
||||||
Будет создан файл "RVMxI.exe" и/или "RVMxI".
|
|
||||||
|
|
||||||
Компилировать программу в байт-код RVMxI:
|
|
||||||
|
|
||||||
Compiler.exe program.ob07 rvm32i [-ram size] [-def host_linux]
|
|
||||||
Compiler.exe program.ob07 rvm64i [-ram size] [-def host_linux]
|
|
||||||
-ram size -- установить размер оперативной памяти для программы в килобайтах 32768..262144
|
|
||||||
(32..256 Мбайт), по умолчанию 32768 (32 Мбайт)
|
|
||||||
-def host_linux -- если байт-код будет исполняться на Linux (по умолчанию -- Windows)
|
|
||||||
|
|
||||||
Будет создан файл "program.bin".
|
|
||||||
|
|
||||||
Выпонить программу:
|
|
||||||
|
|
||||||
RVMxI.exe program.bin -run <параметры>
|
|
||||||
|
|
||||||
Дизассемблировать программу:
|
|
||||||
|
|
||||||
RVMxI.exe program.bin -dis program.txt
|
|
||||||
|
|
||||||
Будет создан файл "program.txt".
|
|
||||||
---------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Архитектура
|
|
||||||
|
|
||||||
Регистры
|
|
||||||
|
|
||||||
Не меньше пяти 32/64-битных регистров:
|
|
||||||
|
|
||||||
R0, R1, R2 регистры общего назначения
|
|
||||||
BP(R3) указатель кадра стэка
|
|
||||||
SP(R4) указатель стэка (растет вниз)
|
|
||||||
|
|
||||||
R5, R6... регистры общего назначения (опционально)
|
|
||||||
|
|
||||||
Регистра связи нет (адрес возврата передается через стэк),
|
|
||||||
регистр-счетчик команд (PC) -- скрытый, регистр флагов -- скрытый.
|
|
||||||
|
|
||||||
Нет вещественных регистров, операции с плавающей точкой (single (32-бит) или double (64-бит))
|
|
||||||
эмулируются.
|
|
||||||
|
|
||||||
Формат кадра стэка
|
|
||||||
|
|
||||||
Стэк:
|
|
||||||
|
|
||||||
меньше <- |лок. переменные|старый BP|адрес возврата|парам1|парам2|...|парамN| -> больше
|
|
||||||
|
|
||||||
(* 32 бита *)
|
|
||||||
адрес(парам1) = BP + 8
|
|
||||||
адрес(парам2) = BP + 12
|
|
||||||
...
|
|
||||||
|
|
||||||
(* 64 бита *)
|
|
||||||
адрес(парам1) = BP + 16
|
|
||||||
адрес(парам2) = BP + 24
|
|
||||||
...
|
|
||||||
|
|
||||||
Параметры передаются через стэк справа налево (как cdecl), результат передается через R0,
|
|
||||||
вызывающая процедура очищает стэк (как cdecl).
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Формат "исполняемого" файла
|
|
||||||
|
|
||||||
RECORD
|
|
||||||
|
|
||||||
Text: ARRAY i OF RECORD opcode, param1, param2: INTEGER END; (* байт-код *)
|
|
||||||
Types: ARRAY t OF INTEGER; (* таблица типов-записей *)
|
|
||||||
Strings: ARRAY s OF BYTE; (* строковые литералы *)
|
|
||||||
offTypes: INTEGER; (* смещение таблицы типов-записей от начала файла (в байтах) *)
|
|
||||||
offStrings: INTEGER; (* смещение строковых литералов от начала файла (в байтах) *)
|
|
||||||
GlobalSize: INTEGER; (* размер глобальных переменных (в словах; слово = 4 байта) *)
|
|
||||||
HeapStackSize: INTEGER; (* размер области кучи/стэка (в словах; слово = 4 байта) *)
|
|
||||||
Reserved: ARRAY 8 OF INTEGER (* зарезервировано *)
|
|
||||||
|
|
||||||
END
|
|
||||||
|
|
||||||
Где:
|
|
||||||
|
|
||||||
INTEGER = INT32/INT64
|
|
||||||
i = offTypes DIV (3 * sizeof(INTEGER));
|
|
||||||
t = (offStrings - offTypes) DIV sizeof(INTEGER)
|
|
||||||
s = FILE_SIZE - offStrings - 12 * sizeof(INTEGER)
|
|
||||||
---------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Система команд
|
|
||||||
|
|
||||||
мнемоника опкод парам1 парам2 действие
|
|
||||||
|
|
||||||
STOP 0 0 0 остановить программу
|
|
||||||
RET 1 0 0 возврат из процедуры (pop PC)
|
|
||||||
ENTER imm 2 imm 0 push BP; BP := SP; WHILE imm > 0 DO push 0; DEC(imm) END
|
|
||||||
NEG Rn 3 n 0 Rn := -Rn
|
|
||||||
NOT Rn 4 n 0 Rn := ORD(-BITS(Rn))
|
|
||||||
NOP 5 0 0 нет операции
|
|
||||||
XCHG Rn, Rm 6 n m temp := Rn; Rn := Rm; Rm := temp
|
|
||||||
LDB Rn, [Rm + imm] 7 m*256 + n imm Rn := UInt8Ptr(Rm + imm)^
|
|
||||||
LDH Rn, [Rm + imm] 8 m*256 + n imm Rn := UInt16Ptr(Rm + imm)^
|
|
||||||
LDW Rn, [Rm + imm] 9 m*256 + n imm Rn := UInt32Ptr(Rm + imm)^
|
|
||||||
* PUSH Rn 10 n 0 DEC(SP, 4); UInt32Ptr(SP)^ := Rn
|
|
||||||
* PUSH imm 11 imm 0 DEC(SP, 4); UInt32Ptr(SP)^ := imm
|
|
||||||
* POP Rn 12 n 0 Rn := UInt32Ptr(SP)^; INC(SP, 4)
|
|
||||||
** PUSH Rn 10 n 0 DEC(SP, 8); UInt64Ptr(SP)^ := Rn
|
|
||||||
** PUSH imm 11 imm 0 DEC(SP, 8); UInt64Ptr(SP)^ := imm
|
|
||||||
** POP Rn 12 n 0 Rn := UInt64Ptr(SP)^; INC(SP, 8)
|
|
||||||
L#hex: 13 hex 0 метка:
|
|
||||||
LEA Rn, TYPES + imm 14 n + 000H imm Rn := imm + address(TYPES)
|
|
||||||
LEA Rn, STRINGS + imm 14 n + 100H imm Rn := imm + address(STRINGS)
|
|
||||||
LEA Rn, GLOBAL + imm 14 n + 200H imm Rn := imm + address(GLOBAL)
|
|
||||||
LEA Rn, HEAP + imm 14 n + 300H imm Rn := imm + address(HEAP)
|
|
||||||
LEA Rn, STACK + imm 14 n + 400H imm Rn := imm + address(STACK)
|
|
||||||
LLA Rn, L#hex 15 n hex Rn := address(L#hex)
|
|
||||||
** LDD Rn, [Rm + imm] 16 m*256 + n imm Rn := UInt64Ptr(Rm + imm)^
|
|
||||||
|
|
||||||
JMP L#hex 19 hex 0 goto L#hex
|
|
||||||
CALL L#hex 20 hex 0 push PC; goto L#hex
|
|
||||||
CALL Rn 21 n 0 push PC; goto Rn
|
|
||||||
MOV Rn, Rm 22 n m Rn := Rm
|
|
||||||
MOV Rn, imm 23 n imm Rn := imm
|
|
||||||
MUL Rn, Rm 24 n m Rn := Rn * Rm
|
|
||||||
MUL Rn, imm 25 n imm Rn := Rm * imm
|
|
||||||
ADD Rn, Rm 26 n m Rn := Rn + Rm
|
|
||||||
ADD Rn, imm 27 n imm Rn := Rn + imm
|
|
||||||
SUB Rn, Rm 28 n m Rn := Rn - Rm
|
|
||||||
SUB Rn, imm 29 n imm Rn := Rn - imm
|
|
||||||
DIV Rn, Rm 30 n m Rn := Rn DIV Rm
|
|
||||||
DIV Rn, imm 31 n imm Rn := Rn DIV imm
|
|
||||||
MOD Rn, Rm 32 n m Rn := Rn MOD Rm
|
|
||||||
MOD Rn, imm 33 n imm Rn := Rn MOD imm
|
|
||||||
STB [Rn + imm], Rm 34 n*256 + m imm UInt8Ptr(Rn + imm)^ := Rm MOD 256
|
|
||||||
STB [Rn], imm 35 n imm UInt8Ptr(Rn)^ := imm MOD 256
|
|
||||||
STH [Rn + imm], Rm 36 n*256 + m imm UInt16Ptr(Rn + imm)^ := Rm MOD 65536
|
|
||||||
STH [Rn], imm 37 n imm UInt16Ptr(Rn)^ := imm MOD 65536
|
|
||||||
* STW [Rn + imm], Rm 38 n*256 + m imm UInt32Ptr(Rn + imm)^ := Rm
|
|
||||||
* STW [Rn], imm 39 n imm UInt32Ptr(Rn)^ := imm
|
|
||||||
** STW [Rn + imm], Rm 38 n*256 + m imm UInt32Ptr(Rn + imm)^ := Rm MOD 100000000H
|
|
||||||
** STW [Rn], imm 39 n imm UInt32Ptr(Rn)^ := imm MOD 100000000H
|
|
||||||
** STD [Rn + imm], Rm 40 n*256 + m imm UInt64Ptr(Rn + imm)^ := Rm
|
|
||||||
** STD [Rn], imm 41 n imm UInt64Ptr(Rn)^ := imm
|
|
||||||
|
|
||||||
AND Rn, Rm 46 n m Rn := ORD(BITS(Rn) * BITS(Rm))
|
|
||||||
AND Rn, imm 47 n imm Rn := ORD(BITS(Rn) * BITS(imm))
|
|
||||||
OR Rn, Rm 48 n m Rn := ORD(BITS(Rn) + BITS(Rm))
|
|
||||||
OR Rn, imm 49 n imm Rn := ORD(BITS(Rn) + BITS(imm))
|
|
||||||
XOR Rn, Rm 50 n m Rn := ORD(BITS(Rn) / BITS(Rm))
|
|
||||||
XOR Rn, imm 51 n imm Rn := ORD(BITS(Rn) / BITS(imm))
|
|
||||||
ASR Rn, Rm 52 n m Rn := ASR(Rn, Rm)
|
|
||||||
ASR Rn, imm 53 n imm Rn := ASR(Rn, imm)
|
|
||||||
LSR Rn, Rm 54 n m Rn := LSR(Rn, Rm)
|
|
||||||
LSR Rn, imm 55 n imm Rn := LSR(Rn, imm)
|
|
||||||
LSL Rn, Rm 56 n m Rn := LSL(Rn, Rm)
|
|
||||||
LSL Rn, imm 57 n imm Rn := LSL(Rn, imm)
|
|
||||||
ROR Rn, Rm 58 n m Rn := ROR(Rn, Rm)
|
|
||||||
ROR Rn, imm 59 n imm Rn := ROR(Rn, imm)
|
|
||||||
|
|
||||||
CMP Rn, Rm 64 n m сравнить Rn и Rm
|
|
||||||
CMP Rn, imm 65 n imm сравнить Rn и imm
|
|
||||||
BIT Rn, Rm 66 n m Rn := ORD({Rm})
|
|
||||||
SYSCALL Rn 67 n 0 системный вызов; Rn содержит адрес параметров
|
|
||||||
JBT L#hex 68 hex 0 перейти на метку L#hex, если "ниже"
|
|
||||||
ADD Rn, Rm, imm 69 m*256 + n imm Rn := Rm + imm
|
|
||||||
JEQ L#hex 70 hex 0 перейти на метку L#hex, если "равно"
|
|
||||||
JNE L#hex 71 hex 0 перейти на метку L#hex, если "не равно"
|
|
||||||
JLT L#hex 72 hex 0 перейти на метку L#hex, если "меньше"
|
|
||||||
JGE L#hex 73 hex 0 перейти на метку L#hex, если "не меньше"
|
|
||||||
JGT L#hex 74 hex 0 перейти на метку L#hex, если "больше"
|
|
||||||
JLE L#hex 75 hex 0 перейти на метку L#hex, если "не больше"
|
|
||||||
SEQ Rn 76 n 0 если "равно": Rn := 1, иначе Rn := 0
|
|
||||||
SNE Rn 77 n 0 если "не равно": Rn := 1, иначе Rn := 0
|
|
||||||
SLT Rn 78 n 0 если "меньше": Rn := 1, иначе Rn := 0
|
|
||||||
SGE Rn 79 n 0 если "не меньше": Rn := 1, иначе Rn := 0
|
|
||||||
SGT Rn 80 n 0 если "больше": Rn := 1, иначе Rn := 0
|
|
||||||
SLE Rn 81 n 0 если "не больше": Rn := 1, иначе Rn := 0
|
|
||||||
|
|
||||||
Команда CMP сохраняет результат сравнения в скрытом регистре, этот результат используется
|
|
||||||
в командах перехода по условию (JEQ, JNE, JLT, JGE, JGT, JLE, JBT) а также в командах
|
|
||||||
установки регистра по условию (SEQ, SNE, SLT, SGE, SGT, SLE).
|
|
||||||
|
|
||||||
* Команда для 32-битной виртуальной машины
|
|
||||||
** Команда для 64-битной виртуальной машины
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Общая структура программы
|
|
||||||
|
|
||||||
CODE: (* машинный код *)
|
|
||||||
LEA SP, STACK + 0x00000000 (* точка входа; инициализация регистра SP *)
|
|
||||||
...
|
|
||||||
STOP (* конец программы *)
|
|
||||||
|
|
||||||
TYPES: (* таблица типов-записей *)
|
|
||||||
WORD 0x00000000, 0x00000000, 0x00000000, 0x00000000
|
|
||||||
WORD 0x00000002, 0x00000002, 0x00000002, 0x00000002
|
|
||||||
WORD 0x00000000, 0x00000006, 0x00000000, 0x00000000
|
|
||||||
WORD 0x00000002, 0x00000000, 0x0000000D, 0x0000000E
|
|
||||||
WORD 0x0000000C, 0x0000000E, 0x0000000C, 0x00000000
|
|
||||||
WORD 0x00000000, 0x0000000C, 0x0000000C, 0x00000016
|
|
||||||
WORD 0x00000000, 0x0000000C, 0x0000000C, 0x0000000C
|
|
||||||
WORD 0x00000000, 0x00000000, 0x0000000C, 0x0000000C
|
|
||||||
WORD 0x0000000C, 0x0000000C, 0x0000000C, 0x0000000C
|
|
||||||
WORD 0x0000000C, 0x0000000C, 0x00000000, 0x00000000
|
|
||||||
WORD 0x0000000C, 0x0000000C, 0x0000000C, 0x00000000
|
|
||||||
WORD 0x00000000, 0x0000000C, 0x0000002D, 0x0000002D
|
|
||||||
WORD 0x0000002D, 0x00000030, 0x00000030, 0x00000030
|
|
||||||
WORD 0x00000030, 0x0000002D, 0x00000000, 0x00000000
|
|
||||||
WORD 0x0000000A, 0x00000000, 0x00000002, 0x00000000
|
|
||||||
WORD 0x00000000, 0x00000000, 0x00000000, 0x00000000
|
|
||||||
WORD 0x00000000, 0x00000000, 0x00000000, 0x00000000
|
|
||||||
WORD 0x00000000, 0x0000000C, 0x0000000C, 0x00000000
|
|
||||||
WORD 0x00000000, 0x0000000C, 0x00000049, 0x00000049
|
|
||||||
WORD 0x00000049, 0x0000004C, 0x0000004C, 0x0000004C
|
|
||||||
WORD 0x00000049, 0x0000000C, 0x00000000, 0x0000000C
|
|
||||||
WORD 0x00000053, 0x00000053, 0x00000053, 0x00000053
|
|
||||||
WORD 0x0000000C, 0x00000000, 0x00000000, 0x00000000
|
|
||||||
WORD 0x00000006, 0x0000000C
|
|
||||||
|
|
||||||
STRINGS: (* строковые литералы *)
|
|
||||||
BYTE 0x46, 0x50, 0x55, 0x00, 0x54, 0x72, 0x61, 0x70
|
|
||||||
BYTE 0x00, 0x0D, 0x0A, 0x00, 0x61, 0x73, 0x73, 0x65
|
|
||||||
BYTE 0x72, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x66, 0x61
|
|
||||||
BYTE 0x69, 0x6C, 0x75, 0x72, 0x65, 0x00, 0x4E, 0x49
|
|
||||||
BYTE 0x4C, 0x20, 0x64, 0x65, 0x72, 0x65, 0x66, 0x65
|
|
||||||
BYTE 0x72, 0x65, 0x6E, 0x63, 0x65, 0x00, 0x62, 0x61
|
|
||||||
BYTE 0x64, 0x20, 0x64, 0x69, 0x76, 0x69, 0x73, 0x6F
|
|
||||||
BYTE 0x72, 0x00, 0x4E, 0x49, 0x4C, 0x20, 0x70, 0x72
|
|
||||||
BYTE 0x6F, 0x63, 0x65, 0x64, 0x75, 0x72, 0x65, 0x20
|
|
||||||
BYTE 0x63, 0x61, 0x6C, 0x6C, 0x00, 0x74, 0x79, 0x70
|
|
||||||
BYTE 0x65, 0x20, 0x67, 0x75, 0x61, 0x72, 0x64, 0x20
|
|
||||||
BYTE 0x65, 0x72, 0x72, 0x6F, 0x72, 0x00, 0x69, 0x6E
|
|
||||||
BYTE 0x64, 0x65, 0x78, 0x20, 0x6F, 0x75, 0x74, 0x20
|
|
||||||
BYTE 0x6F, 0x66, 0x20, 0x72, 0x61, 0x6E, 0x67, 0x65
|
|
||||||
BYTE 0x00, 0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64
|
|
||||||
BYTE 0x20, 0x43, 0x41, 0x53, 0x45, 0x00, 0x61, 0x72
|
|
||||||
BYTE 0x72, 0x61, 0x79, 0x20, 0x61, 0x73, 0x73, 0x69
|
|
||||||
BYTE 0x67, 0x6E, 0x6D, 0x65, 0x6E, 0x74, 0x20, 0x65
|
|
||||||
BYTE 0x72, 0x72, 0x6F, 0x72, 0x00, 0x43, 0x48, 0x52
|
|
||||||
BYTE 0x20, 0x6F, 0x75, 0x74, 0x20, 0x6F, 0x66, 0x20
|
|
||||||
BYTE 0x72, 0x61, 0x6E, 0x67, 0x65, 0x00, 0x57, 0x43
|
|
||||||
BYTE 0x48, 0x52, 0x20, 0x6F, 0x75, 0x74, 0x20, 0x6F
|
|
||||||
BYTE 0x66, 0x20, 0x72, 0x61, 0x6E, 0x67, 0x65, 0x00
|
|
||||||
BYTE 0x42, 0x59, 0x54, 0x45, 0x20, 0x6F, 0x75, 0x74
|
|
||||||
BYTE 0x20, 0x6F, 0x66, 0x20, 0x72, 0x61, 0x6E, 0x67
|
|
||||||
BYTE 0x65, 0x00, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x20
|
|
||||||
BYTE 0x28, 0x00, 0x29, 0x3A, 0x20, 0x00, 0x6D, 0x6F
|
|
||||||
BYTE 0x64, 0x75, 0x6C, 0x65, 0x3A, 0x20, 0x00, 0x6C
|
|
||||||
BYTE 0x69, 0x6E, 0x65, 0x3A, 0x20, 0x00, 0x52, 0x54
|
|
||||||
BYTE 0x4C, 0x00, 0x54, 0x65, 0x73, 0x74, 0x00, 0x00
|
|
||||||
|
|
||||||
GLOBAL:
|
|
||||||
WORDS 0x00000004 (* размер глобальных переменных в словах (слово = 4 или 8 байт) *)
|
|
||||||
|
|
||||||
HEAP:
|
|
||||||
WORDS 0x007FFFBF (* размер области кучи/стэка в словах (слово = 4 или 8 байт) *)
|
|
||||||
STACK:
|
|
||||||
WORDS 8 (* зарезервировано *)
|
|
||||||
---------------------------------------------------------------------------------------------------
|
|
Loading…
Reference in New Issue
Block a user