Execute Computer/Zero is an implementation of Computer/zero Assembly.
Other implementations of Computer/zero Assembly.
Task

Create a Computer/zero Assembly emulator. You may consider 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 STP 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.


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