Voting

Category

assembly language

Bookmarking

Del.icio.us Digg Diigo DZone Earthlink Google Kick.ie
Windows Live LookLater Ma.gnolia Reddit Rojo StumbleUpon Technorati

Language Assembler (Z80)

(Sinclair/Timex variant)

Date:07/28/05
Author:Damien Guard
URL:http://www.damieng.com
Comments:7
Info:n/a
Score: (3.27 in 742 votes)
; 99 Bottles of Beer program in Zilgo Z80 assembly language.
;  Assembles for ZX Spectrum/Timex - change Spectrum: lines 
;  if porting.  Help from Marko!  Compiled and tested with SPIN 
; 
; Adapted from the Alan deLespinasse's Intel 8086 version 
; 
; Author: Damien Guard ; damien@envytech.co.uk ; www.damieng.com

 org 32768

start:
 ld      a, 2                  ; Spectrum: channel 2 = "S" for screen
 call    $1601                 ; Spectrum: Select print channel using ROM

 ld c,99                       ; Number of bottles to start with


loopstart:
 call printc                   ; Print the number of bottles
 ld hl,line1                   ; Print the rest of the first line
 call printline

 call printc                   ; Print the number of bottles
 ld hl,line2_3                 ; Print rest of the 2nd and 3rd lines
 call printline

 dec c                         ; Take one bottle away
 call printc                   ; Print the number of bottles
 ld hl,line4                   ; Print the rest of the fourth line
 call printline

 ld a,c
 cp 0                          ; Out of beer bottles?
 jp nz,loopstart               ; If not, loop round again

 ret                           ; Return to BASIC


printc:                        ; Routine to print C register as ASCII decimal
 ld a,c
 call dtoa2d                   ; Split A register into D and E

 ld a,d                        ; Print first digit in D
 cp '0'                        ; Don't bother printing leading 0
 jr z,printc2
 rst 16                        ; Spectrum: Print the character in 'A'

printc2:
 ld a,e                        ; Print second digit in E
 rst 16                        ; Spectrum: Print the character in 'A'
 ret


printline:                     ; Routine to print out a line
 ld a,(hl)                     ; Get character to print
 cp '$'                        ; See if it '$' terminator
 jp z,printend                 ; We're done if it is
 rst 16                        ; Spectrum: Print the character in 'A'
 inc hl                        ; Move onto the next character
 jp printline                  ; Loop round

printend:
 ret


dtoa2d:                        ; Decimal to ASCII (2 digits only), in: A, out: DE
 ld d,'0'                      ; Starting from ASCII '0' 
 dec d                         ; Because we are inc'ing in the loop
 ld e,10                       ; Want base 10 please
 and a                         ; Clear carry flag

dtoa2dloop:
 inc d                         ; Increase the number of tens
 sub e                         ; Take away one unit of ten from A
 jr nc,dtoa2dloop              ; If A still hasn't gone negative, do another
 add a,e                       ; Decreased it too much, put it back
 add a,'0'                     ; Convert to ASCII
 ld e,a                        ; Stick remainder in E
 ret

; Data
line1:    defb ' bottles of beer on the wall,',13,'$'
line2_3:  defb ' bottles of beer,',13,'Take one down, pass it around,',13,'$'
line4:    defb ' bottles of beer on the wall.',13,13,'$'

Download Source | Write Comment

Alternative Versions

VersionAuthorDateCommentsRate
Amstrad CPC VersionDuncan Bayne08/20/052
2004 submissionElroy Sullivan & Barry Goode08/13/090

Comments

>>  Oleg Kosenkov said on 04/23/06 05:27:56

Oleg Kosenkov Zilgo -> Zilog

>>  bau de jogos said on 11/23/06 23:46:07

bau de jogos It is very good to see the old Z80 beating many modern languages in clarity and correctness :)

>>  sergio said on 10/05/07 11:58:10

sergio Hello! You have a Very good site! I like it! I just wanted to pass on a note to let you know

>>  banana said on 05/21/08 08:07:47

banana This line could be optimized:
cp 0 ;Out of beer bottles?
Instead of comparing to zero, just do 'and a', which should update the flags and is a byte shorter.

>>  Mark G said on 04/27/09 10:43:01

Mark G Looks like 8080 code written with Zilog mnemonic surely if this was Z80 we we have used a DJNZ to control the loop

>>  Jean-Charles Meyrignac said on 05/31/09 17:53:30

Jean-Charles Meyrignac The base 10 routine is overkill !

This could be improved by using a BCD counter instead.

Start with ld c,99h

Instead of dec c use:
ld a,c
sub a,1
daa
ld c,a

Printing an hexadecimal number is done as:
ld d,a
srl a
srl a
srl a
srl a
add a,'0'
printchar
ld a,d
and a,0Fh
printchar

(sorry, my Z80 is a little bit rusty)

>>  barrym said on 08/18/10 04:22:30

barrym @bau: Clarity? Sure. Correctness? Not so much. (Duncan Baynes' version produces a
much more correct output).

Download Source | Write Comment

Add Comment

Please provide a value for the fields Name, Comment and Security Code.
This is a gravatar-friendly website.
E-mail addresses will never be shown.
Enter your e-mail address to use your gravatar.

Please don't post large portions of code here! Use the form to submit new examples or updates instead!

Name:

eMail:

URL:

Security Code:
  
Comment: