Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
4
Task/Execute-Computer-Zero/00-META.yaml
Normal file
4
Task/Execute-Computer-Zero/00-META.yaml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
category:
|
||||
- Compilers and Interpreters
|
||||
from: http://rosettacode.org/wiki/Execute_Computer/Zero
|
||||
14
Task/Execute-Computer-Zero/00-TASK.txt
Normal file
14
Task/Execute-Computer-Zero/00-TASK.txt
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{{implementation|Computer/zero Assembly}}
|
||||
{{omit from|Computer/zero Assembly}}
|
||||
|
||||
;Task:
|
||||
Create a [[Computer/zero Assembly]] emulator. You may consider [http://edmundgriffiths.com/czero.html this webpage] as a reference implementation. Output the results of the sample programs "2+2" and "7*8" found there.
|
||||
|
||||
:* The virtual machine "bytecode" needs to be able to modify itself (or at least act as though it can) while the virtual machine is running, to be consistent with the reference implementation.
|
||||
:* For output, it is sufficient to have the implementation of the <code>STP</code> opcode return the accumulator to your actual language, and then use your standard printing routines to output it.
|
||||
|
||||
;Bonus Points: Run all 5 sample programs at the aforementioned website and output their results.
|
||||
|
||||
|
||||
<br><br>
|
||||
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
BEGIN # execute some ComputerZero programs #
|
||||
# instructions #
|
||||
INT nop = 0, lda = 1, sta = 2, add = 3, sub = 4, brz = 5, jmp = 6, stp = 7;
|
||||
PROC instr = ( INT op, v )INT: ( 32 * op ) + v;
|
||||
OP NOP = ( INT v )INT: instr( nop, v );
|
||||
OP LDA = ( INT v )INT: instr( lda, v );
|
||||
OP STA = ( INT v )INT: instr( sta, v );
|
||||
OP ADD = ( INT v )INT: instr( add, v );
|
||||
OP SUB = ( INT v )INT: instr( sub, v );
|
||||
OP BRZ = ( INT v )INT: instr( brz, v );
|
||||
OP JMP = ( INT v )INT: instr( jmp, v );
|
||||
OP STP = ( INT v )INT: instr( stp, v );
|
||||
# executes the program named name #
|
||||
PROC execute = ( STRING name, []INT program )VOID:
|
||||
BEGIN
|
||||
[ 0 : 31 ]INT m; # the computer 32 has bytes of memory #
|
||||
FOR i FROM LWB m TO UPB m DO m[ i ] := 0 OD;
|
||||
# "assemble" the program #
|
||||
INT m pos := -1;
|
||||
FOR i FROM LWB program TO UPB program DO
|
||||
m[ m pos +:= 1 ] := program[ i ]
|
||||
OD;
|
||||
# execute the program #
|
||||
BOOL running := TRUE;
|
||||
INT pc := 0;
|
||||
INT a := 0;
|
||||
WHILE running DO
|
||||
INT op := m[ pc ] OVER 32;
|
||||
INT operand := m[ pc ] MOD 32;
|
||||
pc +:= 1 MODAB 32;
|
||||
IF op = nop THEN SKIP
|
||||
ELIF op = lda THEN a := m[ operand ]
|
||||
ELIF op = sta THEN m[ operand ] := a
|
||||
ELIF op = add THEN a +:= m[ operand ] MODAB 256
|
||||
ELIF op = sub THEN a -:= m[ operand ] MODAB 256
|
||||
ELIF op = brz THEN IF a = 0 THEN pc := operand FI
|
||||
ELIF op = jmp THEN pc := operand
|
||||
ELSE # stp #
|
||||
running := FALSE;
|
||||
print( ( " " * ( 12 - ( ( UPB name - LWB name ) + 1 ) ) ) );
|
||||
print( ( name, ": ", whole( a, -3 ), newline ) )
|
||||
FI
|
||||
OD
|
||||
END # execute # ;
|
||||
# task test programs (from the Computer Zero website) #
|
||||
# the unary NOP, LDA, STA, etc. operators are used to construct the #
|
||||
# instructions; as parameterless operators aren't allowed, NOP and STP #
|
||||
# must have a dummy parameter #
|
||||
execute( "2+2", ( LDA 3, ADD 4, STP 0, 2, 2 )
|
||||
);
|
||||
execute( "7*8"
|
||||
, ( LDA 12, ADD 10, STA 12, LDA 11, SUB 13, STA 11, BRZ 8, JMP 0
|
||||
, LDA 12, STP 0, 8, 7, 0, 1
|
||||
)
|
||||
);
|
||||
execute( "fibonacci"
|
||||
, ( LDA 14, STA 15, ADD 13, STA 14, LDA 15, STA 13, LDA 16, SUB 17
|
||||
, BRZ 11, STA 16, JMP 0, LDA 14, STP 0, 1, 1, 0
|
||||
, 8, 1
|
||||
)
|
||||
);
|
||||
execute( "linkedList"
|
||||
, ( LDA 13, ADD 15, STA 5, ADD 16, STA 7, NOP 0, STA 14, NOP 0
|
||||
, BRZ 11, STA 15, JMP 0, LDA 14, STP 0, LDA 0, 0, 28
|
||||
, 1, 0, 0, 0, 6, 0, 2, 26
|
||||
, 5, 20, 3, 30, 1, 22, 4, 24
|
||||
)
|
||||
);
|
||||
execute( "prisoner"
|
||||
, ( NOP 0, NOP 0, STP 0, 0, LDA 3, SUB 29, BRZ 18, LDA 3
|
||||
, STA 29, BRZ 14, LDA 1, ADD 31, STA 1, JMP 2, LDA 0, ADD 31
|
||||
, STA 0, JMP 2, LDA 3, STA 29, LDA 1, ADD 30, ADD 3, STA 1
|
||||
, LDA 0, ADD 30, ADD 3, STA 0, JMP 2, 0, 1, 3
|
||||
)
|
||||
);
|
||||
# subtractions yielding negative results #
|
||||
execute( "0-255", ( LDA 3, SUB 4, STP 0, 0, 255 ) );
|
||||
execute( "0-1", ( LDA 3, SUB 4, STP 0, 0, 1 ) );
|
||||
# overflow on addition #
|
||||
execute( "1+255", ( LDA 3, ADD 4, STP 0, 1, 255 ) )
|
||||
END
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
0 FOR P = 1 TO 5: READ S$: PRINT S$" : ";: FOR MEM = 0 TO 31: ON LEN (S$) > 0 GOSUB 90:A = VAL (S$): GOSUB 2: NEXT MEM: GOSUB 7: PRINT A: NEXT P: END
|
||||
1 LET A = V: RETURN
|
||||
2 LET P$ = MID$ (P$,1,MEM) + CHR$ (A) + MID$ (P$,MEM + 2,31 - MEM): PRINT MID$ ("",1 ^ FRE (0));: RETURN
|
||||
3 LET A = A + V:A = A - 256 * (A > 255): RETURN
|
||||
4 LET A = A - V:A = A + 256 * (A < 0): RETURN
|
||||
5 IF A > 0 THEN RETURN
|
||||
6 LET PC = MEM: RETURN
|
||||
7 LET PC = 0
|
||||
8 LET A = 0
|
||||
9 FOR OP = 0 TO 7 STEP 0
|
||||
10 LET PC = PC + 1 - 32 * (PC = 32)
|
||||
20 LET I = ASC ( MID$ (P$,PC,1))
|
||||
30 LET OP = INT (I / 32)
|
||||
40 LET MEM = I - OP * 32
|
||||
50 LET V = ASC ( MID$ (P$,MEM + 1,1))
|
||||
60 ON OP GOSUB 1,2,3,4,5,6
|
||||
70 NEXT OP
|
||||
80 RETURN
|
||||
90 READ S$: RETURN
|
||||
100 DATA "2+2",35,100,224,2,2,
|
||||
200 DATA "7*8",44,106,76,43,141,75,168,192,44,224,8,7,0,1,
|
||||
300 DATA "FIBONACCI",46,79,109,78,47,77,48,145,171,80,192,46,224,1,1,0,8,1,
|
||||
400 DATA "LINKED LIST",45,111,69,112,71,0,78,0,171,79,192,46,224,32,0,28,1,0,0,0,6,0,2,26,5,20,3,30,1,22,4,24
|
||||
500 DATA "PRISONER",0,0,224,0,0,35,157,178,35,93,174,33,127,65,194,32,127,64,192,35,93,33,126,99,
|
||||
268
Task/Execute-Computer-Zero/Delphi/execute-computer-zero.delphi
Normal file
268
Task/Execute-Computer-Zero/Delphi/execute-computer-zero.delphi
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
{structure that holds name of program and code}
|
||||
|
||||
type TProgram = record
|
||||
Name, Code: string;
|
||||
end;
|
||||
|
||||
{List of programs}
|
||||
|
||||
var ProgList: array [0..4] of TProgram =(
|
||||
(Name: 'Two plus two'; Code: 'LDA 3 ADD 4 STP 2 2'),
|
||||
(Name: 'Seven times eight'; Code: 'LDA 12 ADD 10 STA 12 LDA 11 SUB 13 STA 11 BRZ 8 JMP 0 LDA 12 STP 8 7 0 1'),
|
||||
(Name: 'The Fibonacci sequence'; Code: 'LDA 14 STA 15 ADD 13 STA 14 LDA 15 STA 13 LDA 16 SUB 17 BRZ 11 STA 16 JMP 0 LDA 14 STP 1 1 0 8 1'),
|
||||
(Name: 'Linked list'; Code: 'LDA 13 ADD 15 STA 5 ADD 16 STA 7 NOP STA 14 NOP BRZ 11 STA 15 JMP 0 LDA 14 STP LDA 0 0 28 1 0 0 0 6 0 2 26 5 20 3 30 1 22 4 24'),
|
||||
(Name: 'Prisoner’s Dilemma'; Code: '0 0 STP NOP LDA 3 SUB 29 BRZ 18 LDA 3 STA 29 BRZ 14 LDA 1 ADD 31 STA 1 JMP 2 LDA 0 ADD 31 STA 0 JMP 2 LDA 3 STA 29 LDA 0 ADD 30 ADD 3 STA 0 LDA 1 ADD 30 ADD 3 STA 1 JMP 2 0 1 3')
|
||||
);
|
||||
|
||||
{Defines opcode function call}
|
||||
|
||||
type TOpProc = function(Opcode: byte): boolean;
|
||||
|
||||
{Defines argument type for opcode}
|
||||
|
||||
type TArgType = (atNone,atAddress,atMemory);
|
||||
|
||||
{Defines Opcode information}
|
||||
|
||||
type TOpcode = record
|
||||
OpCode: integer;
|
||||
ArgType: TArgType;
|
||||
Mnemonic: string[3];
|
||||
Proc: TOpProc;
|
||||
end;
|
||||
|
||||
{Simulated memory, program counter and accumulator}
|
||||
|
||||
var Memory: array [0..31] of byte;
|
||||
var ProgramCounter: integer;
|
||||
var Accumulator: byte;
|
||||
|
||||
{Routines to carry out actions of opcodes}
|
||||
|
||||
function DoNoOp(Operand: byte): boolean;
|
||||
{ ($00) = NOP - (no operation)}
|
||||
begin
|
||||
Inc(ProgramCounter);
|
||||
Result:=True;
|
||||
end;
|
||||
|
||||
|
||||
function DoLDA(Operand: byte): boolean;
|
||||
{ ($20) LDA - (load accumulator) - a := memory [xxxxx]}
|
||||
begin
|
||||
Accumulator:=Memory[Operand];
|
||||
Inc(ProgramCounter);
|
||||
Result:=True;
|
||||
end;
|
||||
|
||||
|
||||
function DoSTA(Operand: byte): boolean;
|
||||
{ ($40) STA - (store accumulator) - memory [xxxxx] := a}
|
||||
begin
|
||||
Memory[Operand]:=Accumulator;
|
||||
Inc(ProgramCounter);
|
||||
Result:=True;
|
||||
end;
|
||||
|
||||
|
||||
function DoADD(Operand: byte): boolean;
|
||||
{ ($60) ADD - (add) - a := a + memory [xxxxx]}
|
||||
begin
|
||||
Accumulator:=Accumulator + Memory[Operand];
|
||||
Inc(ProgramCounter);
|
||||
Result:=True;
|
||||
end;
|
||||
|
||||
|
||||
function DoSUB(Operand: byte): boolean;
|
||||
{ ($80) SUB - (subtract) - a := a – memory [xxxxx]}
|
||||
begin
|
||||
Accumulator:=Accumulator - Memory[Operand];
|
||||
Inc(ProgramCounter);
|
||||
Result:=True;
|
||||
end;
|
||||
|
||||
|
||||
function DoBRZ(Operand: byte): boolean;
|
||||
{ ($A0) BRZ - (branch on zero) - if a = 0 then goto xxxxx}
|
||||
begin
|
||||
if Accumulator=0 then ProgramCounter:=Operand
|
||||
else Inc(ProgramCounter);
|
||||
Result:=True;
|
||||
end;
|
||||
|
||||
|
||||
function DoJMP(Operand: byte): boolean;
|
||||
{ ($C0) JMP - (jump) - goto xxxxx}
|
||||
begin
|
||||
ProgramCounter:=Operand;
|
||||
Result:=True;
|
||||
end;
|
||||
|
||||
|
||||
function DoSTP(Operand: byte): boolean;
|
||||
{ ($E0) STP - (stop)}
|
||||
begin
|
||||
Result:=False;
|
||||
end;
|
||||
|
||||
{Table of opcodes}
|
||||
|
||||
var OpTable: array [0..7] of TOpcode= (
|
||||
(Opcode: $00; ArgType: atNone; Mnemonic: 'NOP'; Proc: DoNoOp),
|
||||
(Opcode: $20; ArgType: atMemory; Mnemonic: 'LDA'; Proc: DoLDA),
|
||||
(Opcode: $40; ArgType: atMemory; Mnemonic: 'STA'; Proc: DoSTA),
|
||||
(Opcode: $60; ArgType: atMemory; Mnemonic: 'ADD'; Proc: DoADD),
|
||||
(Opcode: $80; ArgType: atMemory; Mnemonic: 'SUB'; Proc: DoSUB),
|
||||
(Opcode: $A0; ArgType: atAddress; Mnemonic: 'BRZ'; Proc: DoBRZ),
|
||||
(Opcode: $C0; ArgType: atAddress; Mnemonic: 'JMP'; Proc: DoJMP),
|
||||
(Opcode: $E0; ArgType: atNone; Mnemonic: 'STP'; Proc: DoSTP));
|
||||
|
||||
|
||||
|
||||
procedure ClearMemory;
|
||||
{Set all memory locations to zero}
|
||||
var I: integer;
|
||||
begin
|
||||
for I:=0 to High(Memory) do
|
||||
Memory[I]:=0;
|
||||
end;
|
||||
|
||||
|
||||
function DecodeMnemonic(NMem: string): TOpcode;
|
||||
{Convert 3-char Mnemonic to opcode info}
|
||||
var I: integer;
|
||||
begin
|
||||
for I:=0 to High(OpTable) do
|
||||
if NMem=OpTable[I].Mnemonic then
|
||||
begin
|
||||
Result:=OpTable[I];
|
||||
exit;
|
||||
end;
|
||||
raise Exception.Create('Opcode Not Found');
|
||||
end;
|
||||
|
||||
|
||||
procedure AssembleProgram(Prog: string);
|
||||
{Convert text source code into machine code and store in memory}
|
||||
var Inx,MemInx,IntAtom,T: integer;
|
||||
var Atom: string;
|
||||
var OC: TOpcode;
|
||||
begin
|
||||
ClearMemory;
|
||||
MemInx:=0;
|
||||
Inx:=1;
|
||||
while true do
|
||||
begin
|
||||
{Get one space delimited atom}
|
||||
Atom:=ExtractToken(Prog,' ',Inx);
|
||||
{exit if end of source code}
|
||||
if Atom='' then break;
|
||||
{Is the atom text (Mnemonic) or number?}
|
||||
if Atom[1] in ['A'..'Z','a'..'z'] then
|
||||
begin
|
||||
{Convert Mnemonic to opcode info}
|
||||
OC:=DecodeMnemonic(Atom);
|
||||
{Get machine value of opcode}
|
||||
IntAtom:=OC.OpCode;
|
||||
{Is operand of of memory or address type?}
|
||||
if OC.ArgType in [atMemory,atAddress] then
|
||||
begin
|
||||
{if so combine opcode and operand}
|
||||
Atom:=ExtractToken(Prog,' ',Inx);
|
||||
T:=StrToInt(Atom);
|
||||
IntAtom:=IntAtom or T;
|
||||
end;
|
||||
end
|
||||
else IntAtom:=StrToInt(Atom);
|
||||
{Store machine code in memory}
|
||||
Memory[MemInx]:=IntAtom;
|
||||
{Point to next memory location}
|
||||
Inc(MemInx);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function DecodeOpcode(Inst: byte; var Opcode: TOpcode): boolean;
|
||||
{Convert machine instruction to opcode information}
|
||||
var I: integer;
|
||||
var Op: byte;
|
||||
begin
|
||||
Result:=True;
|
||||
{Get opcode part of instruction}
|
||||
Op:=$E0 and Inst;
|
||||
{Look for it in table}
|
||||
for I:=0 to High(OpTable) do
|
||||
if OpTable[I].OpCode=Op then
|
||||
begin
|
||||
Opcode:=OpTable[I];
|
||||
exit;
|
||||
end;
|
||||
Result:=False;
|
||||
end;
|
||||
|
||||
|
||||
function ExecuteInstruction(Instruct: byte): boolean;
|
||||
{Execute a single instruction}
|
||||
var I: integer;
|
||||
var Opcode: TOpcode;
|
||||
var Operand: byte;
|
||||
begin
|
||||
if not DecodeOpcode(Instruct,Opcode) then raise Exception.Create('Illegal Opcode');
|
||||
{Separate instruction and operand}
|
||||
Operand:=$1F and Instruct;
|
||||
{Execute instruction}
|
||||
Result:=Opcode.Proc(Operand);
|
||||
end;
|
||||
|
||||
|
||||
procedure DisplayInstruction(Memo: TMemo; PC: integer);
|
||||
{Display instruction information}
|
||||
var Opcode: TOpcode;
|
||||
var Inst,Operand: integer;
|
||||
var S: string;
|
||||
begin
|
||||
Inst:=Memory[PC];
|
||||
if not DecodeOpcode(Inst,Opcode) then raise Exception.Create('Illegal Opcode');
|
||||
Operand:=Inst and $1F;
|
||||
S:=IntToStr(PC)+' $'+IntToHex(Inst,2);
|
||||
S:=S+' '+Opcode.Mnemonic;
|
||||
case Opcode.ArgType of
|
||||
atMemory:
|
||||
begin
|
||||
S:=S+' Mem['+IntToStr(Operand)+']=';
|
||||
S:=S+' '+IntToStr(Memory[Operand]);
|
||||
end;
|
||||
atAddress: S:=S+' '+IntToStr(Operand);
|
||||
end;
|
||||
Memo.Lines.Add(S);
|
||||
end;
|
||||
|
||||
|
||||
procedure ExecuteProgram(Memo: TMemo; Prog: TProgram);
|
||||
{Executed program until stop instruction reached}
|
||||
begin
|
||||
Memo.Lines.Add(Prog.Name);
|
||||
AssembleProgram(Prog.Code);
|
||||
ProgramCounter:=0;
|
||||
Accumulator:=0;
|
||||
repeat
|
||||
begin
|
||||
DisplayInstruction(Memo,ProgramCounter);
|
||||
end
|
||||
until not ExecuteInstruction(Memory[ProgramCounter]);
|
||||
Memo.Lines.Add('Result='+IntToStr(Accumulator));
|
||||
Memo.Lines.Add('');
|
||||
end;
|
||||
|
||||
|
||||
|
||||
procedure ShowComputerZero(Memo: TMemo);
|
||||
{Execute and display all five sample programs.}
|
||||
begin
|
||||
ExecuteProgram(Memo,ProgList[0]);
|
||||
ExecuteProgram(Memo,ProgList[1]);
|
||||
ExecuteProgram(Memo,ProgList[2]);
|
||||
ExecuteProgram(Memo,ProgList[3]);
|
||||
ExecuteProgram(Memo,ProgList[4]);
|
||||
end;
|
||||
194
Task/Execute-Computer-Zero/Forth/execute-computer-zero.fth
Normal file
194
Task/Execute-Computer-Zero/Forth/execute-computer-zero.fth
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
#! /usr/bin/gforth
|
||||
|
||||
\ Execute Computer/Zero
|
||||
|
||||
\ reserve 32 cells for memory
|
||||
|
||||
CREATE MEMORY 32 cells allot
|
||||
MEMORY 32 cells erase
|
||||
|
||||
|
||||
\ gets the address of the memory cell with the given index
|
||||
: mem ( ix - addr )
|
||||
cells MEMORY +
|
||||
;
|
||||
|
||||
\ splits a byte into instruction and argument
|
||||
: instruction ( ix -> arg inst )
|
||||
mem @ dup
|
||||
32 mod swap
|
||||
32 /
|
||||
;
|
||||
|
||||
\ defines a program by giving its name and the 32 memory contents (in binary)
|
||||
: PROGRAM ( "name" "b01" ... "b31" -- )
|
||||
CREATE
|
||||
base @ >r 2 base !
|
||||
32 0 DO
|
||||
BEGIN
|
||||
parse-name
|
||||
dup 0= WHILE
|
||||
2drop refill drop
|
||||
REPEAT
|
||||
s>number? 2drop ,
|
||||
LOOP
|
||||
r> base !
|
||||
DOES> ( -- n00 ... n31 )
|
||||
32 0 DO
|
||||
dup @ swap cell+
|
||||
LOOP
|
||||
drop
|
||||
;
|
||||
|
||||
\ loads 32 bytes from the stack into memory
|
||||
: >memory ( n00 ... n31 -- )
|
||||
-1 31 -DO
|
||||
i mem !
|
||||
1 -LOOP
|
||||
;
|
||||
|
||||
\ prints accumulator and program counter
|
||||
: .acc-pc ( acc pc -- acc pc )
|
||||
over 3 .r dup 3 .r
|
||||
;
|
||||
|
||||
\ prints the argument
|
||||
: .x ( x -- x )
|
||||
dup 2 .r
|
||||
;
|
||||
|
||||
\ performs one step of the simulation
|
||||
: step ( acc pc -- acc' pc' )
|
||||
.acc-pc ." : "
|
||||
tuck instruction CASE
|
||||
0 OF ." NOP " .x drop swap 1+ ENDOF
|
||||
1 OF ." LDA " .x nip mem @ swap 1+ ENDOF
|
||||
2 OF ." STA " .x over swap mem ! swap 1+ ENDOF
|
||||
3 OF ." ADD " .x mem @ + 256 mod swap 1+ ENDOF
|
||||
4 OF ." SUB " .x mem @ - 256 mod swap 1+ ENDOF
|
||||
5 OF ." BRZ " .x over 0= if rot drop else drop swap 1+ then ENDOF
|
||||
6 OF ." JMP " .x rot drop ENDOF
|
||||
7 OF ." STP " .x drop nip -1 ENDOF
|
||||
ENDCASE
|
||||
." -> " .acc-pc
|
||||
;
|
||||
|
||||
\ runs the simulation, starting with accumulator zero and program counter zero
|
||||
: run ( -- acc )
|
||||
0 0 cr
|
||||
BEGIN
|
||||
dup 0>= WHILE
|
||||
step cr
|
||||
REPEAT
|
||||
drop
|
||||
;
|
||||
|
||||
|
||||
\ the five example programs
|
||||
|
||||
PROGRAM 2+2
|
||||
00100011 01100100
|
||||
11100000 00000010
|
||||
00000010 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
|
||||
PROGRAM 7*8
|
||||
00101100 01101010
|
||||
01001100 00101011
|
||||
10001101 01001011
|
||||
10101000 11000000
|
||||
00101100 11100000
|
||||
00001000 00000111
|
||||
00000000 00000001
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
|
||||
PROGRAM Fibonacci
|
||||
00101110 01001111
|
||||
01101101 01001110
|
||||
00101111 01001101
|
||||
00110000 10010001
|
||||
10101011 01010000
|
||||
11000000 00101110
|
||||
11100000 00000001
|
||||
00000001 00000000
|
||||
00001000 00000001
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
00000000 00000000
|
||||
|
||||
PROGRAM List'
|
||||
00101101 01101111
|
||||
01000101 01110000
|
||||
01000111 00000000
|
||||
01001110 00000000
|
||||
10101011 01001111
|
||||
11000000 00101110
|
||||
11100000 00100000
|
||||
00000000 00011100
|
||||
00000001 00000000
|
||||
00000000 00000000
|
||||
00000110 00000000
|
||||
00000010 00011010
|
||||
00000101 00010100
|
||||
00000011 00011110
|
||||
00000001 00010110
|
||||
00000100 00011000
|
||||
|
||||
PROGRAM Prisoner
|
||||
00000000 00000000
|
||||
11100000 00000000
|
||||
00100011 10011101
|
||||
10110010 00100011
|
||||
01011101 10101110
|
||||
00100001 01111111
|
||||
01000001 11000010
|
||||
00100000 01111111
|
||||
01000000 11000010
|
||||
00100011 01011101
|
||||
00100001 01111110
|
||||
01100011 01000001
|
||||
00100000 01111110
|
||||
01100011 01000000
|
||||
11000010 00000000
|
||||
00000001 00000011
|
||||
|
||||
|
||||
\ runs a program and drops the result
|
||||
: run-sample-program ( -- )
|
||||
>memory run drop
|
||||
;
|
||||
|
||||
|
||||
\ run the five example programs
|
||||
|
||||
2+2 run-sample-program
|
||||
7*8 run-sample-program
|
||||
Fibonacci run-sample-program
|
||||
List' run-sample-program
|
||||
Prisoner run-sample-program
|
||||
|
||||
bye
|
||||
268
Task/Execute-Computer-Zero/Go/execute-computer-zero.go
Normal file
268
Task/Execute-Computer-Zero/Go/execute-computer-zero.go
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
NOP = iota
|
||||
LDA
|
||||
STA
|
||||
ADD
|
||||
SUB
|
||||
BRZ
|
||||
JMP
|
||||
STP
|
||||
)
|
||||
|
||||
var opcodes = map[string]int{
|
||||
"NOP": NOP,
|
||||
"LDA": LDA,
|
||||
"STA": STA,
|
||||
"ADD": ADD,
|
||||
"SUB": SUB,
|
||||
"BRZ": BRZ,
|
||||
"JMP": JMP,
|
||||
"STP": STP,
|
||||
}
|
||||
|
||||
var reIns = regexp.MustCompile(
|
||||
`\s*(?:(\w+):)?\s*` + // label
|
||||
`(NOP|LDA|STA|ADD|SUB|BRZ|JMP|STP)?\s*` + // opcode
|
||||
`(\w+)?\s*` + // argument
|
||||
`(?:;([\w\s]+))?`) // comment
|
||||
|
||||
type ByteCode [32]int
|
||||
|
||||
type instruction struct {
|
||||
Label string
|
||||
Opcode string
|
||||
Arg string
|
||||
}
|
||||
|
||||
type Program struct {
|
||||
Instructions []instruction
|
||||
Labels map[string]int
|
||||
}
|
||||
|
||||
func newInstruction(line string) (*instruction, error) {
|
||||
match := reIns.FindStringSubmatch(line)
|
||||
if match == nil {
|
||||
return nil, fmt.Errorf("syntax error: '%s'", line)
|
||||
}
|
||||
return &instruction{Label: match[1], Opcode: match[2], Arg: match[3]}, nil
|
||||
}
|
||||
|
||||
func Parse(asm io.Reader) (*Program, error) {
|
||||
var p Program
|
||||
p.Labels = make(map[string]int, 32)
|
||||
scanner := bufio.NewScanner(asm)
|
||||
lineNumber := 0
|
||||
|
||||
for scanner.Scan() {
|
||||
if instruction, err := newInstruction(scanner.Text()); err != nil {
|
||||
return &p, err
|
||||
} else {
|
||||
if instruction.Label != "" {
|
||||
p.Labels[instruction.Label] = lineNumber
|
||||
}
|
||||
p.Instructions = append(p.Instructions, *instruction)
|
||||
lineNumber++
|
||||
}
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &p, nil
|
||||
}
|
||||
|
||||
func (p *Program) Compile() (ByteCode, error) {
|
||||
var bytecode ByteCode
|
||||
var arg int
|
||||
for i, ins := range p.Instructions {
|
||||
if ins.Arg == "" {
|
||||
arg = 0
|
||||
} else if addr, err := strconv.Atoi(ins.Arg); err == nil {
|
||||
arg = addr
|
||||
} else if addr, ok := p.Labels[ins.Arg]; ok {
|
||||
arg = addr
|
||||
} else {
|
||||
return bytecode, fmt.Errorf("unknown label %v", ins.Arg)
|
||||
}
|
||||
|
||||
if opcode, ok := opcodes[ins.Opcode]; ok {
|
||||
bytecode[i] = opcode<<5 | arg
|
||||
} else {
|
||||
bytecode[i] = arg
|
||||
}
|
||||
}
|
||||
return bytecode, nil
|
||||
}
|
||||
|
||||
func floorMod(a, b int) int {
|
||||
return ((a % b) + b) % b
|
||||
}
|
||||
|
||||
func Run(bytecode ByteCode) (int, error) {
|
||||
acc := 0
|
||||
pc := 0
|
||||
mem := bytecode
|
||||
|
||||
var op int
|
||||
var arg int
|
||||
|
||||
loop:
|
||||
for pc < 32 {
|
||||
op = mem[pc] >> 5
|
||||
arg = mem[pc] & 31
|
||||
pc++
|
||||
|
||||
switch op {
|
||||
case NOP:
|
||||
continue
|
||||
case LDA:
|
||||
acc = mem[arg]
|
||||
case STA:
|
||||
mem[arg] = acc
|
||||
case ADD:
|
||||
acc = floorMod(acc+mem[arg], 256)
|
||||
case SUB:
|
||||
acc = floorMod(acc-mem[arg], 256)
|
||||
case BRZ:
|
||||
if acc == 0 {
|
||||
pc = arg
|
||||
}
|
||||
case JMP:
|
||||
pc = arg
|
||||
case STP:
|
||||
break loop
|
||||
default:
|
||||
return acc, fmt.Errorf("runtime error: %v %v", op, arg)
|
||||
}
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
func Execute(asm string) (int, error) {
|
||||
program, err := Parse(strings.NewReader(asm))
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("assembly error: %v", err)
|
||||
}
|
||||
|
||||
bytecode, err := program.Compile()
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("compilation error: %v", err)
|
||||
}
|
||||
|
||||
result, err := Run(bytecode)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
examples := []string{
|
||||
`LDA x
|
||||
ADD y ; accumulator = x + y
|
||||
STP
|
||||
x: 2
|
||||
y: 2`,
|
||||
`loop: LDA prodt
|
||||
ADD x
|
||||
STA prodt
|
||||
LDA y
|
||||
SUB one
|
||||
STA y
|
||||
BRZ done
|
||||
JMP loop
|
||||
done: LDA prodt ; to display it
|
||||
STP
|
||||
x: 8
|
||||
y: 7
|
||||
prodt: 0
|
||||
one: 1`,
|
||||
`loop: LDA n
|
||||
STA temp
|
||||
ADD m
|
||||
STA n
|
||||
LDA temp
|
||||
STA m
|
||||
LDA count
|
||||
SUB one
|
||||
BRZ done
|
||||
STA count
|
||||
JMP loop
|
||||
done: LDA n ; to display it
|
||||
STP
|
||||
m: 1
|
||||
n: 1
|
||||
temp: 0
|
||||
count: 8 ; valid range: 1-11
|
||||
one: 1`,
|
||||
`start: LDA load
|
||||
ADD car ; head of list
|
||||
STA ldcar
|
||||
ADD one
|
||||
STA ldcdr ; next CONS cell
|
||||
ldcar: NOP
|
||||
STA value
|
||||
ldcdr: NOP
|
||||
BRZ done ; 0 stands for NIL
|
||||
STA car
|
||||
JMP start
|
||||
done: LDA value ; CAR of last CONS
|
||||
STP
|
||||
load: LDA 0
|
||||
value: 0
|
||||
car: 28
|
||||
one: 1
|
||||
; order of CONS cells
|
||||
; in memory
|
||||
; does not matter
|
||||
6
|
||||
0 ; 0 stands for NIL
|
||||
2 ; (CADR ls)
|
||||
26 ; (CDDR ls) -- etc.
|
||||
5
|
||||
20
|
||||
3
|
||||
30
|
||||
1 ; value of (CAR ls)
|
||||
22 ; points to (CDR ls)
|
||||
4
|
||||
24`,
|
||||
`LDA 3
|
||||
SUB 4
|
||||
STP 0
|
||||
0
|
||||
255`,
|
||||
`LDA 3
|
||||
SUB 4
|
||||
STP 0
|
||||
0
|
||||
1`,
|
||||
`LDA 3
|
||||
ADD 4
|
||||
STP 0
|
||||
1
|
||||
255`,
|
||||
}
|
||||
|
||||
for _, asm := range examples {
|
||||
if result, err := Execute(asm); err == nil {
|
||||
fmt.Println(result)
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
45
Task/Execute-Computer-Zero/J/execute-computer-zero-1.j
Normal file
45
Task/Execute-Computer-Zero/J/execute-computer-zero-1.j
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
OPS=: 'nop lda sta add sub brz jmp stp'
|
||||
|
||||
assemble1=: {{
|
||||
y=. tolower y
|
||||
ins=. {.;:y-.":i.10
|
||||
cod=. 8|(;:OPS) i. ins
|
||||
val=. {.0".y-.OPS
|
||||
if. *cod do.
|
||||
assert. 32>val
|
||||
val+32*cod
|
||||
else.
|
||||
assert. 256>val
|
||||
val
|
||||
end.
|
||||
}}
|
||||
|
||||
assemble=: {{
|
||||
if. 0=L. y do.
|
||||
delim=. {.((tolower y)-.(":i.10),;OPS),LF
|
||||
y=. delim cut y
|
||||
end.
|
||||
code=. assemble1@> y
|
||||
mem=: code (i.#code)} 32#0
|
||||
}}
|
||||
|
||||
exec1=: {{
|
||||
'cod val'=. 0 32#:pc{mem
|
||||
pc=: 32|pc+1
|
||||
select. cod
|
||||
case. 0 do.
|
||||
case. 1 do. acc=: val{mem
|
||||
case. 2 do. mem=: acc val} mem
|
||||
case. 3 do. acc=: 256|acc+val{mem
|
||||
case. 4 do. acc=: 256|acc-val{mem
|
||||
case. 5 do. pc=: 32|pc[^:(*acc) val
|
||||
case. 6 do. pc=: 32|val
|
||||
case. 7 do. pc=: __
|
||||
end.
|
||||
}}
|
||||
|
||||
exec=: {{
|
||||
pc=: acc=: 0
|
||||
while. 0<:pc do. exec1'' end.
|
||||
acc
|
||||
}}
|
||||
10
Task/Execute-Computer-Zero/J/execute-computer-zero-2.j
Normal file
10
Task/Execute-Computer-Zero/J/execute-computer-zero-2.j
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
exec assemble 'LDA 3; ADD 4; STP; 2; 2'
|
||||
4
|
||||
exec assemble 'LDA 12; ADD 10; STA 12; LDA 11; SUB 13; STA 11; BRZ 8; JMP; LDA 12; STP; 8; 7; 0; 1'
|
||||
56
|
||||
exec assemble 'LDA 14; STA 15; ADD 13; STA 14; LDA 15; STA 13; LDA 16; SUB 17; BRZ 11; STA 16; JMP; LDA 14; STP; 1; 1; 0; 8; 1'
|
||||
55
|
||||
exec assemble 'LDA 13; ADD 15; STA 5; ADD 16; STA 7; NOP; STA 14; NOP; BRZ 11; STA 15; JMP; LDA 14; STP; LDA; 0; 28; 1; 0; 0; 0; 6; 0; 2; 26; 5; 20; 3; 30; 1; 22; 4; 24'
|
||||
6
|
||||
exec assemble 'NOP; NOP; STP; NOP; LDA 3; SUB 29; BRZ 18; LDA 3; STA 29; BRZ 14; LDA 1; ADD 31; STA 1; JMP 2; LDA; ADD 31; STA; JMP 2; LDA 3; STA 29; LDA 1; ADD 30; ADD 3; STA 1; LDA; ADD 30; ADD 3; STA; JMP 2; 0; 1; 3'
|
||||
0
|
||||
29
Task/Execute-Computer-Zero/J/execute-computer-zero-3.j
Normal file
29
Task/Execute-Computer-Zero/J/execute-computer-zero-3.j
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
opcode=: {{
|
||||
(m+{.y),}.y
|
||||
:
|
||||
x,m opcode y
|
||||
}}
|
||||
|
||||
({{((x)=: y opcode)0}}&>32*i.@#);:'NOP LDA STA ADD SUB BRZ JMP STP'
|
||||
|
||||
exec1=: {{
|
||||
'cod val'=. 0 32#:pc{mem
|
||||
pc=: 32|pc+1
|
||||
select. cod
|
||||
case. 0 do. NB. NOP
|
||||
case. 1 do. acc=: val{mem NB. LDA
|
||||
case. 2 do. mem=: acc val} mem NB. STA
|
||||
case. 3 do. acc=: 256|acc+val{mem NB. ADD
|
||||
case. 4 do. acc=: 256|acc-val{mem NB. SUB
|
||||
case. 5 do. pc=: 32|pc[^:(*acc) val NB. BRZ
|
||||
case. 6 do. pc=: 32|val NB. JMP
|
||||
case. 7 do. pc=: __ NB. STP
|
||||
end.
|
||||
}}
|
||||
|
||||
exec=: {{
|
||||
mem=: 32{.y
|
||||
pc=: acc=: 0
|
||||
while. 0<:pc do. exec1'' end.
|
||||
acc
|
||||
}}
|
||||
10
Task/Execute-Computer-Zero/J/execute-computer-zero-4.j
Normal file
10
Task/Execute-Computer-Zero/J/execute-computer-zero-4.j
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
exec LDA 3 ADD 4 STP 0 2 2
|
||||
4
|
||||
exec LDA 12 ADD 10 STA 12 LDA 11 SUB 13 STA 11 BRZ 8 JMP 0 LDA 12 STP 0 8 7 0 1
|
||||
56
|
||||
exec LDA 14 STA 15 ADD 13 STA 14 LDA 15 STA 13 LDA 16 SUB 17 BRZ 11 STA 16 JMP 0 LDA 14 STP 0 1 1 0 8 1
|
||||
55
|
||||
exec LDA 13 ADD 15 STA 5 ADD 16 STA 7 NOP 0 STA 14 NOP 0 BRZ 11 STA 15 JMP 0 LDA 14 STP 0 LDA 0 0 28 1 0 0 0 6 0 2 26 5 20 3 30 1 22 4 24
|
||||
6
|
||||
exec NOP 0 NOP 0 STP 0 NOP 0 LDA 3 SUB 29 BRZ 18 LDA 3 STA 29 BRZ 14 LDA 1 ADD 31 STA 1 JMP 2 LDA 0 ADD 31 STA 0 JMP 2 LDA 3 STA 29 LDA 1 ADD 30 ADD 3 STA 1 LDA 0 ADD 30 ADD 3 STA 0 JMP 2 0 1 3
|
||||
0
|
||||
305
Task/Execute-Computer-Zero/Java/execute-computer-zero.java
Normal file
305
Task/Execute-Computer-Zero/Java/execute-computer-zero.java
Normal file
|
|
@ -0,0 +1,305 @@
|
|||
import static java.lang.Math.floorMod;
|
||||
import static java.lang.Math.min;
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ComputerZero {
|
||||
|
||||
private static final int MEM = 32;
|
||||
|
||||
private static final int NOP = 0;
|
||||
private static final int LDA = 1;
|
||||
private static final int STA = 2;
|
||||
private static final int ADD = 3;
|
||||
private static final int SUB = 4;
|
||||
private static final int BRZ = 5;
|
||||
private static final int JMP = 6;
|
||||
private static final int STP = 7;
|
||||
|
||||
private static final Map<String, Integer> OPCODES = Stream.of(
|
||||
new SimpleEntry<>("NOP", NOP),
|
||||
new SimpleEntry<>("LDA", LDA),
|
||||
new SimpleEntry<>("STA", STA),
|
||||
new SimpleEntry<>("ADD", ADD),
|
||||
new SimpleEntry<>("SUB", SUB),
|
||||
new SimpleEntry<>("BRZ", BRZ),
|
||||
new SimpleEntry<>("JMP", JMP),
|
||||
new SimpleEntry<>("STP", STP))
|
||||
.collect(toMap(SimpleEntry::getKey, SimpleEntry::getValue));
|
||||
|
||||
private static final Pattern RE_INSTRUCTION = Pattern.compile(
|
||||
"\\s*" +
|
||||
"(?:(?<label>\\w+):)?" +
|
||||
"\\s*" +
|
||||
String.format("(?<opcode>%s)?", String.join("|", OPCODES.keySet())) +
|
||||
"\\s*" +
|
||||
"(?<argument>\\w+)?" +
|
||||
"\\s*" +
|
||||
"(?:;(?<comment>.+))?");
|
||||
|
||||
public static class ComputerZeroException extends RuntimeException {
|
||||
public ComputerZeroException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Instruction {
|
||||
String opcode;
|
||||
String argument;
|
||||
|
||||
public Instruction(String opcode, String argument) {
|
||||
this.opcode = opcode;
|
||||
this.argument = argument;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Assembly {
|
||||
public Iterable<Instruction> instructions;
|
||||
public Map<String, Integer> labels;
|
||||
|
||||
public Assembly(Iterable<Instruction> instructions, Map<String, Integer> labels) {
|
||||
this.instructions = instructions;
|
||||
this.labels = labels;
|
||||
}
|
||||
}
|
||||
|
||||
public static Assembly parse(String assembly) {
|
||||
ArrayList<Instruction> instructions = new ArrayList<Instruction>();
|
||||
HashMap<String, Integer> labels = new HashMap<String, Integer>();
|
||||
int lineNumber = 0;
|
||||
|
||||
for (String line : assembly.split("\\R")) {
|
||||
Matcher matcher = RE_INSTRUCTION.matcher(line);
|
||||
|
||||
if (!matcher.matches()) {
|
||||
throw new ComputerZeroException(String.format("%s %d", line, lineNumber));
|
||||
}
|
||||
|
||||
if (matcher.group("label") != null) {
|
||||
labels.put(matcher.group("label"), lineNumber);
|
||||
}
|
||||
|
||||
instructions.add(new Instruction(matcher.group("opcode"), matcher.group("argument")));
|
||||
lineNumber++;
|
||||
}
|
||||
|
||||
return new Assembly(instructions, labels);
|
||||
}
|
||||
|
||||
public static Integer[] compile(Assembly assembly) {
|
||||
ArrayList<Integer> bytecode = new ArrayList<Integer>();
|
||||
|
||||
for (Instruction instruction : assembly.instructions) {
|
||||
int argument;
|
||||
if (instruction.argument == null) {
|
||||
argument = 0;
|
||||
} else if (instruction.argument.matches("\\d+")) {
|
||||
argument = Integer.parseInt(instruction.argument);
|
||||
} else {
|
||||
argument = assembly.labels.getOrDefault(instruction.argument, 0);
|
||||
}
|
||||
|
||||
if (instruction.opcode != null) {
|
||||
bytecode.add(OPCODES.get(instruction.opcode) << 5 | argument);
|
||||
} else {
|
||||
bytecode.add(argument);
|
||||
}
|
||||
}
|
||||
|
||||
return bytecode.toArray(new Integer[0]);
|
||||
}
|
||||
|
||||
public static int run(Integer[] bytecode) {
|
||||
int accumulator = 0;
|
||||
int instruction_pointer = 0;
|
||||
Integer[] memory = new Integer[MEM];
|
||||
Arrays.fill(memory, 0);
|
||||
System.arraycopy(bytecode, 0, memory, 0, min(MEM, bytecode.length));
|
||||
|
||||
vm: while (instruction_pointer < MEM) {
|
||||
int operation = memory[instruction_pointer] >> 5;
|
||||
int argument = memory[instruction_pointer] & 0b11111;
|
||||
instruction_pointer++;
|
||||
|
||||
switch (operation) {
|
||||
case NOP:
|
||||
continue;
|
||||
case LDA:
|
||||
accumulator = memory[argument];
|
||||
break;
|
||||
case STA:
|
||||
memory[argument] = accumulator;
|
||||
break;
|
||||
case ADD:
|
||||
accumulator = floorMod(accumulator + memory[argument], 256);
|
||||
break;
|
||||
case SUB:
|
||||
accumulator = floorMod(accumulator - memory[argument], 256);
|
||||
break;
|
||||
case BRZ:
|
||||
if (accumulator == 0) {
|
||||
instruction_pointer = argument;
|
||||
}
|
||||
break;
|
||||
case JMP:
|
||||
instruction_pointer = argument;
|
||||
break;
|
||||
case STP:
|
||||
break vm;
|
||||
default:
|
||||
throw new ComputerZeroException(
|
||||
String.format("error: %d %d", operation, argument));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
public static int run(String source) {
|
||||
return run(compile(parse(source)));
|
||||
}
|
||||
|
||||
public static final List<String> TEST_CASES = Arrays.asList(
|
||||
String.join("\n",
|
||||
" LDA x",
|
||||
" ADD y ; accumulator = x + y",
|
||||
" STP",
|
||||
"x: 2",
|
||||
"y: 2"),
|
||||
String.join("\n",
|
||||
"loop: LDA prodt",
|
||||
" ADD x",
|
||||
" STA prodt",
|
||||
" LDA y",
|
||||
" SUB one",
|
||||
" STA y",
|
||||
" BRZ done",
|
||||
" JMP loop",
|
||||
"done: LDA prodt ; to display it",
|
||||
" STP",
|
||||
"x: 8",
|
||||
"y: 7",
|
||||
"prodt: 0",
|
||||
"one: 1"),
|
||||
String.join("\n",
|
||||
"loop: LDA n",
|
||||
" STA temp",
|
||||
" ADD m",
|
||||
" STA n",
|
||||
" LDA temp",
|
||||
" STA m",
|
||||
" LDA count",
|
||||
" SUB one",
|
||||
" BRZ done",
|
||||
" STA count",
|
||||
" JMP loop",
|
||||
"done: LDA n ; to display it",
|
||||
" STP",
|
||||
"m: 1",
|
||||
"n: 1",
|
||||
"temp: 0",
|
||||
"count: 8 ; valid range: 1-11",
|
||||
"one: 1"),
|
||||
String.join("\n",
|
||||
"start: LDA load",
|
||||
" ADD car ; head of list",
|
||||
" STA ldcar",
|
||||
" ADD one",
|
||||
" STA ldcdr ; next CONS cell",
|
||||
"ldcar: NOP",
|
||||
" STA value",
|
||||
"ldcdr: NOP",
|
||||
" BRZ done ; 0 stands for NIL",
|
||||
" STA car",
|
||||
" JMP start",
|
||||
"done: LDA value ; CAR of last CONS",
|
||||
" STP",
|
||||
"load: LDA 0",
|
||||
"value: 0",
|
||||
"car: 28",
|
||||
"one: 1",
|
||||
" ; order of CONS cells",
|
||||
" ; in memory",
|
||||
" ; does not matter",
|
||||
" 6",
|
||||
" 0 ; 0 stands for NIL",
|
||||
" 2 ; (CADR ls)",
|
||||
" 26 ; (CDDR ls) -- etc.",
|
||||
" 5",
|
||||
" 20",
|
||||
" 3",
|
||||
" 30",
|
||||
" 1 ; value of (CAR ls)",
|
||||
" 22 ; points to (CDR ls)",
|
||||
" 4",
|
||||
" 24"),
|
||||
String.join("\n",
|
||||
"p: 0 ; NOP in first round",
|
||||
"c: 0",
|
||||
"start: STP ; wait for p's move",
|
||||
"pmove: NOP",
|
||||
" LDA pmove",
|
||||
" SUB cmove",
|
||||
" BRZ same",
|
||||
" LDA pmove",
|
||||
" STA cmove ; tit for tat",
|
||||
" BRZ cdeft",
|
||||
" LDA c ; p defected, c did not",
|
||||
" ADD three",
|
||||
" STA c",
|
||||
" JMP start",
|
||||
"cdeft: LDA p",
|
||||
" ADD three",
|
||||
" STA p",
|
||||
" JMP start",
|
||||
"same: LDA pmove",
|
||||
" STA cmove ; tit for tat",
|
||||
" LDA p",
|
||||
" ADD one",
|
||||
" ADD pmove",
|
||||
" STA p",
|
||||
" LDA c",
|
||||
" ADD one",
|
||||
" ADD pmove",
|
||||
" STA c",
|
||||
" JMP start",
|
||||
"cmove: 0 ; co-operate initially",
|
||||
"one: 1",
|
||||
"three: 3 "),
|
||||
String.join("\n",
|
||||
"LDA 3",
|
||||
"SUB 4",
|
||||
"STP 0",
|
||||
" 0",
|
||||
" 255"),
|
||||
String.join("\n",
|
||||
"LDA 3",
|
||||
"SUB 4",
|
||||
"STP 0",
|
||||
" 0",
|
||||
" 1"),
|
||||
String.join("\n",
|
||||
"LDA 3",
|
||||
"ADD 4",
|
||||
"STP 0",
|
||||
" 1",
|
||||
" 255")
|
||||
|
||||
);
|
||||
|
||||
public static void main(String[] args) {
|
||||
for (String source : TEST_CASES) {
|
||||
System.out.println(run(source));
|
||||
}
|
||||
}
|
||||
}
|
||||
175
Task/Execute-Computer-Zero/Julia/execute-computer-zero-1.julia
Normal file
175
Task/Execute-Computer-Zero/Julia/execute-computer-zero-1.julia
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
mutable struct ComputerZero
|
||||
ip::Int
|
||||
ram::Vector{UInt8}
|
||||
accum::UInt8
|
||||
isready::Bool
|
||||
end
|
||||
function ComputerZero(program)
|
||||
memory = zeros(UInt8, 32)
|
||||
for i in 1:min(32, length(program))
|
||||
memory[i] = program[i]
|
||||
end
|
||||
return ComputerZero(1, memory, 0, true)
|
||||
end
|
||||
|
||||
NOP(c) = (c.ip = mod1(c.ip + 1, 32))
|
||||
LDA(c) = (c.accum = c.ram[c.ram[c.ip] & 0b00011111 + 1]; c.ip = mod1(c.ip + 1, 32))
|
||||
STA(c) = (c.ram[c.ram[c.ip] & 0b00011111 + 1] = c.accum; c.ip = mod1(c.ip + 1, 32))
|
||||
ADD(c) = (c.accum += c.ram[c.ram[c.ip] & 0b00011111 + 1]; c.ip = mod1(c.ip + 1, 32))
|
||||
SUB(c) = (c.accum -= c.ram[c.ram[c.ip] & 0b00011111 + 1]; c.ip = mod1(c.ip + 1, 32))
|
||||
BRZ(c) = (c.ip = (c.accum == 0) ? c.ram[c.ip] & 0b00011111 + 1 : mod1(c.ip + 1, 32))
|
||||
JMP(c) = (c.ip = c.ram[c.ip] & 0b00011111 + 1)
|
||||
STP(c) = (println("Program completed with accumulator value $(c.accum).\n"); c.isready = false)
|
||||
|
||||
const step = [NOP, LDA, STA, ADD, SUB, BRZ, JMP, STP]
|
||||
const instructions = ["NOP", "LDA", "STA", "ADD", "SUB", "BRZ", "JMP", "STP"]
|
||||
const assemblywords = Dict(s => i - 1 for (i, s) in pairs(instructions))
|
||||
|
||||
function run(compzero::ComputerZero, debug = false)
|
||||
while compzero.isready
|
||||
instruction = compzero.ram[compzero.ip]
|
||||
opcode, operand = instruction >> 5 + 1, instruction & 0b00011111
|
||||
debug && println("op $(instructions[opcode]), operand $operand")
|
||||
step[opcode](compzero)
|
||||
end
|
||||
return compzero.accum
|
||||
end
|
||||
run(program::Vector, debug = false) = run(ComputerZero(program), debug)
|
||||
|
||||
function compile(text::String)
|
||||
bin, lines = UInt8[], 0
|
||||
for line in strip.(split(text, "\n"))
|
||||
lines += 1
|
||||
if isempty(line)
|
||||
push!(bin, 0)
|
||||
elseif (m = match(r"(\w\w\w)\s+(\d\d?)", line)) != nothing
|
||||
push!(bin, UInt8((assemblywords[m.captures[1]] << 5) | parse(UInt8, m.captures[2])))
|
||||
elseif (m = match(r"(\w\w\w)", line)) != nothing
|
||||
push!(bin, UInt8(assemblywords[m.match] << 5))
|
||||
elseif (m = match(r"\d\d?", line)) != nothing
|
||||
push!(bin, parse(UInt8, m.match))
|
||||
else
|
||||
error("Compilation error at line $lines: error parsing <$line>")
|
||||
end
|
||||
end
|
||||
println("Compiled $lines lines.")
|
||||
return bin
|
||||
end
|
||||
|
||||
const testprograms = [
|
||||
"""
|
||||
LDA 3
|
||||
ADD 4
|
||||
STP
|
||||
2
|
||||
2
|
||||
""",
|
||||
"""
|
||||
LDA 12
|
||||
ADD 10
|
||||
STA 12
|
||||
LDA 11
|
||||
SUB 13
|
||||
STA 11
|
||||
BRZ 8
|
||||
JMP 0
|
||||
LDA 12
|
||||
STP
|
||||
8
|
||||
7
|
||||
0
|
||||
1
|
||||
""",
|
||||
"""
|
||||
LDA 14
|
||||
STA 15
|
||||
ADD 13
|
||||
STA 14
|
||||
LDA 15
|
||||
STA 13
|
||||
LDA 16
|
||||
SUB 17
|
||||
BRZ 11
|
||||
STA 16
|
||||
JMP 0
|
||||
LDA 14
|
||||
STP
|
||||
1
|
||||
1
|
||||
0
|
||||
8
|
||||
1
|
||||
""",
|
||||
"""
|
||||
LDA 13
|
||||
ADD 15
|
||||
STA 5
|
||||
ADD 16
|
||||
STA 7
|
||||
NOP
|
||||
STA 14
|
||||
NOP
|
||||
BRZ 11
|
||||
STA 15
|
||||
JMP 0
|
||||
LDA 14
|
||||
STP
|
||||
LDA 0
|
||||
0
|
||||
28
|
||||
1
|
||||
|
||||
|
||||
|
||||
6
|
||||
0
|
||||
2
|
||||
26
|
||||
5
|
||||
20
|
||||
3
|
||||
30
|
||||
1
|
||||
22
|
||||
4
|
||||
24
|
||||
""",
|
||||
"""
|
||||
0
|
||||
0
|
||||
STP
|
||||
NOP
|
||||
LDA 3
|
||||
SUB 29
|
||||
BRZ 18
|
||||
LDA 3
|
||||
STA 29
|
||||
BRZ 14
|
||||
LDA 1
|
||||
ADD 31
|
||||
STA 1
|
||||
JMP 2
|
||||
LDA 0
|
||||
ADD 31
|
||||
STA 0
|
||||
JMP 2
|
||||
LDA 3
|
||||
STA 29
|
||||
LDA 0
|
||||
ADD 30
|
||||
ADD 3
|
||||
STA 0
|
||||
LDA 1
|
||||
ADD 30
|
||||
ADD 3
|
||||
STA 1
|
||||
JMP 2
|
||||
0
|
||||
1
|
||||
3
|
||||
"""
|
||||
]
|
||||
|
||||
for t in testprograms
|
||||
run(compile(t))
|
||||
end
|
||||
294
Task/Execute-Computer-Zero/Julia/execute-computer-zero-2.julia
Normal file
294
Task/Execute-Computer-Zero/Julia/execute-computer-zero-2.julia
Normal file
|
|
@ -0,0 +1,294 @@
|
|||
function interpret(text::String)
|
||||
ip, accum, isready, ram = 0x1, 0x0, true, zeros(UInt8, 32)
|
||||
NOP() = (ip = mod1(ip + 1, 32))
|
||||
LDA() = (accum = ram[ram[ip] & 0b00011111 + 1]; ip = mod1(ip + 1, 32))
|
||||
STA() = (ram[ram[ip] & 0b00011111 + 1] = accum; ip = mod1(ip + 1, 32))
|
||||
ADD() = (accum += ram[ram[ip] & 0b00011111 + 1]; ip = mod1(ip + 1, 32))
|
||||
SUB() = (accum -= ram[ram[ip] & 0b00011111 + 1]; ip = mod1(ip + 1, 32))
|
||||
BRZ() = (ip = (accum == 0) ? ram[ip] & 0b00011111 + 1 : mod1(ip + 1, 32))
|
||||
JMP() = (ip = ram[ip] & 0b00011111 + 1)
|
||||
STP() = (println("Program completed with accumulator value $(accum).\n"); isready = false)
|
||||
step = [NOP, LDA, STA, ADD, SUB, BRZ, JMP, STP]
|
||||
assemblywords = Dict(s => i - 1 for (i, s) in pairs(string.(step)))
|
||||
labels = Dict{String, Int}()
|
||||
arglabels = Dict{Int, Tuple{Int, String}}()
|
||||
for (i, line) in pairs(strip.(split(text, "\n")))
|
||||
i > 32 && break
|
||||
line = replace(line, r";.*$" => "") # remove comment
|
||||
if occursin(":", line)
|
||||
label, line = split(line, ":", limit = 2)
|
||||
haskey(labels, label) && error("Duplicate label at line $i")
|
||||
labels[strip(label)] = i - 1
|
||||
end
|
||||
if isempty(line)
|
||||
ram[i] = 0
|
||||
elseif (m = match(r"(\w\w\w)\s+([a-zA-Z]\w*)", line)) != nothing
|
||||
arglabels[i] = (UInt8((assemblywords[m.captures[1]] << 5)), m.captures[2])
|
||||
elseif (m = match(r"(\w\w\w)\s+(\d\d*)", line)) != nothing
|
||||
ram[i] = UInt8((assemblywords[m.captures[1]] << 5) | parse(UInt8, m.captures[2]))
|
||||
elseif (m = match(r"([a-zA-Z]\w*)", line)) != nothing
|
||||
ram[i] = UInt8(assemblywords[m.match] << 5)
|
||||
elseif (m = match(r"\d\d*", line)) != nothing
|
||||
ram[i] = parse(UInt8, m.match)
|
||||
else
|
||||
error("Compilation error at line $i: error parsing <$line>")
|
||||
end
|
||||
end
|
||||
for (i, t) in arglabels
|
||||
ram[i] = t[1] | labels[t[2]]
|
||||
end
|
||||
while isready
|
||||
step[ram[ip] >> 5 + 1]()
|
||||
end
|
||||
return accum
|
||||
end
|
||||
|
||||
const testprograms = [
|
||||
"""
|
||||
LDA 3
|
||||
ADD 4
|
||||
STP
|
||||
2
|
||||
2
|
||||
""",
|
||||
"""
|
||||
LDA 12
|
||||
ADD 10
|
||||
STA 12
|
||||
LDA 11
|
||||
SUB 13
|
||||
STA 11
|
||||
BRZ 8
|
||||
JMP 0
|
||||
LDA 12
|
||||
STP
|
||||
8
|
||||
7
|
||||
0
|
||||
1
|
||||
""",
|
||||
"""
|
||||
LDA 14
|
||||
STA 15
|
||||
ADD 13
|
||||
STA 14
|
||||
LDA 15
|
||||
STA 13
|
||||
LDA 16
|
||||
SUB 17
|
||||
BRZ 11
|
||||
STA 16
|
||||
JMP 0
|
||||
LDA 14
|
||||
STP
|
||||
1
|
||||
1
|
||||
0
|
||||
8
|
||||
1
|
||||
""",
|
||||
"""
|
||||
LDA 13
|
||||
ADD 15
|
||||
STA 5
|
||||
ADD 16
|
||||
STA 7
|
||||
NOP
|
||||
STA 14
|
||||
NOP
|
||||
BRZ 11
|
||||
STA 15
|
||||
JMP 0
|
||||
LDA 14
|
||||
STP
|
||||
LDA 0
|
||||
0
|
||||
28
|
||||
1
|
||||
|
||||
|
||||
|
||||
6
|
||||
0
|
||||
2
|
||||
26
|
||||
5
|
||||
20
|
||||
3
|
||||
30
|
||||
1
|
||||
22
|
||||
4
|
||||
24
|
||||
""",
|
||||
"""
|
||||
0
|
||||
0
|
||||
STP
|
||||
NOP
|
||||
LDA 3
|
||||
SUB 29
|
||||
BRZ 18
|
||||
LDA 3
|
||||
STA 29
|
||||
BRZ 14
|
||||
LDA 1
|
||||
ADD 31
|
||||
STA 1
|
||||
JMP 2
|
||||
LDA 0
|
||||
ADD 31
|
||||
STA 0
|
||||
JMP 2
|
||||
LDA 3
|
||||
STA 29
|
||||
LDA 0
|
||||
ADD 30
|
||||
ADD 3
|
||||
STA 0
|
||||
LDA 1
|
||||
ADD 30
|
||||
ADD 3
|
||||
STA 1
|
||||
JMP 2
|
||||
0
|
||||
1
|
||||
3
|
||||
""",
|
||||
"""\
|
||||
LDA x
|
||||
ADD y ; accumulator = x + y
|
||||
STP
|
||||
x: 2
|
||||
y: 2
|
||||
""",
|
||||
"""\
|
||||
loop: LDA prodt
|
||||
ADD x
|
||||
STA prodt
|
||||
LDA y
|
||||
SUB one
|
||||
STA y
|
||||
BRZ done
|
||||
JMP loop
|
||||
done: LDA prodt ; to display it
|
||||
STP
|
||||
x: 8
|
||||
y: 7
|
||||
prodt: 0
|
||||
one: 1
|
||||
""",
|
||||
"""\
|
||||
loop: LDA n
|
||||
STA temp
|
||||
ADD m
|
||||
STA n
|
||||
LDA temp
|
||||
STA m
|
||||
LDA count
|
||||
SUB one
|
||||
BRZ done
|
||||
STA count
|
||||
JMP loop
|
||||
done: LDA n ; to display it
|
||||
STP
|
||||
m: 1
|
||||
n: 1
|
||||
temp: 0
|
||||
count: 8 ; valid range: 1-11
|
||||
one: 1
|
||||
""",
|
||||
"""\
|
||||
start: LDA load
|
||||
ADD car ; head of list
|
||||
STA ldcar
|
||||
ADD one
|
||||
STA ldcdr ; next CONS cell
|
||||
ldcar: NOP
|
||||
STA value
|
||||
ldcdr: NOP
|
||||
BRZ done ; 0 stands for NIL
|
||||
STA car
|
||||
JMP start
|
||||
done: LDA value ; CAR of last CONS
|
||||
STP
|
||||
load: LDA 0
|
||||
value: 0
|
||||
car: 28
|
||||
one: 1
|
||||
; order of CONS cells
|
||||
; in memory
|
||||
; does not matter
|
||||
6
|
||||
0 ; 0 stands for NIL
|
||||
2 ; (CADR ls)
|
||||
26 ; (CDDR ls) -- etc.
|
||||
5
|
||||
20
|
||||
3
|
||||
30
|
||||
1 ; value of (CAR ls)
|
||||
22 ; points to (CDR ls)
|
||||
4
|
||||
24
|
||||
""",
|
||||
"""\
|
||||
p: 0 ; NOP in first round
|
||||
c: 0
|
||||
start: STP ; wait for p's move
|
||||
pmove: NOP
|
||||
LDA pmove
|
||||
SUB cmove
|
||||
BRZ same
|
||||
LDA pmove
|
||||
STA cmove ; tit for tat
|
||||
BRZ cdeft
|
||||
LDA c ; p defected, c did not
|
||||
ADD three
|
||||
STA c
|
||||
JMP start
|
||||
cdeft: LDA p
|
||||
ADD three
|
||||
STA p
|
||||
JMP start
|
||||
same: LDA pmove
|
||||
STA cmove ; tit for tat
|
||||
LDA p
|
||||
ADD one
|
||||
ADD pmove
|
||||
STA p
|
||||
LDA c
|
||||
ADD one
|
||||
ADD pmove
|
||||
STA c
|
||||
JMP start
|
||||
cmove: 0 ; co-operate initially
|
||||
one: 1
|
||||
three: 3
|
||||
""",
|
||||
"""\
|
||||
LDA 3
|
||||
SUB 4
|
||||
STP 0
|
||||
0
|
||||
255
|
||||
""",
|
||||
"""\
|
||||
LDA 3
|
||||
SUB 4
|
||||
STP 0
|
||||
0
|
||||
1
|
||||
""",
|
||||
"""\
|
||||
LDA 3
|
||||
ADD 4
|
||||
STP 0
|
||||
1
|
||||
255
|
||||
""",
|
||||
]
|
||||
|
||||
for t in testprograms
|
||||
interpret(t)
|
||||
end
|
||||
30
Task/Execute-Computer-Zero/Lua/execute-computer-zero-1.lua
Normal file
30
Task/Execute-Computer-Zero/Lua/execute-computer-zero-1.lua
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
vmz = {
|
||||
pc = 0,
|
||||
acc = 0,
|
||||
mem = { [0]=0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0 },
|
||||
b2oa = function(byte) return math.floor(byte / 32), byte % 32 end,
|
||||
boot = function(self) self.pc, self.acc = 0, 0 for pc=0,31 do self.mem[pc]=0 end return self end,
|
||||
load = function(self, bytes) for pc = 0, 31 do self.mem[pc]=bytes[pc] or 0 end return self end,
|
||||
clam = function(n) if n<0 then n=n+256 elseif n>255 then n=n-256 end return n end,
|
||||
opfn = {[0]=
|
||||
function(self,addr) self.pc=self.pc+1 return true end, -- NOP
|
||||
function(self,addr) self.acc=self.mem[addr] self.pc=self.pc+1 return true end, -- LDA
|
||||
function(self,addr) self.mem[addr]=self.acc self.pc=self.pc+1 return true end, -- STA
|
||||
function(self,addr) self.acc=self.clam(self.acc+self.mem[addr]) self.pc=self.pc+1 return true end, -- ADD
|
||||
function(self,addr) self.acc=self.clam(self.acc-self.mem[addr]) self.pc=self.pc+1 return true end, -- SUB
|
||||
function(self,addr) if (self.acc==0) then self.pc=addr else self.pc=self.pc+1 end return true end, -- BRZ
|
||||
function(self,addr) self.pc=addr return true end, -- JMP
|
||||
function(self,addr) self.pc=self.pc+1 return false end, -- STP
|
||||
},
|
||||
step = function(self)
|
||||
local oper, addr = self.b2oa(self.mem[self.pc])
|
||||
return self.opfn[oper](self,addr)
|
||||
end,
|
||||
exec = function(self)
|
||||
while self.pc < 32 and self:step() do end
|
||||
return self
|
||||
end,
|
||||
}
|
||||
-- object code derived from js sim code
|
||||
print("2 + 2 = " .. vmz:boot():load({[0]=35,100,224,2,2}):exec().acc)
|
||||
print("7 x 8 = " .. vmz:boot():load({[0]=44,106,76,43,141,75,168,192,44,224,8,7,0,1}):exec().acc)
|
||||
15
Task/Execute-Computer-Zero/Lua/execute-computer-zero-2.lua
Normal file
15
Task/Execute-Computer-Zero/Lua/execute-computer-zero-2.lua
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
vmz.dism = function(self)
|
||||
local mnem, imax = { [0]="NOP", "LDA", "STA", "ADD", "SUB", "BRZ", "JMP", "STP" }
|
||||
for pc = 31,0,-1 do imax=pc if self.mem[pc]~=0 then break end end
|
||||
local result, pretty = "", " %3s %2d\n"
|
||||
for i = 0, imax do
|
||||
local oper, addr = self.b2oa(self.mem[i])
|
||||
result = result .. pretty:format(mnem[oper], addr)
|
||||
end
|
||||
return result
|
||||
end
|
||||
vmz:boot():load({[0]=44,106,76,43,141,75,168,192,44,224,8,7,0,1})
|
||||
print("Disassembly of 7 x 8 (PRE-RUN):")
|
||||
print(vmz:dism())
|
||||
print("Disassembly of 7 x 8 (POST-RUN):")
|
||||
print(vmz:exec():dism())
|
||||
21
Task/Execute-Computer-Zero/Lua/execute-computer-zero-3.lua
Normal file
21
Task/Execute-Computer-Zero/Lua/execute-computer-zero-3.lua
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
-- <statement> ::= <opcode> <address>
|
||||
vmz.assm = function(self, source)
|
||||
local function oa2b(oper, addr) return oper * 32 + addr end
|
||||
local pc, objc = 0, { NOP=0, LDA=1, STA=2, ADD=3, SUB=4, BRZ=5, JMP=6, STP=7 }
|
||||
for oper, addr in source:gmatch("%s*(%a%a%a)%s*(%d*)") do
|
||||
self.mem[pc] = oa2b(objc[oper], tonumber(addr) or 0)
|
||||
pc = pc + 1
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
srcfibo = "LDA 14 STA 15 ADD 13 STA 14 LDA 15 STA 13 LDA 16 SUB 17 BRZ 11 STA 16 JMP 0 LDA 14 STP 0 NOP 1 NOP 1 NOP 0 NOP 8 NOP 1"
|
||||
print("Fibonacci = " .. vmz:boot():assm(srcfibo):exec().acc)
|
||||
|
||||
srclist = [[
|
||||
LDA 13 ADD 15 STA 5 ADD 16 STA 7 NOP 0 STA 14 NOP 0
|
||||
BRZ 11 STA 15 JMP 0 LDA 14 STP 0 LDA 0 NOP 0 NOP 28
|
||||
NOP 1 NOP 0 NOP 0 NOP 0 NOP 6 NOP 0 NOP 2 NOP 26
|
||||
NOP 5 NOP 20 NOP 3 NOP 30 NOP 1 NOP 22 NOP 4 NOP 24
|
||||
]]
|
||||
print("Linked list = " .. vmz:boot():assm(srclist):exec().acc)
|
||||
17
Task/Execute-Computer-Zero/Lua/execute-computer-zero-4.lua
Normal file
17
Task/Execute-Computer-Zero/Lua/execute-computer-zero-4.lua
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
vmz.peek = function(self,addr) return self.mem[addr] end
|
||||
vmz.poke = function(self,addr,byte) self.mem[addr]=byte end
|
||||
vmz.entr = function(self,byte) self.mem[self.pc]=byte self.pc=self.pc+1 end
|
||||
-- derived from the javascript "object code", rather than the descriptive "source code", as they appear to differ
|
||||
srcpris = [[
|
||||
NOP 0 NOP 0 STP 0 NOP 0 LDA 3 SUB 29 BRZ 18 LDA 3 STA 29 BRZ 14 LDA 1 ADD 31 STA 1 JMP 2 LDA 0 ADD 31
|
||||
STA 0 JMP 2 LDA 3 STA 29 LDA 1 ADD 30 ADD 3 STA 1 LDA 0 ADD 30 ADD 3 STA 0 JMP 2 NOP 0 NOP 1 NOP 3
|
||||
]]
|
||||
print("\nPrisoner (priming) = " .. vmz:boot():assm(srcpris):exec().acc)
|
||||
-- play five rounds,ie: poke 0 or 1 into mem[3], pc+=1, exec again
|
||||
mvnm = {[0]="coop", "defe"}
|
||||
for r = 1, 5 do
|
||||
local move = r%2 -- artificial stupidity?
|
||||
vmz:entr(move)
|
||||
vmz:exec()
|
||||
print("Round: " .. r .. " Move: " .. mvnm[move] .. " Player: " .. vmz:peek(0) .. " Computer: " .. vmz:peek(1))
|
||||
end
|
||||
127
Task/Execute-Computer-Zero/Nim/execute-computer-zero.nim
Normal file
127
Task/Execute-Computer-Zero/Nim/execute-computer-zero.nim
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
import std/strformat
|
||||
|
||||
type
|
||||
OpCode = enum opNOP, opLDA, opSTA, opADD, opSUB, opBRZ, opJMP, opSTP
|
||||
Instruction = byte
|
||||
Address = 0..31
|
||||
# Definition of a computer zero.
|
||||
Computer = object
|
||||
mem: array[Address, byte] # Memory.
|
||||
pc: Address # Program counter.
|
||||
acc: byte # Accumulator.
|
||||
Program = tuple
|
||||
name: string # Name of the program.
|
||||
code: seq[Instruction] # List of instructions.
|
||||
|
||||
proc split(inst: Instruction): tuple[code: OpCode, address: Address] =
|
||||
## Split an instruction into an opCode and a value.
|
||||
(OpCode((inst and 0b11100000u8) shr 5), Address(inst and 0b00011111u8))
|
||||
|
||||
proc toInst(opCode: OpCode; address: int): Instruction =
|
||||
## Build an instruction with given opcode and value.
|
||||
if address notin Address.low..Address.high:
|
||||
raise newException(ValueError, "address out of range.")
|
||||
byte(opCode) shl 5 or byte(address)
|
||||
|
||||
# Functions to build instructions.
|
||||
func NOP(n: int): Instruction = toInst(opNOP, n)
|
||||
func LDA(n: int): Instruction = toInst(opLDA, n)
|
||||
func STA(n: int): Instruction = toInst(opSTA, n)
|
||||
func ADD(n: int): Instruction = toInst(opADD, n)
|
||||
func SUB(n: int): Instruction = toInst(opSUB, n)
|
||||
func BRZ(n: int): Instruction = toInst(opBRZ, n)
|
||||
func JMP(n: int): Instruction = toInst(opJMP, n)
|
||||
func STP(n: int): Instruction = toInst(opSTP, n)
|
||||
|
||||
proc reset(comp: var Computer) =
|
||||
## Reset the computer state.
|
||||
comp.mem.reset()
|
||||
comp.pc = 0
|
||||
comp.acc = 0
|
||||
|
||||
proc load(comp: var Computer; program: Program) =
|
||||
## Load a program into a computer.
|
||||
comp.reset()
|
||||
var idx = 0
|
||||
for inst in program.code:
|
||||
comp.mem[idx] = inst
|
||||
inc idx
|
||||
|
||||
proc run(comp: var Computer) =
|
||||
## Run a computer.
|
||||
## The execution starts or resumes at the instruction
|
||||
## at current PC, with current value in the accumulator.
|
||||
while true:
|
||||
let (opCode, address) = comp.mem[comp.pc].split()
|
||||
inc comp.pc
|
||||
case opCode
|
||||
of opNOP:
|
||||
discard
|
||||
of opLDA:
|
||||
comp.acc = comp.mem[address]
|
||||
of opSTA:
|
||||
comp.mem[address] = comp.acc
|
||||
of opADD:
|
||||
comp.acc += comp.mem[address]
|
||||
of opSUB:
|
||||
comp.acc -= comp.mem[address]
|
||||
of opBRZ:
|
||||
if comp.acc == 0:
|
||||
comp.pc = address
|
||||
of opJMP:
|
||||
comp.pc = address
|
||||
of opSTP:
|
||||
break
|
||||
|
||||
proc enterValue(comp: var Computer; value: byte) =
|
||||
## Enter a value into memory at address given by the PC,
|
||||
## then increment the PC.
|
||||
comp.mem[comp.pc] = value
|
||||
inc comp.pc
|
||||
|
||||
|
||||
# Programs are built using the functions NOP, LDA, STA, etc.
|
||||
# To be able to use Uniform Function Call Syntax (i.e. call without parentheses),
|
||||
# all these functions have an argument, even NOP and STP.
|
||||
const
|
||||
Prog1 = (name: "2+2",
|
||||
code: @[LDA 3, ADD 4, STP 0, 2, 2])
|
||||
Prog2 = (name: "7*8",
|
||||
code: @[LDA 12, ADD 10, STA 12, LDA 11, SUB 13, STA 11, BRZ 8, JMP 0,
|
||||
LDA 12, STP 0, 8, 7, 0, 1])
|
||||
Prog3 = (name: "Fibonacci",
|
||||
code: @[LDA 14, STA 15, ADD 13, STA 14, LDA 15, STA 13, LDA 16, SUB 17,
|
||||
BRZ 11, STA 16, JMP 0, LDA 14, STP 0, 1, 1, 0,
|
||||
8, 1])
|
||||
Prog4 = (name: "List",
|
||||
code: @[LDA 13, ADD 15, STA 5, ADD 16, STA 7, NOP 0, STA 14, NOP 0,
|
||||
BRZ 11, STA 15, JMP 0, LDA 14, STP 0, LDA 0, 0, 28,
|
||||
1, 0, 0, 0, 6, 0, 2, 26,
|
||||
5, 20, 3, 30, 1, 22, 4, 24])
|
||||
Prog5 = (name: "Prisoner",
|
||||
code: @[NOP 0, NOP 0, STP 0, NOP 0, LDA 3, SUB 29, BRZ 18, LDA 3,
|
||||
STA 29, BRZ 14, LDA 1, ADD 31, STA 1, JMP 2, LDA 0, ADD 31,
|
||||
STA 0, JMP 2, LDA 3, STA 29, LDA 1, ADD 30, ADD 3, STA 1,
|
||||
LDA 0, ADD 30, ADD 3, STA 0, JMP 2, 0, 1, 3])
|
||||
|
||||
var computer: Computer
|
||||
|
||||
for prog in [Prog1, Prog2, Prog3, Prog4]:
|
||||
computer.load prog
|
||||
computer.run()
|
||||
echo &"Result for {prog.name}: {computer.acc}"
|
||||
|
||||
# "Prog5" is different as it stops and waits for an input from the user.
|
||||
# Input is stored at address 3 (current PC value) and scores are stored at addresses 0 and 1.
|
||||
|
||||
type Action = enum cooperate, defect
|
||||
|
||||
echo &"\nResult for {Prog5.name}:"
|
||||
computer.load Prog5
|
||||
computer.run()
|
||||
|
||||
for round in 1..5:
|
||||
let action = Action(round and 1)
|
||||
computer.enterValue(byte(action))
|
||||
computer.run()
|
||||
echo &"Round {round} Action: {action:9} Player: {computer.mem[0]} Computer: {computer.mem[1]}"
|
||||
110
Task/Execute-Computer-Zero/PL-M/execute-computer-zero.plm
Normal file
110
Task/Execute-Computer-Zero/PL-M/execute-computer-zero.plm
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
100H: /* EXECUTE SOME COMPUTERZERO PROGRAMS */
|
||||
|
||||
/* CP/M SYSTEM CALL AND I/O ROUTINES */
|
||||
BDOS: PROCEDURE( FN, ARG ); DECLARE FN BYTE, ARG ADDRESS; GOTO 5; END;
|
||||
PR$CHAR: PROCEDURE( C ); DECLARE C BYTE; CALL BDOS( 2, C ); END;
|
||||
PR$STRING: PROCEDURE( S ); DECLARE S ADDRESS; CALL BDOS( 9, S ); END;
|
||||
PR$NL: PROCEDURE; CALL PR$CHAR( 0DH ); CALL PR$CHAR( 0AH ); END;
|
||||
PR$NUMBER: PROCEDURE( N ); /* PRINTS A NUMBER IN THE MINIMUN FIELD WIDTH */
|
||||
DECLARE N ADDRESS;
|
||||
DECLARE V ADDRESS, N$STR ( 6 )BYTE, W BYTE;
|
||||
V = N;
|
||||
W = LAST( N$STR );
|
||||
N$STR( W ) = '$';
|
||||
N$STR( W := W - 1 ) = '0' + ( V MOD 10 );
|
||||
DO WHILE( ( V := V / 10 ) > 0 );
|
||||
N$STR( W := W - 1 ) = '0' + ( V MOD 10 );
|
||||
END;
|
||||
CALL PR$STRING( .N$STR( W ) );
|
||||
END PR$NUMBER;
|
||||
|
||||
/* TASK */
|
||||
|
||||
DECLARE FALSE LITERALLY '0'
|
||||
, TRUE LITERALLY '0FFH'
|
||||
;
|
||||
DECLARE NOP$C LITERALLY '0' /* INSTRUCTION CODES */
|
||||
, LDA$C LITERALLY '32'
|
||||
, STA$C LITERALLY '(2*32)'
|
||||
, ADD$C LITERALLY '(3*32)'
|
||||
, SUB$C LITERALLY '(4*32)'
|
||||
, BRZ$C LITERALLY '(5*32)'
|
||||
, JMP$C LITERALLY '(6*32)'
|
||||
, STP$C LITERALLY '(7*32)'
|
||||
;
|
||||
DECLARE CODE LITERALLY 'PC=255' /* ASSEMBLER MNEMONICS */
|
||||
, LOAD LITERALLY 'PC=PC+1;PGM(PC)='
|
||||
, NOP LITERALLY 'LOAD NOP$C'
|
||||
, LDA LITERALLY 'LOAD LDA$C+'
|
||||
, STA LITERALLY 'LOAD STA$C+'
|
||||
, ADD LITERALLY 'LOAD ADD$C+'
|
||||
, SUB LITERALLY 'LOAD SUB$C+'
|
||||
, BRZ LITERALLY 'LOAD BRZ$C+'
|
||||
, JMP LITERALLY 'LOAD JMP$C+'
|
||||
, STP LITERALLY 'LOAD STP$C '
|
||||
, VAL LITERALLY 'LOAD '
|
||||
, EDOC LITERALLY 'CALL EXECUTE'
|
||||
;
|
||||
DECLARE PGM (32)BYTE; /* THE PROGRAM */
|
||||
DECLARE PC BYTE; /* PROGRAM COUNTER */
|
||||
EXECUTE: PROCEDURE; /* EXECUTES THE PROGRAM */
|
||||
DECLARE ( RUNNING, A, OP, OPERAND ) BYTE;
|
||||
PC, A = 0;
|
||||
RUNNING = TRUE;
|
||||
DO WHILE RUNNING;
|
||||
OP = PGM( PC ) AND 0E0H;
|
||||
OPERAND = PGM( PC ) AND 1FH;
|
||||
PC = ( PC + 1 ) MOD 32;
|
||||
IF OP = NOP$C THEN DO; /* NOTHING */ END;
|
||||
ELSE IF OP = LDA$C THEN A = PGM( OPERAND );
|
||||
ELSE IF OP = STA$C THEN PGM( OPERAND ) = A;
|
||||
ELSE IF OP = ADD$C THEN A = A + PGM( OPERAND );
|
||||
ELSE IF OP = SUB$C THEN A = A - PGM( OPERAND );
|
||||
ELSE IF OP = BRZ$C THEN DO; IF A = 0 THEN PC = OPERAND MOD 32; END;
|
||||
ELSE IF OP = JMP$C THEN PC = OPERAND MOD 32;
|
||||
ELSE DO; /* MUST BE STP$C */
|
||||
RUNNING = FALSE;
|
||||
CALL PR$NUMBER( A );
|
||||
CALL PR$NL;
|
||||
END;
|
||||
END;
|
||||
END EXECUTE ;
|
||||
/* TEST PROGRAMS (FROM THE COMPUTER ZERO WEBSITE) */
|
||||
CALL PR$STRING( .' 2+2: $' );
|
||||
CODE; LDA 3; ADD 4; STP; VAL 2; VAL 2; EDOC;
|
||||
|
||||
CALL PR$STRING( .' 7*8: $' );
|
||||
CODE; LDA 12; ADD 10; STA 12; LDA 11; SUB 13; STA 11; BRZ 8; JMP 0;
|
||||
LDA 12; STP; VAL 8; VAL 7; VAL 0; VAL 1;
|
||||
EDOC;
|
||||
|
||||
CALL PR$STRING( .' FIBONACCI: $' );
|
||||
CODE; LDA 14; STA 15; ADD 13; STA 14; LDA 15; STA 13; LDA 16; SUB 17;
|
||||
BRZ 11; STA 16; JMP 0; LDA 14; STP;
|
||||
VAL 1; VAL 1; VAL 0; VAL 8; VAL 1;
|
||||
EDOC;
|
||||
|
||||
CALL PR$STRING( .'LINKEDLIST: $' );
|
||||
CODE; LDA 13; ADD 15; STA 5; ADD 16; STA 7; NOP; STA 14; NOP;
|
||||
BRZ 11; STA 15; JMP 0; LDA 14; STP; LDA 0; VAL 0; VAL 28;
|
||||
VAL 1; VAL 0; VAL 0; VAL 0; VAL 6; VAL 0; VAL 2; VAL 26;
|
||||
VAL 5; VAL 20; VAL 3; VAL 30; VAL 1; VAL 22; VAL 4; VAL 24;
|
||||
EDOC;
|
||||
|
||||
CALL PR$STRING( .' PRISONER: $' );
|
||||
CODE; NOP; NOP; STP; VAL 0; LDA 3; SUB 29; BRZ 18; LDA 3;
|
||||
STA 29; BRZ 14; LDA 1; ADD 31; STA 1; JMP 2; LDA 0; ADD 31;
|
||||
STA 0; JMP 2; LDA 3; STA 29; LDA 1; ADD 30; ADD 3; STA 1;
|
||||
LDA 0; ADD 30; ADD 3; STA 0; JMP 2; VAL 0; VAL 1; VAL 3;
|
||||
EDOC;
|
||||
|
||||
/* SUBTRACTIONS YIELDING NEGATIVE RESULTS */
|
||||
CALL PR$STRING( .' 0-255: $' );
|
||||
CODE; LDA 3; SUB 4; STP; VAL 0; VAL 255; EDOC;
|
||||
CALL PR$STRING( .' 0-1: $' );
|
||||
CODE; LDA 3; SUB 4; STP; VAL 0; VAL 1; EDOC;
|
||||
/* OVERFLOW ON ADDITION */
|
||||
CALL PR$STRING( .' 1+255: $' );
|
||||
CODE; LDA 3; ADD 4; STP; VAL 1; VAL 255; EDOC;
|
||||
|
||||
EOF
|
||||
53
Task/Execute-Computer-Zero/Phix/execute-computer-zero.phix
Normal file
53
Task/Execute-Computer-Zero/Phix/execute-computer-zero.phix
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">NOP</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0b000_00000</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- no operation</span>
|
||||
<span style="color: #000000;">LDA</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0b001_00000</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- load accumulator, a := memory [xxxxx]</span>
|
||||
<span style="color: #000000;">STA</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0b010_00000</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- store accumulator, memory [xxxxx] := a</span>
|
||||
<span style="color: #000000;">ADD</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0b011_00000</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- add, a := a + memory [xxxxx]</span>
|
||||
<span style="color: #000000;">SUB</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0b100_00000</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- subtract, a := a – memory [xxxxx]</span>
|
||||
<span style="color: #000000;">BRZ</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0b101_00000</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- branch on zero, if a = 0 then goto xxxxx</span>
|
||||
<span style="color: #000000;">JMP</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0b110_00000</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- jump, goto xxxxx</span>
|
||||
<span style="color: #000000;">STP</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0b111_00000</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- stop</span>
|
||||
<span style="color: #000000;">OP</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0b111_00000</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- operator mask</span>
|
||||
<span style="color: #000000;">ARG</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0b000_11111</span> <span style="color: #000080;font-style:italic;">-- memory location (0 based)</span>
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">execute</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">name</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">program</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">memory</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">program</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">pc</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
|
||||
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">ppc</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">memory</span><span style="color: #0000FF;">[</span><span style="color: #000000;">pc</span><span style="color: #0000FF;">],</span>
|
||||
<span style="color: #000000;">op</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">and_bitsu</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ppc</span><span style="color: #0000FF;">,</span><span style="color: #000000;">OP</span><span style="color: #0000FF;">),</span>
|
||||
<span style="color: #000000;">arg</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ppc</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ARG</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span>
|
||||
<span style="color: #000000;">pc</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
|
||||
<span style="color: #008080;">switch</span> <span style="color: #000000;">op</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #008080;">case</span> <span style="color: #000000;">NOP</span><span style="color: #0000FF;">:</span> <span style="color: #008080;">break</span>
|
||||
<span style="color: #008080;">case</span> <span style="color: #000000;">LDA</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">memory</span><span style="color: #0000FF;">[</span><span style="color: #000000;">arg</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">case</span> <span style="color: #000000;">STA</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">memory</span><span style="color: #0000FF;">[</span><span style="color: #000000;">arg</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">a</span>
|
||||
<span style="color: #008080;">case</span> <span style="color: #000000;">ADD</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">and_bitsu</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">+</span><span style="color: #000000;">memory</span><span style="color: #0000FF;">[</span><span style="color: #000000;">arg</span><span style="color: #0000FF;">],</span><span style="color: #000000;">#FF</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">case</span> <span style="color: #000000;">SUB</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">and_bitsu</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">-</span><span style="color: #000000;">memory</span><span style="color: #0000FF;">[</span><span style="color: #000000;">arg</span><span style="color: #0000FF;">],</span><span style="color: #000000;">#FF</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">case</span> <span style="color: #000000;">BRZ</span><span style="color: #0000FF;">:</span> <span style="color: #008080;">if</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">pc</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">arg</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">case</span> <span style="color: #000000;">JMP</span><span style="color: #0000FF;">:</span> <span style="color: #000000;">pc</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">arg</span>
|
||||
<span style="color: #008080;">case</span> <span style="color: #000000;">STP</span><span style="color: #0000FF;">:</span> <span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%12s: %3d\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">name</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #008080;">return</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">switch</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
|
||||
<span style="color: #000000;">execute</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"2+2"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">LDA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ADD</span><span style="color: #0000FF;">+</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STP</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #000000;">execute</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"7*8"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">LDA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">12</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ADD</span><span style="color: #0000FF;">+</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">12</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">LDA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">SUB</span><span style="color: #0000FF;">+</span><span style="color: #000000;">13</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">BRZ</span><span style="color: #0000FF;">+</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">JMP</span><span style="color: #0000FF;">+</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">LDA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">12</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STP</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #000000;">execute</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"fibonacci"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">LDA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">14</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">15</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ADD</span><span style="color: #0000FF;">+</span><span style="color: #000000;">13</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">14</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">LDA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">15</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">13</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">LDA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">16</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">SUB</span><span style="color: #0000FF;">+</span><span style="color: #000000;">17</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">BRZ</span><span style="color: #0000FF;">+</span><span style="color: #000000;">11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">16</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">JMP</span><span style="color: #0000FF;">+</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">LDA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">14</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STP</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #000000;">execute</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"linkedList"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">LDA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">13</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ADD</span><span style="color: #0000FF;">+</span><span style="color: #000000;">15</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ADD</span><span style="color: #0000FF;">+</span><span style="color: #000000;">16</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">NOP</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">14</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">NOP</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">BRZ</span><span style="color: #0000FF;">+</span><span style="color: #000000;">11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">15</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">JMP</span><span style="color: #0000FF;">+</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">LDA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">14</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STP</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">LDA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">28</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">26</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">20</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">30</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">22</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span><span style="color: #000000;">24</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #000000;">execute</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"prisoner"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">NOP</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">NOP</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STP</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">LDA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">SUB</span><span style="color: #0000FF;">+</span><span style="color: #000000;">29</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">BRZ</span><span style="color: #0000FF;">+</span><span style="color: #000000;">18</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">LDA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">29</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">BRZ</span><span style="color: #0000FF;">+</span><span style="color: #000000;">14</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">LDA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ADD</span><span style="color: #0000FF;">+</span><span style="color: #000000;">31</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">JMP</span><span style="color: #0000FF;">+</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">LDA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ADD</span><span style="color: #0000FF;">+</span><span style="color: #000000;">31</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">JMP</span><span style="color: #0000FF;">+</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">LDA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">29</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">LDA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ADD</span><span style="color: #0000FF;">+</span><span style="color: #000000;">30</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ADD</span><span style="color: #0000FF;">+</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">LDA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">ADD</span><span style="color: #0000FF;">+</span><span style="color: #000000;">30</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ADD</span><span style="color: #0000FF;">+</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">JMP</span><span style="color: #0000FF;">+</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #000080;font-style:italic;">-- subtractions yielding negative results</span>
|
||||
<span style="color: #000000;">execute</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"0-255"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">LDA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">SUB</span><span style="color: #0000FF;">+</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span><span style="color: #000000;">STP</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">255</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #000000;">execute</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"0-1"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">LDA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">SUB</span><span style="color: #0000FF;">+</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STP</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #000080;font-style:italic;">-- overflow on addition</span>
|
||||
<span style="color: #000000;">execute</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"1+255"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">LDA</span><span style="color: #0000FF;">+</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ADD</span><span style="color: #0000FF;">+</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">STP</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">255</span><span style="color: #0000FF;">})</span>
|
||||
<!--
|
||||
270
Task/Execute-Computer-Zero/Python/execute-computer-zero.py
Normal file
270
Task/Execute-Computer-Zero/Python/execute-computer-zero.py
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
"""Computer/zero Assembly emulator. Requires Python >= 3.7"""
|
||||
|
||||
import re
|
||||
|
||||
from typing import Dict
|
||||
from typing import Iterable
|
||||
from typing import List
|
||||
from typing import NamedTuple
|
||||
from typing import Optional
|
||||
from typing import Tuple
|
||||
|
||||
|
||||
NOP = 0b000
|
||||
LDA = 0b001
|
||||
STA = 0b010
|
||||
ADD = 0b011
|
||||
SUB = 0b100
|
||||
BRZ = 0b101
|
||||
JMP = 0b110
|
||||
STP = 0b111
|
||||
|
||||
OPCODES = {
|
||||
"NOP": NOP,
|
||||
"LDA": LDA,
|
||||
"STA": STA,
|
||||
"ADD": ADD,
|
||||
"SUB": SUB,
|
||||
"BRZ": BRZ,
|
||||
"JMP": JMP,
|
||||
"STP": STP,
|
||||
}
|
||||
|
||||
RE_INSTRUCTION = re.compile(
|
||||
r"\s*"
|
||||
r"(?:(?P<label>\w+):)?"
|
||||
r"\s*"
|
||||
rf"(?P<opcode>{'|'.join(OPCODES)})?"
|
||||
r"\s*"
|
||||
r"(?P<argument>\w+)?"
|
||||
r"\s*"
|
||||
r"(?:;(?P<comment>[\w\s]+))?"
|
||||
)
|
||||
|
||||
|
||||
class AssemblySyntaxError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Instruction(NamedTuple):
|
||||
label: Optional[str]
|
||||
opcode: Optional[str]
|
||||
argument: Optional[str]
|
||||
comment: Optional[str]
|
||||
|
||||
|
||||
def parse(assembly: str) -> Tuple[List[Instruction], Dict[str, int]]:
|
||||
instructions: List[Instruction] = []
|
||||
labels: Dict[str, int] = {}
|
||||
linenum: int = 0
|
||||
|
||||
for line in assembly.split("\n"):
|
||||
match = RE_INSTRUCTION.match(line)
|
||||
|
||||
if not match:
|
||||
raise AssemblySyntaxError(f"{line}: {linenum}")
|
||||
|
||||
instructions.append(Instruction(**match.groupdict()))
|
||||
label = match.group(1)
|
||||
if label:
|
||||
labels[label] = linenum
|
||||
|
||||
linenum += 1
|
||||
|
||||
return instructions, labels
|
||||
|
||||
|
||||
def compile(instructions: List[Instruction], labels: Dict[str, int]) -> Iterable[int]:
|
||||
for instruction in instructions:
|
||||
if instruction.argument is None:
|
||||
argument = 0
|
||||
elif instruction.argument.isnumeric():
|
||||
argument = int(instruction.argument)
|
||||
else:
|
||||
argument = labels[instruction.argument]
|
||||
|
||||
if instruction.opcode:
|
||||
yield OPCODES[instruction.opcode] << 5 | argument
|
||||
else:
|
||||
yield argument
|
||||
|
||||
|
||||
def run(bytecode: bytes) -> int:
|
||||
accumulator = 0
|
||||
program_counter = 0
|
||||
memory = list(bytecode)[:32] + [0 for _ in range(32 - len(bytecode))]
|
||||
|
||||
while program_counter < 32:
|
||||
operation = memory[program_counter] >> 5
|
||||
argument = memory[program_counter] & 0b11111
|
||||
program_counter += 1
|
||||
|
||||
if operation == NOP:
|
||||
continue
|
||||
elif operation == LDA:
|
||||
accumulator = memory[argument]
|
||||
elif operation == STA:
|
||||
memory[argument] = accumulator
|
||||
elif operation == ADD:
|
||||
accumulator = (accumulator + memory[argument]) % 256
|
||||
elif operation == SUB:
|
||||
accumulator = (accumulator - memory[argument]) % 256
|
||||
elif operation == BRZ:
|
||||
if accumulator == 0:
|
||||
program_counter = argument
|
||||
elif operation == JMP:
|
||||
program_counter = argument
|
||||
elif operation == STP:
|
||||
break
|
||||
else:
|
||||
raise Exception(f"error: {operation} {argument}")
|
||||
|
||||
return accumulator
|
||||
|
||||
|
||||
SAMPLES = [
|
||||
"""\
|
||||
LDA x
|
||||
ADD y ; accumulator = x + y
|
||||
STP
|
||||
x: 2
|
||||
y: 2
|
||||
""",
|
||||
"""\
|
||||
loop: LDA prodt
|
||||
ADD x
|
||||
STA prodt
|
||||
LDA y
|
||||
SUB one
|
||||
STA y
|
||||
BRZ done
|
||||
JMP loop
|
||||
done: LDA prodt ; to display it
|
||||
STP
|
||||
x: 8
|
||||
y: 7
|
||||
prodt: 0
|
||||
one: 1
|
||||
""",
|
||||
"""\
|
||||
loop: LDA n
|
||||
STA temp
|
||||
ADD m
|
||||
STA n
|
||||
LDA temp
|
||||
STA m
|
||||
LDA count
|
||||
SUB one
|
||||
BRZ done
|
||||
STA count
|
||||
JMP loop
|
||||
done: LDA n ; to display it
|
||||
STP
|
||||
m: 1
|
||||
n: 1
|
||||
temp: 0
|
||||
count: 8 ; valid range: 1-11
|
||||
one: 1
|
||||
""",
|
||||
"""\
|
||||
start: LDA load
|
||||
ADD car ; head of list
|
||||
STA ldcar
|
||||
ADD one
|
||||
STA ldcdr ; next CONS cell
|
||||
ldcar: NOP
|
||||
STA value
|
||||
ldcdr: NOP
|
||||
BRZ done ; 0 stands for NIL
|
||||
STA car
|
||||
JMP start
|
||||
done: LDA value ; CAR of last CONS
|
||||
STP
|
||||
load: LDA 0
|
||||
value: 0
|
||||
car: 28
|
||||
one: 1
|
||||
; order of CONS cells
|
||||
; in memory
|
||||
; does not matter
|
||||
6
|
||||
0 ; 0 stands for NIL
|
||||
2 ; (CADR ls)
|
||||
26 ; (CDDR ls) -- etc.
|
||||
5
|
||||
20
|
||||
3
|
||||
30
|
||||
1 ; value of (CAR ls)
|
||||
22 ; points to (CDR ls)
|
||||
4
|
||||
24
|
||||
""",
|
||||
"""\
|
||||
p: 0 ; NOP in first round
|
||||
c: 0
|
||||
start: STP ; wait for p's move
|
||||
pmove: NOP
|
||||
LDA pmove
|
||||
SUB cmove
|
||||
BRZ same
|
||||
LDA pmove
|
||||
STA cmove ; tit for tat
|
||||
BRZ cdeft
|
||||
LDA c ; p defected, c did not
|
||||
ADD three
|
||||
STA c
|
||||
JMP start
|
||||
cdeft: LDA p
|
||||
ADD three
|
||||
STA p
|
||||
JMP start
|
||||
same: LDA pmove
|
||||
STA cmove ; tit for tat
|
||||
LDA p
|
||||
ADD one
|
||||
ADD pmove
|
||||
STA p
|
||||
LDA c
|
||||
ADD one
|
||||
ADD pmove
|
||||
STA c
|
||||
JMP start
|
||||
cmove: 0 ; co-operate initially
|
||||
one: 1
|
||||
three: 3
|
||||
""",
|
||||
"""\
|
||||
LDA 3
|
||||
SUB 4
|
||||
STP 0
|
||||
0
|
||||
255
|
||||
""",
|
||||
"""\
|
||||
LDA 3
|
||||
SUB 4
|
||||
STP 0
|
||||
0
|
||||
1
|
||||
""",
|
||||
"""\
|
||||
LDA 3
|
||||
ADD 4
|
||||
STP 0
|
||||
1
|
||||
255
|
||||
""",
|
||||
]
|
||||
|
||||
|
||||
def main() -> None:
|
||||
for sample in SAMPLES:
|
||||
instructions, labels = parse(sample)
|
||||
bytecode = bytes(compile(instructions, labels))
|
||||
result = run(bytecode)
|
||||
print(result)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
41
Task/Execute-Computer-Zero/Raku/execute-computer-zero.raku
Normal file
41
Task/Execute-Computer-Zero/Raku/execute-computer-zero.raku
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
my (@mem, $ip, $acc); # memory, instruction pointer, accumulator
|
||||
|
||||
sub load (@program) {
|
||||
die "memory exceeded" if +@program > 32;
|
||||
$ip = 0;
|
||||
$acc = 0;
|
||||
@mem = @program »%» 256;
|
||||
}
|
||||
|
||||
sub execute (*@program) {
|
||||
load @program;
|
||||
loop {
|
||||
my $reg = @mem[$ip];
|
||||
quietly my ($inst, $data) = $reg +> 5 +& 7, $reg +& 31;
|
||||
given $inst {
|
||||
when 0 { #`{ NOP } }
|
||||
when 1 { #`{ LDA } $acc = @mem[$data] }
|
||||
when 2 { #`{ STA } @mem[$data] = $acc }
|
||||
when 3 { #`{ ADD } $acc += @mem[$data] }
|
||||
when 4 { #`{ SUB } $acc -= @mem[$data] }
|
||||
when 5 { #`{ BRZ } $ip = $data - 1 unless $acc }
|
||||
when 6 { #`{ JMP } $ip = $data - 1 }
|
||||
when 7 { #`{ STP } last }
|
||||
default { die 'Invalid instruction' }
|
||||
}
|
||||
++$ip;
|
||||
last if $ip == 32;
|
||||
}
|
||||
$acc
|
||||
}
|
||||
|
||||
say "2 + 2 = " ~ execute 35,100,224,2,2;
|
||||
say "7 x 8 = " ~ execute 44,106,76,43,141,75,168,192,44,224,8,7,0,1;
|
||||
say "Fibonacci: " ~
|
||||
execute 46,79,109,78,47,77,48,145,171,80,192,46,224,1,1,0,8,1;
|
||||
say "Linked list: " ~
|
||||
execute 45,111,69,112,71,0,78,0,171,79,192,46,
|
||||
224,32,0,28,1,0,0,0,6,0,2,26,5,20,3,30,1,22,4,24;
|
||||
say "Prisoners dilemma: " ~
|
||||
execute 0,0,224,0,35,157,178,35,93,174,33,127,65,194,
|
||||
32,127,64,194,35,93,33,126,99,65,32,126,99,64,194,0,1,3;
|
||||
177
Task/Execute-Computer-Zero/Wren/execute-computer-zero.wren
Normal file
177
Task/Execute-Computer-Zero/Wren/execute-computer-zero.wren
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
var NOP = 0
|
||||
var LDA = 1
|
||||
var STA = 2
|
||||
var ADD = 3
|
||||
var SUB = 4
|
||||
var BRZ = 5
|
||||
var JMP = 6
|
||||
var STP = 7
|
||||
|
||||
var ops = {"NOP": NOP, "LDA": LDA, "STA": STA, "ADD": ADD,
|
||||
"SUB": SUB, "BRZ": BRZ, "JMP": JMP, "STP": STP}
|
||||
|
||||
var load = Fn.new { |prog|
|
||||
var mem = List.filled(32, 0)
|
||||
var lines = prog.trimEnd().split("\n")
|
||||
for (i in 0...lines.count) {
|
||||
var line = lines[i].trim()
|
||||
var split = line.split(" ")
|
||||
var instr = split[0]
|
||||
var addr = 0
|
||||
if (split.count == 2) addr = Num.fromString(split[1])
|
||||
if (ops[instr]) {
|
||||
mem[i] = ops[instr] * 32 + addr
|
||||
} else {
|
||||
var v = Num.fromString(instr)
|
||||
if (v) mem[i] = v
|
||||
}
|
||||
}
|
||||
return mem
|
||||
}
|
||||
|
||||
var output = Fn.new { |acc|
|
||||
System.print(acc)
|
||||
}
|
||||
|
||||
var interp = Fn.new { |prog|
|
||||
var acc = 0
|
||||
var pc = 0
|
||||
var mem = load.call(prog)
|
||||
while (true) {
|
||||
var instr = mem[pc] >> 5
|
||||
var addr = mem[pc] % 32
|
||||
pc = pc + 1
|
||||
if (instr == LDA) {
|
||||
acc = mem[addr]
|
||||
} else if (instr == STA) {
|
||||
mem[addr] = acc
|
||||
} else if (instr == ADD) {
|
||||
acc = acc + mem[addr]
|
||||
if (acc > 255) acc = acc - 256
|
||||
} else if (instr == SUB) {
|
||||
acc = acc - mem[addr]
|
||||
if (acc < 0) acc = acc + 256
|
||||
} else if (instr == BRZ) {
|
||||
if (acc == 0) pc = addr
|
||||
} else if (instr == JMP) {
|
||||
pc = addr
|
||||
}
|
||||
if (instr == STP || pc > 31) break
|
||||
}
|
||||
output.call(acc)
|
||||
}
|
||||
|
||||
var progs = [
|
||||
"""
|
||||
LDA 3
|
||||
ADD 4
|
||||
STP
|
||||
2
|
||||
2
|
||||
""",
|
||||
"""
|
||||
LDA 12
|
||||
ADD 10
|
||||
STA 12
|
||||
LDA 11
|
||||
SUB 13
|
||||
STA 11
|
||||
BRZ 8
|
||||
JMP 0
|
||||
LDA 12
|
||||
STP
|
||||
8
|
||||
7
|
||||
0
|
||||
1
|
||||
""",
|
||||
"""
|
||||
LDA 14
|
||||
STA 15
|
||||
ADD 13
|
||||
STA 14
|
||||
LDA 15
|
||||
STA 13
|
||||
LDA 16
|
||||
SUB 17
|
||||
BRZ 11
|
||||
STA 16
|
||||
JMP 0
|
||||
LDA 14
|
||||
STP
|
||||
1
|
||||
1
|
||||
0
|
||||
8
|
||||
1
|
||||
""",
|
||||
"""
|
||||
LDA 13
|
||||
ADD 15
|
||||
STA 5
|
||||
ADD 16
|
||||
STA 7
|
||||
NOP
|
||||
STA 14
|
||||
NOP
|
||||
BRZ 11
|
||||
STA 15
|
||||
JMP 0
|
||||
LDA 14
|
||||
STP
|
||||
LDA 0
|
||||
0
|
||||
28
|
||||
1
|
||||
|
||||
|
||||
|
||||
6
|
||||
0
|
||||
2
|
||||
26
|
||||
5
|
||||
20
|
||||
3
|
||||
30
|
||||
1
|
||||
22
|
||||
4
|
||||
24
|
||||
""",
|
||||
"""
|
||||
0
|
||||
0
|
||||
STP
|
||||
NOP
|
||||
LDA 3
|
||||
SUB 29
|
||||
BRZ 18
|
||||
LDA 3
|
||||
STA 29
|
||||
BRZ 14
|
||||
LDA 1
|
||||
ADD 31
|
||||
STA 1
|
||||
JMP 2
|
||||
LDA 0
|
||||
ADD 31
|
||||
STA 0
|
||||
JMP 2
|
||||
LDA 3
|
||||
STA 29
|
||||
LDA 0
|
||||
ADD 30
|
||||
ADD 3
|
||||
STA 0
|
||||
LDA 1
|
||||
ADD 30
|
||||
ADD 3
|
||||
STA 1
|
||||
JMP 2
|
||||
0
|
||||
1
|
||||
3
|
||||
"""
|
||||
]
|
||||
for (prog in progs) interp.call(prog)
|
||||
78
Task/Execute-Computer-Zero/XPL0/execute-computer-zero.xpl0
Normal file
78
Task/Execute-Computer-Zero/XPL0/execute-computer-zero.xpl0
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
def NOP=0, LDA=1, STA=2, ADD=3, SUB=4, BRZ=5, JMP=6, STP=7;
|
||||
char Mem(32);
|
||||
string 0;
|
||||
|
||||
proc Load(Prog); \Load program into memory
|
||||
char Prog;
|
||||
int PC, I, Ch, Hash;
|
||||
|
||||
func GetNum; \Return value of number
|
||||
int Num;
|
||||
[while Ch <= $20 do
|
||||
[Ch:= Prog(I); I:= I+1];
|
||||
Num:= 0;
|
||||
while Ch>=^0 and Ch<=^9 do
|
||||
[Num:= Num*10 + Ch - ^0;
|
||||
Ch:= Prog(I); I:= I+1;
|
||||
];
|
||||
return Num;
|
||||
];
|
||||
|
||||
[PC:= 0; I:= 0;
|
||||
repeat repeat Ch:= Prog(I); I:= I+1; until Ch > $20;
|
||||
if Ch>=^0 and Ch<=^9 then
|
||||
Mem(PC):= GetNum
|
||||
else [Hash:= 0;
|
||||
while Ch >= ^A do
|
||||
[Hash:= Hash + Ch;
|
||||
Ch:= Prog(I); I:= I+1;
|
||||
];
|
||||
case Hash of
|
||||
^N+^O+^P: Mem(PC):= NOP<<5;
|
||||
^L+^D+^A: Mem(PC):= LDA<<5 + GetNum;
|
||||
^S+^T+^A: Mem(PC):= STA<<5 + GetNum;
|
||||
^A+^D+^D: Mem(PC):= ADD<<5 + GetNum;
|
||||
^S+^U+^B: Mem(PC):= SUB<<5 + GetNum;
|
||||
^B+^R+^Z: Mem(PC):= BRZ<<5 + GetNum;
|
||||
^J+^M+^P: Mem(PC):= JMP<<5 + GetNum;
|
||||
^S+^T+^P: Mem(PC):= STP<<5
|
||||
other [Text(0, "Bad opcode at "); IntOut(0, PC); exit];
|
||||
];
|
||||
PC:= PC+1;
|
||||
until Ch = 0;
|
||||
];
|
||||
|
||||
proc Run(Prog); \Load and run a program
|
||||
int Prog, PC, Acc, Instr, Addr;
|
||||
[Load(Prog);
|
||||
PC:= 0; Acc:= 0;
|
||||
loop [Instr:= Mem(PC) >> 5;
|
||||
Addr:= Mem(PC) & $1F;
|
||||
PC:= PC+1;
|
||||
case Instr of
|
||||
LDA: Acc:= Mem(Addr);
|
||||
STA: Mem(Addr):= Acc;
|
||||
ADD: Acc:= Acc + Mem(Addr) & $FF;
|
||||
SUB: Acc:= Acc - Mem(Addr) & $FF;
|
||||
BRZ: if Acc = 0 then PC:= Addr;
|
||||
JMP: PC:= Addr;
|
||||
STP: quit
|
||||
other []; \NOP
|
||||
if PC > 31 then quit;
|
||||
];
|
||||
IntOut(0, Acc); CrLf(0);
|
||||
];
|
||||
|
||||
int Progs, N;
|
||||
[Progs:= [
|
||||
"LDA 3 ADD 4 STP 2 2",
|
||||
"LDA 12 ADD 10 STA 12 LDA 11 SUB 13 STA 11 BRZ 8 JMP 0 LDA 12 STP 8 7 0 1",
|
||||
"LDA 14 STA 15 ADD 13 STA 14 LDA 15 STA 13 LDA 16 SUB 17 BRZ 11 STA 16 JMP 0
|
||||
LDA 14 STP 1 1 0 8 1",
|
||||
"LDA 13 ADD 15 STA 5 ADD 16 STA 7 NOP STA 14 NOP BRZ 11 STA 15 JMP 0 LDA 14
|
||||
STP LDA 0 0 28 1 0 0 0 6 0 2 26 5 20 3 30 1 22 4 24",
|
||||
"0 0 STP NOP LDA 3 SUB 29 BRZ 18 LDA 3 STA 29 BRZ 14 LDA 1 ADD 31 STA 1
|
||||
JMP 2 LDA 0 ADD 31 STA 0 JMP 2 LDA 3 STA 29 LDA 0 ADD 30 ADD 3 STA 0 LDA 1
|
||||
ADD 30 ADD 3 STA 1 JMP 2 0 1 3"];
|
||||
for N:= 0 to 4 do Run(Progs(N));
|
||||
]
|
||||
|
|
@ -0,0 +1,195 @@
|
|||
org &1000
|
||||
PrintChar equ &BB5A
|
||||
|
||||
;reg usage:
|
||||
;DE = VM'S Program Counter
|
||||
;IXL = VM's Accumulator
|
||||
main:
|
||||
ld ixl,0
|
||||
ld de,Computer_Zero_RAM_2_plus_2
|
||||
call Computer_Zero_VM
|
||||
ld a,ixl
|
||||
call ShowHex ;output to Amstrad CPC's screen
|
||||
call NewLine
|
||||
|
||||
ld ixl,0
|
||||
ld de,Computer_Zero_RAM_7x8
|
||||
call Computer_Zero_VM
|
||||
ld a,ixl
|
||||
jp ShowHex ;output and return to basic.
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;these two functions are related to displaying the output
|
||||
; and have nothing to do with the virtual machine itself.
|
||||
ShowHex:
|
||||
push af
|
||||
and %11110000
|
||||
rrca
|
||||
rrca
|
||||
rrca
|
||||
rrca
|
||||
call PrintHexChar
|
||||
pop af
|
||||
and %00001111
|
||||
;call PrintHexChar
|
||||
;execution flows into it naturally.
|
||||
PrintHexChar:
|
||||
;converts hex to ascii
|
||||
or a ;Clear Carry Flag
|
||||
daa
|
||||
add a,&F0
|
||||
adc a,&40
|
||||
jp PrintChar
|
||||
|
||||
NewLine:
|
||||
push af
|
||||
ld a,13
|
||||
call PrintChar
|
||||
ld a,10
|
||||
call PrintChar
|
||||
pop af
|
||||
ret
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
Computer_Zero_VM:
|
||||
ld a,(de) ;opcode fetch
|
||||
call UnpackOpcode ;stores opcode in B, operand in C
|
||||
push de
|
||||
ld de,Opcode_Table
|
||||
ld a,b
|
||||
rlca ;index times 2 for word data
|
||||
|
||||
ld e,a
|
||||
ld a,(de)
|
||||
ld L,a
|
||||
inc de
|
||||
ld a,(de)
|
||||
ld h,a ;LD HL,(DE)
|
||||
|
||||
pop de
|
||||
jp (hl)
|
||||
;register state after this jump:
|
||||
;DE = program counter
|
||||
;HL = address of instruction implementation
|
||||
;C = operand of the instruction we're about to execute
|
||||
;IXL = accumulator
|
||||
|
||||
|
||||
|
||||
overhead:
|
||||
ld a,e
|
||||
inc a
|
||||
and %00011111
|
||||
;ensures we stay within the 32 byte address space.
|
||||
ld e,a
|
||||
jp Computer_Zero_VM
|
||||
|
||||
|
||||
UnpackOpcode:
|
||||
push af
|
||||
and %11100000
|
||||
rlca
|
||||
rlca
|
||||
rlca
|
||||
ld b,a ;opcode in B
|
||||
pop af
|
||||
and %00011111
|
||||
ld c,a ;operand in C
|
||||
dummy:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
align 256 ;ensures the following table is page-aligned
|
||||
;this lets us index it much faster.
|
||||
Opcode_Table:
|
||||
dw vmNOP
|
||||
dw vmLDA
|
||||
dw vmSTA
|
||||
dw vmADD
|
||||
dw vmSUB
|
||||
dw vmBRZ
|
||||
dw vmJMP
|
||||
dw vmSTP
|
||||
|
||||
vmNOP:
|
||||
jp overhead ;do nothing
|
||||
vmLDA:
|
||||
push de
|
||||
ld e,c ;offset DE by the operand
|
||||
ld a,(de) ;load from that address
|
||||
ld ixl,a ;and store it in the accumulator
|
||||
pop de
|
||||
jp overhead
|
||||
vmSTA:
|
||||
push de
|
||||
ld e,c ;offset DE by the operand
|
||||
ld a,ixl ;get the accumulator
|
||||
ld (de),a ;store it into (DE)
|
||||
pop de
|
||||
jp overhead
|
||||
vmADD:
|
||||
push de
|
||||
ld e,c ;offset DE by the operand
|
||||
ld a,(de) ;load from that address
|
||||
add ixl ;and add that value to the accumulator
|
||||
ld ixl,a ;then set the new accumulator
|
||||
pop de
|
||||
jp overhead
|
||||
vmSUB:
|
||||
push de
|
||||
ld e,c ;offset DE by the operand
|
||||
ld a,(de)
|
||||
ld b,a
|
||||
ld a,ixl
|
||||
sub b
|
||||
ld ixl,a
|
||||
pop de
|
||||
noBRZ:
|
||||
jp overhead
|
||||
vmBRZ:
|
||||
ld a,ixl
|
||||
or a
|
||||
jr nz, noBRZ
|
||||
vmJMP:
|
||||
ld e,c
|
||||
jp Computer_Zero_VM
|
||||
vmSTP:
|
||||
ret ;return to main
|
||||
|
||||
align 256
|
||||
Computer_Zero_RAM_2_plus_2:
|
||||
db %00100011,%01100100
|
||||
db %11100000,%00000010
|
||||
db %00000010,%00000000
|
||||
db %00000000,%00000000
|
||||
db %00000000,%00000000
|
||||
db %00000000,%00000000
|
||||
db %00000000,%00000000
|
||||
db %00000000,%00000000
|
||||
db %00000000,%00000000
|
||||
db %00000000,%00000000
|
||||
db %00000000,%00000000
|
||||
db %00000000,%00000000
|
||||
db %00000000,%00000000
|
||||
db %00000000,%00000000
|
||||
db %00000000,%00000000
|
||||
align 256
|
||||
Computer_Zero_RAM_7x8:
|
||||
db %00101100,%01101010
|
||||
db %01001100,%00101011
|
||||
db %10001101,%01001011
|
||||
db %10101000,%11000000
|
||||
db %00101100,%11100000
|
||||
db %00001000,%00000111
|
||||
db %00000000,%00000001
|
||||
db %00000000,%00000000
|
||||
db %00000000,%00000000
|
||||
db %00000000,%00000000
|
||||
db %00000000,%00000000
|
||||
db %00000000,%00000000
|
||||
db %00000000,%00000000
|
||||
db %00000000,%00000000
|
||||
db %00000000,%00000000
|
||||
db %00000000,%00000000
|
||||
Loading…
Add table
Add a link
Reference in a new issue