Execute Computer/Zero: Difference between revisions

Added FreeBASIC
No edit summary
(Added FreeBASIC)
 
(5 intermediate revisions by 3 users not shown)
Line 135:
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,</syntaxhighlight>
 
==={{header|FreeBASIC}}===
{{trans|ALGOL 68}}
<syntaxhighlight lang="vbnet">' Define the opcodes
Enum
NOP = 0
LDA
STA
ADD
SUV
BRZ
JMP
STP
End Enum
 
Function instr_(op As Ubyte, v As Ubyte) As Ubyte
Return (32 * op) + v
End Function
 
Function NOP_(v As Ubyte) As Ubyte
Return instr_(NOP, v)
End Function
 
Function LDA_(v As Ubyte) As Ubyte
Return instr_(LDA, v)
End Function
 
Function STA_(v As Ubyte) As Ubyte
Return instr_(STA, v)
End Function
 
Function ADD_(v As Ubyte) As Ubyte
Return instr_(ADD, v)
End Function
 
Function SUB_(v As Ubyte) As Ubyte
Return instr_(SUV, v)
End Function
 
Function BRZ_(v As Ubyte) As Ubyte
Return instr_(BRZ, v)
End Function
 
Function JMP_(v As Ubyte) As Ubyte
Return instr_(JMP, v)
End Function
 
Function STP_(v As Ubyte) As Ubyte
Return instr_(STP, v)
End Function
 
Sub execute(nombre As String, program() As Ubyte)
' Initialize memory and program counter
Dim As Ubyte m(Ubound(program))
Dim As Short m_pos = -1
For i As Ubyte = Lbound(program) To Ubound(program)
m(m_pos + 1) = program(i)
m_pos += 1
Next
Dim As Boolean running = True
Dim As Ubyte pc = 0
Dim As Ubyte a = 0
Dim As Ubyte op
Dim As Ubyte operand
While running
op = m(pc) \ 32
operand = m(pc) Mod 32
pc = (pc + 1) Mod 32
Select Case op
Case NOP
' No operation
Case LDA
a = m(operand)
Case STA
m(operand) = a
Case ADD
a = (a + m(operand)) Mod 256
If a > 255 Then a = 0
Case SUV
a = (a - m(operand)) Mod 256
If a < 0 Then a = 255
Case BRZ
If a = 0 Then pc = operand
Case JMP
pc = operand
Case Else
' Stop
running = False
Print Space(12 - Len(nombre)) & nombre & ": " & a
End Select
Wend
End Sub
 
' Test programs
Dim poly1(4) As Ubyte = {LDA_(3), ADD_(4), STP_(0), 2, 2}
execute("2+2", poly1())
 
Dim poly2(13) As Ubyte = {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("7*8", poly2())
 
Dim poly3(0 To ...) As Ubyte = {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("fibonacci", poly3())
 
Dim poly4(0 To ...) As Ubyte = {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("linkedList", poly4())
 
Dim poly5(0 To ...) As Ubyte = {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}
execute("prisoner", poly5())
 
Dim poly6(0 To ...) As Ubyte = {LDA_(3), SUB_(4), STP_(0), 0, 255}
execute("0-255", poly6())
 
Dim poly7(0 To ...) As Ubyte = {LDA_(3), SUB_(4), STP_(0), 0, 1}
execute("0-1", poly7())
 
Dim poly8(0 To ...) As Ubyte = {LDA_(3), ADD_(4), STP_(0), 1, 255}
execute("1+255", poly8())
 
Sleep</syntaxhighlight>
{{out}}
<pre> 2+2: 4
7*8: 56
fibonacci: 55
linkedList: 6
prisoner: 0
0-255: 1
0-1: 255
1+255: 0</pre>
 
=={{header|Delphi}}==
Line 648 ⟶ 780:
</pre>
 
 
=={{header|EasyLang}}==
<syntaxhighlight>
proc run name$ mem[] . .
write name$ & ": "
pc = 1
len mem[] 32
repeat
ppc = mem[pc]
op = ppc div 32
addr = ppc mod 32 + 1
pc += 1
if op = 1
acc = mem[addr]
elif op = 2
mem[addr] = acc
elif op = 3
acc = (acc + mem[addr]) mod 255
elif op = 4
acc = (acc - mem[addr]) mod 255
elif op = 5
if acc = 0
pc = addr
.
elif op = 6
pc = addr
.
until op = 7 or pc > 32
.
print acc
.
run "2+2" [ 35 100 224 2 2 ]
run "7*8" [ 44 106 76 43 141 75 168 192 44 224 8 7 0 1 ]
run "Fibonacci" [ 46 79 109 78 47 77 48 145 171 80 192 46 224 1 1 0 8 1 ]
run "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 ]
run "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>
 
{{out}}
<pre>
2+2: 4
7*8: 56
Fibonacci: 55
List: 6
Prisoner: 0
</pre>
 
=={{header|Forth}}==
Line 1,785 ⟶ 1,963:
1
255
0
</pre>
 
=={{header|jq}}==
'''Adapted from [[#Wren|Wren]]'''
{{works with|jq}}
'''Also works with gojq, the Go implementation of jq'''
 
This entry assumes all the programs have been placed in a text file
in which each program takes the form of a header followed
by the instructions, one per line, followed by at least one blank line.
 
The header is assumed to have the form:
<pre>
; title
</pre>
<syntaxhighlight lang="jq">
### Utility
def trim: sub("^ +";"") | sub(" +$";"");
 
### Computer/Zero
def NOP: 0;
def LDA: 1;
def STA: 2;
def ADD: 3;
def SUB: 4;
def BRZ: 5;
def JMP: 6;
def STP: 7;
 
def ops: {"NOP": NOP, "LDA": LDA, "STA": STA, "ADD": ADD,
"SUB": SUB, "BRZ": BRZ, "JMP": JMP, "STP": STP};
 
# Input: the program in the form of an array of strings,
# each string corresponding to an input line of the form
# "INSTR N" or "N"
# Output: an array of integers
def load:
map([splits(" *")] as $split
| $split[0] as $instr
| (if ($split|length == 2) then $split[1]|tonumber
else 0
end) as $addr
| if ops[$instr]
then ops[$instr] * 32 + $addr
else try ($instr|tonumber) catch 0
end );
 
# input: an array as produced by `load`
def interp:
{ acc: 0, pc: 0, mem: .}
| until(.break;
(.mem[.pc] % 32) as $addr
| ((.mem[.pc] - $addr) / 32) as $instr
| .pc += 1
| if $instr == LDA then .acc = .mem[$addr]
elif $instr == STA then .mem[$addr] = .acc
elif $instr == ADD then .acc += .mem[$addr]
| if .acc > 255 then .acc += -256 else . end
elif $instr == SUB then .acc += (- .mem[$addr])
| if .acc < 0 then .acc += 256 else . end
elif $instr == BRZ
then if .acc == 0 then .pc = $addr else . end
elif $instr == JMP then .pc = $addr
else .
end
| .break = $instr == STP or .pc > 31 )
| .acc;
 
# Assume the input file consists of several programs, each structured as:
# ; program name
# one instruction per line
#
def task:
def init: map_values(null);
foreach (inputs, null) as $line ({};
if $line == null then .program = .buffer
elif $line[0:1] == ";" then init | .title = $line
else ($line|trim) as $line
| if $line == "" then .program = .buffer | .buffer = []
else .buffer += [$line]
end
end)
| .title as $title
| .program
| if length == 0 then empty
else
$title, (load|interp)
end ;
 
task
</syntaxhighlight>
'''Program file - scrollable window''' (programs.txt)
<div style="overflow:scroll; height:400px;">
<pre>
; 2+2
LDA 3
ADD 4
STP
2
2
 
; 7 * 8
LDA 12
ADD 10
STA 12
LDA 11
SUB 13
STA 11
BRZ 8
JMP 0
LDA 12
STP
8
7
0
1
 
; 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
1
1
0
8
1
 
; linkedList
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
 
; prisoner
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
</pre>
</div>
 
{{output}}
'''Invocation:''' jq -nR -f execute-computer-zero.jq programs.txt
<pre>
"; 2+2"
4
"; 7 * 8"
56
"; fibonacci"
55
"; linkedList"
6
"; prisoner"
0
</pre>
Line 3,195 ⟶ 3,594:
 
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="ecmascriptwren">var NOP = 0
var LDA = 1
var STA = 2
2,169

edits