home *** CD-ROM | disk | FTP | other *** search
- (* ----------------------------------------------------------------------- *)
- (* DC.PAS *)
- (* Simulation eines einfachen didaktischen Computers "DC" *)
- (* Autor: Zbigniew Szkaradnik - Vers. 1.1 fuer DEC LSI-11 25-April-85 *)
- (* - Vers. 1.2 fuer JOYCE 10-Febr.-87 *)
- (* Modifikation und Implementierung (Vers. 1.3) von Michael Ceol fuer *)
- (* PC-/MS-DOS (Turbo Pascal), CP/M (Turbo Pascal), Atari ST (Pascal ST +) *)
- (* Sept. 87. Kurzanleitung siehe Datei "DC.HLP". Viel Spass.... *)
- PROGRAM Didactic_Computer;
- (*$C-*) (* nur fuer Turbo Pascal *)
- CONST
- none = -1; null = 0; addr_start = 5; op_start = 1;
- addr_end = 10; op_end = 4; mnem_size = 3; word_size = 10;
- max_length = 30; mem_size = 63; winymin = 18; winymax = 24;
- instructions = 15; screen_lines = 25; sign_val = 512; sign_bit = 1;
- zero = '0000000000';
-
- TYPE
- dc_word = STRING[word_size]; op_str = STRING[op_end];
- mnem_str = STRING[mnem_size]; one_line = STRING[80];
- lines = STRING[max_length]; string2 = STRING[2];
- errors = (illcmd, illadd, illlab, illcod, illarg, illcon,
- loops, ovf, illfil, illhlp, break);
- mem_area = ARRAY [0..mem_size] OF dc_word;
-
- VAR
- end_of_program, out_cycle: BOOLEAN; inp_file: TEXT; esc: CHAR;
- command : (cl, instr, regr, step, run, go, tim, bpt, Int, ldf,
- other, hlp, view, ends);
- mode : (waiting, nowait, delaying);
- err : errors; memory : mem_area; Line : lines;
- item : ARRAY[1..3] OF lines;
- window : ARRAY[winymin..winymax] OF lines;
- mnems : ARRAY[0..instructions] OF mnem_str;
- op_codes: ARRAY[0..instructions] OF op_str;
- ar, pc, ac, dr, ir, sp: dc_word;
- address, counter, int_addr, break_addr, s_ptr,
- time, blink_num, blink_time, row, items, mempage, op_code: INTEGER;
- ve, he, ce, dle, dre, ule, ure, uhe, dhe, rve, lve, se, vd, led_on, dpc,
- led_off, wr, rd, sp2, ipc, pl, mi, sp1, u_arrow, d_arrow, bar, sl: string2;
- (* ----------------------------------------------------------------------- *)
- (*$I DCTURMS.PAS *) (* bzw. ein anderes System-Modul, z.B. DCPSPTOS.PAS *)
- (*$I DCKONV.PAS *)
- (*$I DCOUT.PAS *)
- (*$I DCTRAN.PAS *)
- (*$I DCEXE.PAS *)
- (* ----------------------------------------------------------------------- *)
- PROCEDURE Init;
- VAR i: INTEGER; temp: dc_word;
- BEGIN
- esc := Chr(27); RevOff; CrsOff; ClrScr; Init_Sys;
- pl := '+'; mi := '-'; sp1 := ' '; sp2 := ' ';
- ipc := '+1'; dpc := '-1'; rd := 'rd'; wr := 'wr'; mode := nowait;
- mnems[0] := 'LDA'; mnems[1] := 'STA'; mnems[2] := 'ADD';
- mnems[3] := 'SUB'; mnems[4] := 'JMP'; mnems[5] := 'JMS';
- mnems[6] := 'JSR'; mnems[7] := 'RTN';
- FOR i := 8 TO 15 DO mnems[i] := '???';
- temp := zero; sp := zero;
- FOR i := 0 TO instructions DO BEGIN
- Int_to_Bin(i,op_start,op_end,temp);
- op_codes[i] := Copy(temp,op_start,op_end);
- END;
- Print_Display; Print_Computer; Clear;
- GotoXY(2,25); revon; Write(' <H> fuer Information'); RevOff;
- row := winymin; GotoXY(1,row);
- END;
- (* ----------------------------------------------------------------------- *)
- PROCEDURE Load_Constant (address: INTEGER); (* Konstante in Speicher laden *)
- VAR value, err: INTEGER;
- BEGIN
- Val(item[3],value,err);
- IF (err = null)
- AND (value > (-1 * Succ(sign_val))) AND (value < sign_val) THEN BEGIN
- Load_Int(value,memory[address]); print_cell(address);
- END
- ELSE Error(illcon); (* Illegal constant *)
- END;
-
- PROCEDURE Load_Instruction (address: INTEGER; op_code: op_str);
- VAR arg, i: INTEGER; Mem: dc_word; (* Befehl in Speicher laden *)
- BEGIN
- IF item[2] = 'RTN' THEN item[3] := '0';
- Val(item[3],arg,i); Mem := zero;
- IF (i = null) AND Legal(arg) THEN BEGIN
- Int_to_Bin(arg,addr_start,addr_end,Mem);
- FOR i := op_start TO op_end DO Mem[i] := op_code[i];
- memory[address] := Mem; print_cell(address);
- END
- ELSE Error(illarg); (* Illegal argument *)
- END;
-
- PROCEDURE Load_PC;
- VAR temp: dc_word; value, err: INTEGER;
- BEGIN
- Val(item[2],value,err); Int_to_Bin(value,1,word_size,temp);
- IF (err = null) AND Legal(value) THEN
- IF item[1] = 'PC' THEN BEGIN pc := temp; counter := value; END
- ELSE Error(illcmd)
- ELSE Error(illadd); (* Illegal binary argument *)
- Display_Status;
- END;
- (* ----------------------------------------------------------------------- *)
- PROCEDURE Interpret_Instruction; (* Befehl in Maschinencode uebersetzen *)
- VAR i, address: INTEGER;
- BEGIN
- Val(item[1],address,i);
- IF (i = null) AND Legal(address) THEN BEGIN
- i := -1;
- REPEAT
- i := Succ(i);
- UNTIL (item[2] = mnems[i]) OR (i = instructions);
- IF item[2] = mnems[i] THEN Load_Instruction(address,op_codes[i])
- ELSE IF item[2] = 'DEF' THEN Load_Constant(address)
- ELSE Error(illcod); (* Illegal code *)
- END
- ELSE Error(illlab); (* Illegal label *)
- END;
- (* ----------------------------------------------------------------------- *)
- PROCEDURE Read_Line; (* Kommando-Zeile einlesen *)
- VAR st: lines; i: INTEGER;
- BEGIN
- Invert_Cell(counter); CrsOn; GotoXY(1,row); Bell;
- Write('> '); ReadLn(Line); st := Line;
- FOR i := 1 TO max_length - Length(Line) DO st := Concat(st,' ');
- CrsOff; w_write(st); Erase_Error; print_cell(counter);
- END;
- (* ----------------------------------------------------------------------- *)
- PROCEDURE Separate_Tokens; (* Bestandteile des Kommandos aufloesen *)
- VAR i: INTEGER;
-
- FUNCTION empty (VAR st: lines): BOOLEAN;
- VAR i: INTEGER; temp: BOOLEAN;
- BEGIN
- temp := FALSE; i := 0;
- REPEAT
- i := Succ(i);
- IF i <= Length(st) THEN IF st[i] <> ' ' THEN temp := TRUE;
- UNTIL temp OR (i >= Length(st));
- empty := NOT(temp);
- END;
-
- BEGIN
- FOR i := 1 TO 3 DO item[i] := '';
- i := Pos(';',Line);
- IF i > 0 THEN Delete(Line,i,Length(Line)-i+1); (* Kommentar entfernen *)
- items := 0;
- IF empty(Line) THEN Line := '';
- IF Length(Line) > 0 THEN BEGIN
- Line := Concat(Line,' ');
- REPEAT
- items := Succ(items);
- WHILE Line[1] = ' ' DO Delete(Line,1,1);
- i := Pos(' ',Line); item[items] := Copy(Line,1,Pred(i));
- Delete(Line,1,Length(item[items]))
- UNTIL (items = 3) OR empty(Line);
- END;
- END;
- (* ----------------------------------------------------------------------- *)
- PROCEDURE Interpret_Line; (* Kommandozeile uebersetzen *)
- VAR st: lines; i, err: INTEGER;
- BEGIN
- To_Upper(Line); Separate_Tokens; st := item[1]; command := other;
- Val(item[1],i,err);
- IF items = 0 THEN command := step
- ELSE IF err = null THEN command := instr
- ELSE IF (items = 1) AND (Length(st) = 1) THEN
- CASE st[1] OF
- 'H': command := hlp; 'I': command := Int;
- 'B': command := bpt; 'C': command := cl;
- 'R': command := run; 'E': command := ends;
- 'W': command := tim; 'N': command := tim;
- 'D': command := tim;
- END
- ELSE IF (items = 2) AND (Length(st) = 1) THEN
- CASE st[1] OF
- 'B': command := bpt; 'I': command := Int; 'V': command := view;
- 'G': command := go; 'L': command := ldf;
- END
- ELSE IF (items = 2) AND (Length(st) = 2) THEN
- IF (st = 'AR') OR (st = 'PC')
- OR (st = 'AC') OR (st = 'DR') OR (st = 'IR') THEN command := regr
- END;
- (* ----------------------------------------------------------------------- *)
- PROCEDURE Set_Time; (* Pause bei schrittweiser Ausfuehrung festlegen *)
- VAR st: lines;
- BEGIN
- st := item[1];
- CASE st[1] OF
- 'N': mode := nowait; 'W': mode := waiting; 'D': mode := delaying;
- END;
- END;
- (* ----------------------------------------------------------------------- *)
- PROCEDURE View_Page;
- VAR address, err: INTEGER; ch: CHAR;
- BEGIN
- Val(item[2],address,err); IF err = null THEN Print_Mempage(address);
- GotoXY(2,25); revon; Write('Druecke eine Taste'); RevOff;
- ch := ReadKeyboard;
- END;
- (* ----------------------------------------------------------------------- *)
- PROCEDURE help;
- VAR counter, i: INTEGER; ch: CHAR; Str: lines;
- BEGIN
- IF Open_File('DC.HLP') THEN BEGIN
- counter := 0; ch := ' ';
- WHILE NOT Eof(inp_file) AND (ch <> esc) DO BEGIN
- counter := counter + 1; ReadLn(inp_file, Line); Str := Line;
- FOR i := 1 TO max_length - Length(Line) DO Str := Concat(Str, ' ');
- IF counter MOD 7 = 0 THEN BEGIN
- Write(Line);
- GotoXY (2,25); RevOn; Write('ESC: Ende WEITER: Taste'); RevOff;
- ch := ReadKeyboard; Erase_Error;
- IF ch = esc THEN
- BEGIN GotoXY(1,row); Write ('> '); w_write(Str); END;
- END
- ELSE BEGIN GotoXY(1,row); Write('> '); w_write(Str); END;
- END;
- END
- ELSE error(illhlp);
- END;
- (* ----------------------------------------------------------------------- *)
- PROCEDURE Load_File; FORWARD; (* Programm aus Datei laden *)
- (* ----------------------------------------------------------------------- *)
- PROCEDURE Execute_Command; (* Kommando ausfuehren *)
- BEGIN
- CASE command OF
- hlp : help; cl : Clear;
- tim : Set_Time; regr : Load_PC;
- instr: Interpret_Instruction; go : Go_From;
- bpt : breakpoint; Int : interrupt;
- ldf : Load_File; step : Single_Step;
- run : execute_program; view : View_Page;
- other: Error(illcmd); ends : Exit_DC;
- END;
- END;
- (* ----------------------------------------------------------------------- *)
- PROCEDURE Load_File;
- BEGIN
- IF Pos('.',item[2]) = 0 THEN item[2] := Concat(item[2],'.DC');
- IF Open_File(item[2]) THEN
- WHILE NOT Eof(inp_file) DO BEGIN
- ReadLn(inp_file, Line); Interpret_Line; Execute_Command;
- END
- ELSE Error(illfil); (* Illegal filename *)
- END;
- (* ----------------------------------------------------------------------- *)
- BEGIN (* Didactic_Computer *)
- Init;
- REPEAT Read_Line; Interpret_Line; Execute_Command; UNTIL command = ends;
- END.