Execute HQ9+: Difference between revisions
Content added Content deleted
(Added Wren) |
Not a robot (talk | contribs) (Add 8080 assembly) |
||
Line 4: | Line 4: | ||
Implement a ''' [[HQ9+]] ''' interpreter or compiler. |
Implement a ''' [[HQ9+]] ''' interpreter or compiler. |
||
<br><br> |
<br><br> |
||
=={{header|8080 Assembly}}== |
|||
This program runs under CP/M. The HQ9+ source code is read from the file given |
|||
on the command line. After the program is finished, the final value of the |
|||
accumulator can be found at address <code>0252H</code>. (If you are running the |
|||
code on an emulator or on a machine that has a front panel, this is easy to do. |
|||
Alternatively, DDT can be used, though you will have to set up the FCB by hand.) |
|||
<lang 8080asm>putch: equ 2 ; Write character |
|||
puts: equ 9 ; Write string |
|||
fopen: equ 15 ; Open file |
|||
fread: equ 20 ; Read record |
|||
setdma: equ 26 ; Set DMA address |
|||
fcb: equ 5Ch ; FCB for first file on command line |
|||
org 100h |
|||
;;; Open source file given on command line |
|||
lxi d,fcb |
|||
mvi c,fopen |
|||
call 5 ; Open file |
|||
inr a ; A=FF = error |
|||
lxi d,efile |
|||
jz s_out ; If error, print error message and stop |
|||
lxi d,src ; Start reading file at src |
|||
;;; Load the entire source file into memory |
|||
block: push d ; Set DMA address to next free location |
|||
mvi c,setdma |
|||
call 5 |
|||
lxi d,fcb ; Read 128-byte record |
|||
mvi c,fread |
|||
call 5 |
|||
pop d ; Advance pointer by 128 bytes |
|||
lxi h,128 |
|||
dad d |
|||
xchg |
|||
dcr a ; A=1 = end of file |
|||
jz block ; If not EOF, read next block |
|||
xchg |
|||
mvi m,26 ; Terminate last block with EOF byte to be sure |
|||
lxi b,src ; BC = source pointer |
|||
ins: ldax b ; Get current instruction |
|||
cpi 26 ; If EOF, stop |
|||
rz |
|||
ori 32 ; Make lowercase |
|||
push b ; Keep source pointer |
|||
cpi 'h' ; H=hello |
|||
cz hello |
|||
cpi 'q' ; Q=quine |
|||
cz quine |
|||
cpi '9' ; 9=bottles |
|||
cz botls |
|||
cpi '+' ; +=increment |
|||
cz incr |
|||
pop b ; Restore source pointer |
|||
inx b ; Next instruction |
|||
jmp ins |
|||
;;; Increment accumulator |
|||
incr: lxi h,accum |
|||
inr m |
|||
ret |
|||
;;; Print "Hello, World" |
|||
hello: lxi d,histr |
|||
jmp s_out |
|||
;;; Print the source |
|||
quine: lxi h,src ; Pointer to source |
|||
qloop: mov a,m ; Load byte |
|||
cpi 26 ; Reached the end? |
|||
rz ; If so, stop |
|||
push h ; Otherwise, keep pointer |
|||
mov e,a |
|||
mvi c,putch ; Print character |
|||
call 5 |
|||
pop h ; Restore pointer |
|||
inx h ; Next byte |
|||
jmp qloop |
|||
;;; 99 bottles of beer |
|||
botls: mvi e,99 ; 99 bottles |
|||
bverse: call nbeer ; _ bottle(s) of beer |
|||
lxi h,otw ; on the wall |
|||
call bstr |
|||
call nbeer ; _ bottle(s) of beer |
|||
lxi h,nl ; \r\n |
|||
call bstr |
|||
lxi h,tod ; Take one down and pass it around |
|||
call bstr |
|||
dcr e ; Decrement counter |
|||
push psw ; Keep status |
|||
call nbeer ; _ bottle(s) of beer |
|||
lxi h,otw |
|||
call bstr ; on the wall |
|||
lxi h,nl ; \r\n |
|||
call bstr |
|||
pop psw ; restore status |
|||
jnz bverse ; If not at 0, next verse |
|||
ret |
|||
nbeer: push d ; keep counter |
|||
call btlstr ; _ bottle(s) |
|||
lxi d,ofbeer |
|||
call s_out ; of beer |
|||
pop d |
|||
ret |
|||
bstr: push d ; keep counter |
|||
xchg ; print string in HL |
|||
call s_out |
|||
pop d ; restore counter |
|||
ret |
|||
;;; Print "N bottle(s)" |
|||
btlstr: push d ; Keep counter |
|||
mov a,e ; Print number |
|||
call num |
|||
lxi d,bottle |
|||
call s_out ; Print " bottle" |
|||
pop d ; Restore counter |
|||
dcr e ; If counter is 1, |
|||
rz ; then stop, |
|||
mvi e,'s' ; otherwise, print S |
|||
mvi c,putch |
|||
jmp 5 |
|||
;;; Print number (0-99) in A |
|||
num: ana a ; If 0, print "no more" |
|||
lxi d,nomore |
|||
jz s_out |
|||
mvi b,'0'-1 ; Tens digit |
|||
nloop: inr b ; Increment tens digit |
|||
sui 10 ; Subtract 10 |
|||
jnc nloop |
|||
adi '0'+10 ; Ones digit |
|||
lxi d,snum-1 |
|||
stax d ; Store ones digit |
|||
mov a,b ; Tens digit zero? |
|||
cpi '0' |
|||
jz s_out ; If so, only print ones digit |
|||
dcx d ; Otherwise, store tens digit |
|||
stax d |
|||
s_out: mvi c,puts ; Print result |
|||
jmp 5 |
|||
efile: db 'File error.$' |
|||
histr: db 'Hello, world!',13,10,'$' |
|||
db '..' |
|||
snum: db '$' |
|||
nomore: db 'No more$' |
|||
bottle: db ' bottle$' |
|||
ofbeer: db ' of beer$' |
|||
otw: db ' on the wall',13,10,'$' |
|||
tod: db 'Take one down and pass it around' |
|||
nl: db 13,10,'$' |
|||
accum: db 0 ; Accumulator |
|||
src: equ $ ; Program source</lang> |
|||
{{out}} |
|||
This shows the code being run in SIMH and the accumulator checked afterwards. |
|||
For brevity, no <code>9</code> instruction is included in the HQ9+ source file. |
|||
<pre>A>type test.hq |
|||
HQ+hq+ |
|||
qh+QH+ |
|||
A>hq9+ test.hq |
|||
Hello, world! |
|||
HQ+hq+ |
|||
qh+QH+ |
|||
Hello, world! |
|||
HQ+hq+ |
|||
qh+QH+ |
|||
HQ+hq+ |
|||
qh+QH+ |
|||
Hello, world! |
|||
HQ+hq+ |
|||
qh+QH+ |
|||
Hello, world! |
|||
A>^E |
|||
Simulation stopped, PC: 0F402 (JMP F3F8h) |
|||
sim> ex 0252 |
|||
252: 04 |
|||
</pre> |
|||
=={{header|Ada}}== |
=={{header|Ada}}== |