Execute Computer/Zero: Difference between revisions
Content added Content deleted
(implementation in Forth) |
Thundergnat (talk | contribs) m (syntax highlighting fixup automation) |
||
Line 15: | Line 15: | ||
=={{header|ALGOL 68}}== |
=={{header|ALGOL 68}}== |
||
< |
<syntaxhighlight lang="algol68">BEGIN # execute some ComputerZero programs # |
||
# instructions # |
# instructions # |
||
INT nop = 0, lda = 1, sta = 2, add = 3, sub = 4, brz = 5, jmp = 6, stp = 7; |
INT nop = 0, lda = 1, sta = 2, add = 3, sub = 4, brz = 5, jmp = 6, stp = 7; |
||
Line 96: | Line 96: | ||
execute( "1+255", ( LDA 3, ADD 4, STP 0, 1, 255 ) ) |
execute( "1+255", ( LDA 3, ADD 4, STP 0, 1, 255 ) ) |
||
END |
END |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 110: | Line 110: | ||
=={{header|Applesoft BASIC}}== |
=={{header|Applesoft BASIC}}== |
||
< |
<syntaxhighlight lang="gwbasic"> 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 |
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 |
2 LET P$ = MID$ (P$,1,MEM) + CHR$ (A) + MID$ (P$,MEM + 2,31 - MEM): PRINT MID$ ("",1 ^ FRE (0));: RETURN |
||
Line 133: | Line 133: | ||
300 DATA "FIBONACCI",46,79,109,78,47,77,48,145,171,80,192,46,224,1,1,0,8,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 |
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,</ |
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,</syntaxhighlight> |
||
=={{header|Forth}}== |
=={{header|Forth}}== |
||
{{works with|gforth|0.7.3}} |
{{works with|gforth|0.7.3}} |
||
<br> |
<br> |
||
< |
<syntaxhighlight lang="forth">#! /usr/bin/gforth |
||
\ Execute Computer/Zero |
\ Execute Computer/Zero |
||
Line 332: | Line 332: | ||
bye |
bye |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
Line 563: | Line 563: | ||
Here's one approach which might be sufficiently close to the task requirements: |
Here's one approach which might be sufficiently close to the task requirements: |
||
< |
<syntaxhighlight lang="j">OPS=: 'nop lda sta add sub brz jmp stp' |
||
assemble1=: {{ |
assemble1=: {{ |
||
Line 607: | Line 607: | ||
while. 0<:pc do. exec1'' end. |
while. 0<:pc do. exec1'' end. |
||
acc |
acc |
||
}}</ |
}}</syntaxhighlight> |
||
With this implementation, we can assemble and run representations of the five suggested programs: |
With this implementation, we can assemble and run representations of the five suggested programs: |
||
< |
<syntaxhighlight lang="j"> exec assemble 'LDA 3; ADD 4; STP; 2; 2' |
||
4 |
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' |
exec assemble 'LDA 12; ADD 10; STA 12; LDA 11; SUB 13; STA 11; BRZ 8; JMP; LDA 12; STP; 8; 7; 0; 1' |
||
Line 620: | Line 620: | ||
6 |
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' |
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</ |
0</syntaxhighlight> |
||
=== Alternate approach === |
=== Alternate approach === |
||
Line 626: | Line 626: | ||
Another approach would be to eliminate the 'assemble' command and implement the opcodes as native J commands (which build a representation of the memory space). To conform with J syntax, the right arguments of these opcodes is required (so you need a 0 even for NOP and STP). The implementation of <code>exec</code> remains much the same as before, but it's convenient to have exec save the code to memory. In other words: |
Another approach would be to eliminate the 'assemble' command and implement the opcodes as native J commands (which build a representation of the memory space). To conform with J syntax, the right arguments of these opcodes is required (so you need a 0 even for NOP and STP). The implementation of <code>exec</code> remains much the same as before, but it's convenient to have exec save the code to memory. In other words: |
||
< |
<syntaxhighlight lang="j">opcode=: {{ |
||
(m+{.y),}.y |
(m+{.y),}.y |
||
: |
: |
||
Line 654: | Line 654: | ||
while. 0<:pc do. exec1'' end. |
while. 0<:pc do. exec1'' end. |
||
acc |
acc |
||
}}</ |
}}</syntaxhighlight> |
||
and: |
and: |
||
< |
<syntaxhighlight lang="j"> exec LDA 3 ADD 4 STP 0 2 2 |
||
4 |
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 |
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 |
||
Line 667: | Line 667: | ||
6 |
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 |
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</ |
0</syntaxhighlight> |
||
=={{header|Java}}== |
=={{header|Java}}== |
||
Line 673: | Line 673: | ||
{{works with|Java|8}} |
{{works with|Java|8}} |
||
< |
<syntaxhighlight lang="python">import static java.lang.Math.floorMod; |
||
import static java.lang.Math.min; |
import static java.lang.Math.min; |
||
import static java.util.stream.Collectors.toMap; |
import static java.util.stream.Collectors.toMap; |
||
Line 978: | Line 978: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
Line 993: | Line 993: | ||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
< |
<syntaxhighlight lang="ruby">mutable struct ComputerZero |
||
ip::Int |
ip::Int |
||
ram::Vector{UInt8} |
ram::Vector{UInt8} |
||
Line 1,168: | Line 1,168: | ||
run(compile(t)) |
run(compile(t)) |
||
end |
end |
||
</ |
</syntaxhighlight>{{out}} |
||
<pre> |
<pre> |
||
Compiled 6 lines. |
Compiled 6 lines. |
||
Line 1,187: | Line 1,187: | ||
=== Interpreter version with labels === |
=== Interpreter version with labels === |
||
Uses the Python examples. |
Uses the Python examples. |
||
< |
<syntaxhighlight lang="ruby">function interpret(text::String) |
||
ip, accum, isready, ram = 0x1, 0x0, true, zeros(UInt8, 32) |
ip, accum, isready, ram = 0x1, 0x0, true, zeros(UInt8, 32) |
||
NOP() = (ip = mod1(ip + 1, 32)) |
NOP() = (ip = mod1(ip + 1, 32)) |
||
Line 1,481: | Line 1,481: | ||
interpret(t) |
interpret(t) |
||
end |
end |
||
</ |
</syntaxhighlight>{{out}} |
||
<pre> |
<pre> |
||
Program completed with accumulator value 4. |
Program completed with accumulator value 4. |
||
Line 1,513: | Line 1,513: | ||
===Execute (2+2, 7*8)=== |
===Execute (2+2, 7*8)=== |
||
Per primary task, just execute first two examples: |
Per primary task, just execute first two examples: |
||
< |
<syntaxhighlight lang="lua">vmz = { |
||
pc = 0, |
pc = 0, |
||
acc = 0, |
acc = 0, |
||
Line 1,542: | Line 1,542: | ||
-- object code derived from js sim code |
-- object code derived from js sim code |
||
print("2 + 2 = " .. vmz:boot():load({[0]=35,100,224,2,2}):exec().acc) |
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)</ |
print("7 x 8 = " .. vmz:boot():load({[0]=44,106,76,43,141,75,168,192,44,224,8,7,0,1}):exec().acc)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>2 + 2 = 4 |
<pre>2 + 2 = 4 |
||
Line 1,548: | Line 1,548: | ||
===Disassembler (7*8)=== |
===Disassembler (7*8)=== |
||
Assembly syntax doesn't seem well-specified (except as shown in descriptive text, which is presumably just pseudocode), but next step might be to add a minimal disassembler: |
Assembly syntax doesn't seem well-specified (except as shown in descriptive text, which is presumably just pseudocode), but next step might be to add a minimal disassembler: |
||
< |
<syntaxhighlight lang="lua">vmz.dism = function(self) |
||
local mnem, imax = { [0]="NOP", "LDA", "STA", "ADD", "SUB", "BRZ", "JMP", "STP" } |
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 |
for pc = 31,0,-1 do imax=pc if self.mem[pc]~=0 then break end end |
||
Line 1,562: | Line 1,562: | ||
print(vmz:dism()) |
print(vmz:dism()) |
||
print("Disassembly of 7 x 8 (POST-RUN):") |
print("Disassembly of 7 x 8 (POST-RUN):") |
||
print(vmz:exec():dism())</ |
print(vmz:exec():dism())</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>Disassembly of 7 x 8 (PRE-RUN): |
<pre>Disassembly of 7 x 8 (PRE-RUN): |
||
Line 1,597: | Line 1,597: | ||
===Assembler (fibo, list)=== |
===Assembler (fibo, list)=== |
||
Add an assembler (same minimal syntax as disassembler) for the next two examples: |
Add an assembler (same minimal syntax as disassembler) for the next two examples: |
||
< |
<syntaxhighlight lang="lua">-- <statement> ::= <opcode> <address> |
||
vmz.assm = function(self, source) |
vmz.assm = function(self, source) |
||
local function oa2b(oper, addr) return oper * 32 + addr end |
local function oa2b(oper, addr) return oper * 32 + addr end |
||
Line 1,617: | Line 1,617: | ||
NOP 5 NOP 20 NOP 3 NOP 30 NOP 1 NOP 22 NOP 4 NOP 24 |
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)</ |
print("Linked list = " .. vmz:boot():assm(srclist):exec().acc)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>Fibonacci = 55 |
<pre>Fibonacci = 55 |
||
Line 1,623: | Line 1,623: | ||
===Prisoner=== |
===Prisoner=== |
||
Some additional helper routines, then multiple rounds: |
Some additional helper routines, then multiple rounds: |
||
< |
<syntaxhighlight lang="lua">vmz.peek = function(self,addr) return self.mem[addr] end |
||
vmz.poke = function(self,addr,byte) self.mem[addr]=byte 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 |
vmz.entr = function(self,byte) self.mem[self.pc]=byte self.pc=self.pc+1 end |
||
Line 1,639: | Line 1,639: | ||
vmz:exec() |
vmz:exec() |
||
print("Round: " .. r .. " Move: " .. mvnm[move] .. " Player: " .. vmz:peek(0) .. " Computer: " .. vmz:peek(1)) |
print("Round: " .. r .. " Move: " .. mvnm[move] .. " Player: " .. vmz:peek(0) .. " Computer: " .. vmz:peek(1)) |
||
end</ |
end</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>Prisoner (priming) = 0 |
<pre>Prisoner (priming) = 0 |
||
Line 1,650: | Line 1,650: | ||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
Assumes there is no need for an "assembler", just a runtime interpreter. Output matches Algol 68. |
Assumes there is no need for an "assembler", just a runtime interpreter. Output matches Algol 68. |
||
<!--< |
<!--<syntaxhighlight lang="phix">(phixonline)--> |
||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
<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: #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> |
||
Line 1,702: | Line 1,702: | ||
<span style="color: #000080;font-style:italic;">-- overflow on addition</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> |
<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> |
||
<!--</ |
<!--</syntaxhighlight>--> |
||
You could of course define the programs using (say) 0b001_00011 instead of LDA+3. |
You could of course define the programs using (say) 0b001_00011 instead of LDA+3. |
||
{{out}} |
{{out}} |
||
Line 1,717: | Line 1,717: | ||
=={{header|Python}}== |
=={{header|Python}}== |
||
< |
<syntaxhighlight lang="python">"""Computer/zero Assembly emulator. Requires Python >= 3.7""" |
||
import re |
import re |
||
Line 1,987: | Line 1,987: | ||
if __name__ == "__main__": |
if __name__ == "__main__": |
||
main() |
main() |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
Line 2,005: | Line 2,005: | ||
Although I've entered the fifth program, it just returns 0 when reaching the STP instruction. I'm unclear how we can make it interactive without having another instruction though possibly, if STP had address bits other than 0, this could signal that user input was required. |
Although I've entered the fifth program, it just returns 0 when reaching the STP instruction. I'm unclear how we can make it interactive without having another instruction though possibly, if STP had address bits other than 0, this could signal that user input was required. |
||
< |
<syntaxhighlight lang="ecmascript">var NOP = 0 |
||
var LDA = 1 |
var LDA = 1 |
||
var STA = 2 |
var STA = 2 |
||
Line 2,181: | Line 2,181: | ||
""" |
""" |
||
] |
] |
||
for (prog in progs) interp.call(prog)</ |
for (prog in progs) interp.call(prog)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 2,194: | Line 2,194: | ||
=={{header|Z80 Assembly}}== |
=={{header|Z80 Assembly}}== |
||
Output is in hexadecimal but is otherwise correct. |
Output is in hexadecimal but is otherwise correct. |
||
< |
<syntaxhighlight lang="z80">org &1000 |
||
PrintChar equ &BB5A |
PrintChar equ &BB5A |
||
Line 2,388: | Line 2,388: | ||
db %00000000,%00000000 |
db %00000000,%00000000 |
||
db %00000000,%00000000 |
db %00000000,%00000000 |
||
db %00000000,%00000000</ |
db %00000000,%00000000</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>04 |
<pre>04 |