Execute Computer/Zero: Difference between revisions
Content added Content deleted
(Add Java) |
(→{{header|Lua}}: added Lua solution) |
||
Line 1,061: | Line 1,061: | ||
Program completed with accumulator value 0. |
Program completed with accumulator value 0. |
||
</pre> |
</pre> |
||
=={{header|Lua}}== |
|||
===Execute (2+2, 7*8)=== |
|||
Per primary task, just execute first two examples: |
|||
<lang lua>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)</lang> |
|||
{{out}} |
|||
<pre>2 + 2 = 4 |
|||
7 x 8 = 56</pre> |
|||
===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: |
|||
<lang lua>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())</lang> |
|||
{{out}} |
|||
<pre>Disassembly of 7 x 8 (PRE-RUN): |
|||
LDA 12 |
|||
ADD 10 |
|||
STA 12 |
|||
LDA 11 |
|||
SUB 13 |
|||
STA 11 |
|||
BRZ 8 |
|||
JMP 0 |
|||
LDA 12 |
|||
STP 0 |
|||
NOP 8 |
|||
NOP 7 |
|||
NOP 0 |
|||
NOP 1 |
|||
Disassembly of 7 x 8 (POST-RUN): |
|||
LDA 12 |
|||
ADD 10 |
|||
STA 12 |
|||
LDA 11 |
|||
SUB 13 |
|||
STA 11 |
|||
BRZ 8 |
|||
JMP 0 |
|||
LDA 12 |
|||
STP 0 |
|||
NOP 8 |
|||
NOP 0 |
|||
LDA 24 |
|||
NOP 1</pre> |
|||
===Assembler (fibo, list)=== |
|||
Add an assembler (same minimal syntax as disassembler) for the next two examples: |
|||
<lang lua>-- <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)</lang> |
|||
{{out}} |
|||
<pre>Fibonacci = 55 |
|||
Linked list = 6</pre> |
|||
===Prisoner=== |
|||
Some additional helper routines, then multiple rounds: |
|||
<lang lua>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</lang> |
|||
{{out}} |
|||
<pre>Prisoner (priming) = 0 |
|||
Round: 1 Move: defe Player: 0 Computer: 3 |
|||
Round: 2 Move: coop Player: 3 Computer: 3 |
|||
Round: 3 Move: defe Player: 3 Computer: 6 |
|||
Round: 4 Move: coop Player: 6 Computer: 6 |
|||
Round: 5 Move: defe Player: 6 Computer: 9</pre> |
|||
=={{header|Phix}}== |
=={{header|Phix}}== |