0,0 → 1,668 |
(* |
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. |