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 (6510)

Date:04/20/05
Author:Johannes Tevessen
URL:n/a
Comments:12
Info:n/a
Score: (3.31 in 49 votes)
; 
99 bottles of beer - C64 6510 assembler version
; 
written 2001 by Johannes Tevessen <j.tevessen@gmx.net>
;
; 
Self-modifying code.
; 
Compiled size: 192 byte plus 2 byte loading offset.
; 
If you can make a shorter version doing the same,
; 
please contact me.
;
; 
Compile, for example, to $C000 and start
; 
using:
; 
	LOAD "64BEER",8,1
; 
	NEW
; 
	SYS 49152
;
; 
for example: as64 -sC000 64beer.S -o 64beer
;
; 
This code is downloadable:
;
; 
Source: 
	http://www.dummy.de/c64/64beer.S
; 
Compiled: 
	http://www.dummy.de/c64/64beer.bin
;
; 
The code looks like this:
;
; $ ./thex <64beer
; 000000:  00C0A263 2054C0A9 5EA01C20 44C0A9BC    ...c T..^.. D...
; 000010:  A0022044 C02054C0 A95EA010 2044C0A9    .. D. T..^.. D..
; 000020:  7AA02120 44C0CA20 54C0A95E A01C2044    z.! D.. T..^.. D
; 000030:  C0A97AA0 022044C0 8AD0C9A9 9BA02520    ..z.. D.......%
; 000040:  44C0A95E A01E8D48 C0AD00C0 20D2FFEE    D..^...H.... ...
; 000050:  48C088D0 F4608A48 A90020CD BD68AA60    H.....H.. ..h...
; 000060:  20424F54 544C4553 204F4620 42454552     BOTTLES OF BEER
; 000070:  204F4E20 54484520 57414C4C 2E0D5441     ON THE WALL..TA
; 000080:  4B45204F 4E452044 4F574E2C 20504153    KE ONE DOWN, PAS
; 000090:  53204954 2041524F 554E442C 0D474F20    S IT AROUND,.GO
; 0000A0:  544F2054 48452053 544F5245 20414E44    TO THE STORE AND
; 0000B0:  20425559 20534F4D 45204D4F 52452C0D     BUY SOME MORE,.
; 0000C0:  3939                                   99

; 
.org 
$C000

org: 
ldx 
#99
bloop: 
jsr 
xout
	lda	#<bobot
	ldy	#28
	jsr	strout
	lda	#<comcr
	ldy	#2
	jsr	strout
	jsr	xout
	lda	#<bobot
	ldy	#16
	jsr	strout
	lda	#<bobpa
	ldy	#33
	jsr	strout
	dex
	jsr	xout
	lda	#<bobot
	ldy	#28
	jsr	strout
	lda	#<bobpa
	ldy	#2
	jsr	strout
	txa
	bne	bloop
	lda	#<endtx
	ldy	#37
	jsr	strout
	lda	#<bobot
	ldy	#30
strout: 
sta 
ldins+1
ldins: 
lda 
org
	jsr	$ffd2
	inc	ldins+1
	dey
	bne	ldins
outdon: 
rts

xout: 
txa
	pha
	lda	#0
	jsr	$bdcd
	pla
	tax
	rts

bobot: 
.text 
" BOTTLES OF BEER ON THE WALL"
bobpa: 
.text 
"."
	.byte	13
	.text	"TAKE ONE DOWN, PASS IT AROUND,"
	.byte	13
endtx: 
.text 
"GO TO THE STORE AND BUY SOME MORE"
comcr: 
.text 
","
	.byte	13
	.text	"99"

Download Source | Write Comment

Alternative Versions

Comments

>>  xtr said on 08/23/05 10:54:22

xtr Yeah! - just tried it out - it runs ;-)
From the rules to be known.. :
"Real programmers write self-modifying code, espacially if it can safe 20 nanoseconds in the middle of a tight loop"

xtr

>>  dr beep said on 11/30/05 07:55:22

dr beep When you place the endtext in front of BOBOT you can put the last two print commands together and you won't be needing the last JSR to the BOBOT-text.

Shortens the code like this

LDA #<ENDTX
LDY #37
JSR STROUT
LDA #<BOBOT
LDY #30

becomes
LDA #<ENDTX
LDY #67

>>  Jean-Charles Meyrignac said on 05/31/09 17:43:23

Jean-Charles Meyrignac Using self-modifying code in this case is terrible, both in terms of speed and in term of space.

First, instead of storing strings, and displaying Y bytes, the best is
to use zero-ended strings.

bobot:
.text " BOTTLES OF BEER ON THE WALL"
.byte 0
bobpa:
.text "."
.byte 13
.text "TAKE ONE DOWN, PASS IT AROUND,"
.byte 13
.byte 0
endtx:
.text "GO TO THE STORE AND BUY SOME MORE"
.byte 0
comcr:
.text ","
.byte 13
.text "99"
.byte 0

We lost 5 bytes.
Now, let's change strout:
strout:
lda org,y
beq outdon
jsr $ffd2
iny
bne strout
outdon:
rts
So, from the original 16 bytes, we have now 12 bytes, but the parameter is not A
anymore, but Y.
And here is the best:
lda #<bobot
ldy #28
jsr strout

is replaced by:
ldy #<bobot
jsr strout

Saving 2 bytes for each call (and a lot more cycles, since INC xxxx is very slow !), so a total of 16 bytes are saved !
Thus we saved 16+4-5 = 15 bytes !

>>  rayman said on 12/14/09 20:44:08

rayman LOL

>>  barrym said on 03/28/10 06:43:11

barrym $1000: a9 63 85 fe a9 1c 20 2b 10 a2 23 a0 02 20 37 10
$1010: a9 10 20 2b 10 a2 00 a0 45 c6 fe 30 1a a2 43 a0
$1020: 21 20 37 10 a9 1e 20 2b 10 f0 d9 48 a6 fe a9 00
$1030: 20 cd bd a2 27 68 a8 bd 42 10 20 d2 ff e8 88 d0
$1040: f6 60 2e 0d 47 4f 20 54 4f 20 54 48 45 20 53 54 .mGO TO THE ST
$1050: 4f 52 45 20 41 4e 44 20 42 55 59 20 53 4f 4d 45 ORE AND BUY SOME
$1060: 20 4d 4f 52 45 2c 0d 39 39 20 42 4f 54 54 4c 45 MORE,m99 BOTTLE
$1070: 53 20 4f 46 20 42 45 45 52 20 4f 4e 20 54 48 45 S OF BEER ON THE
$1080: 20 57 41 4c 4c 2e 0d 54 41 4b 45 20 4f 4e 45 20 WALL.mTAKE ONE
$1090: 44 4f 57 4e 2c 20 50 41 53 53 20 49 54 20 41 52 DOWN, PASS IT AR
$10a0: 4f 55 4e 44 2c 0d OUND,m

66 bytes of instructions, 100 bytes of text, 1 byte of zero page.
No need to self-modify because the designers of the 6502 thoughtfully
provided several INDEXED ADDRESSING MODES that are much smaller and
faster than the equivalent self-modifying code! You should try them
some time, they're quite useful.

>>  barrym said on 03/28/10 10:42:38

barrym Hey, I re-read my previous comment and realized that I came across a little bit
more smug than I intended. Anyone who can make a 65xx do something is okay in
my book! Keep the dream alive. 65XX FOREVER!!

>>  barrym said on 03/29/10 05:32:16

barrym By the way, I offered the 166 byte version here because it's output is
similar to yours (mine does a little better near the end). A 203 byte
version that correctly adds a blank line between verses, removes the 'S'
from '1 BOTTLES' and substitutes 'NO MORE' for '0' has been submitted
under new language 'APPLE ][+ MACHINE LANGUAGE', but my understanding is
that the webmaster is very busy, and I don't expect it to appear very soon.
>>>>>>>>>>>>>>>>>>>>>> 65XX FOREVER!!!!!!!!!!!!!!! <<<<<<<<<<<<<<<<<<<<<<

>>  barrym said on 06/19/10 09:11:16

barrym I did it! After considerable effort (and several puzzled glances from my family)
I managed to jam a complete program that prints an upper-case 40-column version of
the official lyrics into 191 bytes (85 of instructions, 106 of text, no zero page):

> 0c00 a2 63 d0 05 a0 00 20 18 0c a0 21 20 18 0c a0 20 .c.... ...! ...
> 0c10 20 18 0c ca 10 ee a2 63 98 48 20 47 0c 8a f0 0a ......c.H G....
> 0c20 48 a9 00 20 cd bd 68 aa a0 29 20 47 0c e0 01 d0 H.. ..h..) G....
> 0c30 01 c8 20 47 0c 68 c9 20 d0 04 a0 45 10 09 48 20 .. G.h. ...E..H
> 0c40 47 0c 68 c9 21 f0 0d b9 55 0c c8 48 29 7f 20 d2 G.h.!...U..H). .
> 0c50 ff 68 10 f3 60 54 41 4b 45 20 4f 4e 45 20 44 4f .h..`TAKE ONE DO
> 0c60 57 4e 20 41 4e 44 20 50 41 53 53 20 49 54 20 41 WN AND PASS IT A
> 0c70 52 4f 55 4e 44 2c 8d 4e 4f 20 4d 4f 52 45 20 42 ROUND,.NO MORE B
> 0c80 4f 54 54 4c c5 53 20 4f 46 20 42 45 45 d2 20 4f OTTL.S OF BEE. O
> 0c90 4e 20 54 48 45 20 57 41 4c cc 2e 8d 47 4f 20 54 N THE WAL...GO T
> 0ca0 4f 20 54 48 45 20 53 54 4f 52 45 20 41 4e 44 20 O THE STORE AND
> 0cb0 42 55 59 20 53 4f 4d 45 20 4d 4f 52 45 2c 8d BUY SOME MORE,.

This one knows how to do '1 BOTTLE' and 'NO MORE BOTTLES', add a blank line
between verses and print a proper ending. I don't think I can compact it any
further without frying a circuit in my brain ... oh, wait, too late ...

>>  barrym said on 06/29/10 09:16:08

barrym I guess I wasn't quite done, because I found a subtle rearrangement that saved
two more bytes of instructions, so I'm at 189 bytes!

>>  barrym said on 08/27/10 07:34:29

barrym

;23456789012345678901234567890123456789012345678901234;
; BEER SONG IN 6510 ASSEMBLER BY BARRYM 2010-06-30    ;
; THANKS TO SBPROJECTS.COM FOR LOTS OF VALUABLE INFO  ;
; AND A NICE ASSEMBLER!  THIS SOURCE TARGETS A C-64,  ;
; BUT CAN BE EASILY ADJUSTED FOR OTHER 65XX DEVICES   ;
; BY CHANGING THE ROM EQUATES FOR ECHO AND ITOA.      ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        .CR 6502
        .TF C64BEER.O,BIN
        .OR $0C00
;
ECHO    .EQ $FFD2         ; ROM : EMIT AN ASCII CHAR
ITOA	.EQ $BDCD         ; ROM : EMIT A 16-BIT INT
STBEER  .EQ 99            ; STARTING BEER COUNT
;
; X REG. IS THE BOTTLE COUNTER.
; Y REG. IS THE STRING INDEX POINTER.
; A REG. TAKES CARE OF EVERYTHING ELSE (WITH A LITTLE
;    HELP FROM THE STACK).
; ZERO PAGE ISN'T USED EXCEPT BY THE ROM ROUTINES.
; THE OBJECT CODE OCCUPIES A TOTAL OF 189 BYTES!
;
; PRINT THE COMPLETE, CORRECT SONG (ADJUSTED FOR UPPER-
;    CASE, 40-COLUMN DISPLAY). '1 BOTTLE' AND 'NO MORE
;    BOTTLES' ARE PRINTED TO SPEC.
;
MAIN    LDX #STBEER       ; X=STBEER
        BNE PRSONG        ; (SING THE SONG AND EXIT)
;
; PRINT THE WHOLE SONG EXCEPT FOR THE LAST SENTENCE.
;
BEERME  LDY #TAKE-STR     ; ? "TAKE ONE ... AROUND,"
        JSR PRBOB         ; ? X;" BOTTL ... WALL."
PRSONG  LDY #CR-STR       ; ?
        JSR PRBOB         ; ? X;" BOTTL ... WALL";
        LDY #COMCR-STR    ; ? ","
        JSR PRBOB         ; ? X;" BOTTL ... BEER."
        DEX               ; X=X-1
        BPL BEERME        ; IF X>-1 THEN BEERME
;
; SET UP THE LAST SENTENCE AND FALL THROUGH TO PRBOB
;    (Y REG IS ALREADY SET TO "GO ...").
;
        LDX #STBEER       ; X=STBEER: ? "GO ... MORE,"
;
; PRINT A PROPERLY PUNCTUATED "BOTTLE OF BEER" SUB-
;    PHRASE.
;
PRBOB   TYA               ; (SAVE PRE-STRING POINTER
        PHA               ;    FOR LATER USE)
        JSR PUTS          ; (PRINT THE PRE-STRING)
        TXA               ; IF X=0 THEN ? "NO MORE";
        BEQ PRBOTT        ;    (Y IS ALREADY SET TO GO)
        PHA
        LDA #0
        JSR ITOA          ; IF X<>0 THEN ? X;
        PLA
        TAX
        LDY #BOTTL-STR
PRBOTT  JSR PUTS          ; ? " BOTTLE";
        CPX #1
        BNE PLURAL        ; IF X<>1 THEN ? "S";
        INY
PLURAL  JSR PUTS          ; ? " OF BEER";
        PLA               ; (RETRIEVE PRE-STRING PTR)
        CMP #COMCR-STR
        BEQ NOWALL
        PHA               ; IF (APPROPRIATE) THEN
        JSR PUTS          ;    ? " ON THE WALL";
        PLA
        CMP #CR-STR       ; IF (APPROPRIATE) THEN
        BEQ KPUT          ;    ? "."
NOWALL  LDY #DOTCR-STR
;
; PRINT A HI-BIT-SET TERMINATED STRING @ Y, LEAVING Y @
;    START OF NEXT STRING.
;
PUTS    LDA STR,Y         ; GRAB A STRING CHAR
        INY               ; ADVANCE POINTER
        PHA
        AND #$7F          ; (USE ORA #$80 HERE IF ECHO
        JSR ECHO          ;    EXPECTS NEGATIVE ASCII)
        PLA
        BPL PUTS
KPUT    RTS               ; THE ONLY ONE IN MY PROGRAM!
;
; THIS LYRIC STRING IS OPTIMIZED FOR AN UPPER-CASE 40-
;    COLUMN DISPLAY.  LAYING IT OUT IN THIS PARTICULAR
;    WAY ALLOWED THE ELIMINATION OF SEVERAL 'LDY #'
;    INSTRUCTIONS, MAKING THE PROGRAM LOGIC SHORTER,
;    BUT SLIGHTLY OPAQUE.
;
STR:
TAKE    .AS "TAKE ONE DOWN AND PASS IT AROUND"
COMCR   .AS ","
CR      .AT #13
        .AS "NO MORE"
BOTTL   .AT " BOTTLE"
        .AT "S OF BEER"
        .AT " ON THE WALL"
DOTCR   .AT ".",#13
        .AT "GO TO THE STORE AND BUY SOME MORE,",#13
        .EN


>>  barrym said on 09/21/10 06:29:11

barrym Another re-arrangement and now I'm at 186 bytes!

... same beginning as previous sample ...
;
MAIN    LDY #CR-STR       ; ?
STOCK   LDX #STBEER       ; X=STBEER
        BNE PRBOB         ; ? X;" BOTTL ... WALL";
PUTCOM  LDY #COMCR-STR    ; ? ","
        JSR PRBOB         ; ? X;" BOTTL ... BEER."
        DEX               ; X=X-1
        BMI STOCK         ; IF X<0 THEN FINISH THE SONG
;                           WITH A FANCY HACKER TRICK!
        LDY #TAKE-STR     ; ? "TAKE ONE ... AROUND,"
        JSR PRBOB         ; ? X;" BOTTL ... WALL.";
        LDY #CR-STR       ; ?
PRBOB   TYA               ; (SAVE PRE-STRING POINTER
        PHA               ;    FOR LATER USE)
        JSR PUTS          ; (PRINT THE PRE-STRING)
        TXA               ; IF X=0 THEN ? "NO MORE";
        BEQ PRBOTT        ;    (Y IS ALREADY SET TO GO)
        PHA
        LDA #0
        JSR ITOA          ; IF X<>0 THEN ? X;
        PLA
        TAX
        LDY #BOTTL-STR
PRBOTT  JSR PUTS          ; ? " BOTTLE";
        CPX #1
        BNE PLURAL        ; IF X<>1 THEN ? "S";
        INY
PLURAL  JSR PUTS          ; ? " OF BEER";
        PLA               ; (RETRIEVE PRE-STRING PTR)
        CMP #COMCR-STR
        BEQ PUTDOT
        PHA               ; IF (APPROPRIATE) THEN
        JSR PUTS          ;    ? " ON THE WALL";
        PLA
        CMP #CR-STR       ; IF (APPROPRIATE) GOTO
        BEQ PUTCOM        ;    PUTCOM
PUTDOT  LDY #DOTCR-STR    ; ? "."
PUTS    LDA STR,Y         ; GRAB A STRING CHAR
        INY               ; ADVANCE POINTER
        PHA               ; SAVE RAW CHAR
        AND #$7F          ; (USE ORA #$80 HERE IF ECHO
        JSR ECHO          ;    EXPECTS NEGATIVE ASCII)
        PLA               ; RESTORE RAW CHAR
        BPL PUTS          ; LOOP IF HIGH BIT IS CLEAR
        RTS               ; RTS FOR PUTS, PRBOB & MAIN
;
... same ending as previous sample ...

>>  new mbt said on 09/21/10 08:30:14

new mbt mbt shoes
mbt sneakers
mbts
new mbts
mbts sell

mbt 2010
mbt trainers
mbt sneakers store
mbt UK
mbt US
Cheap MBTs
MBT Shoes Discount
MBT Shoes On Sale
MBT Trainers Webstie
new mbt shoes
buy mbt
mbt
authentic mbt
mbts discount
buy mbt shoes
cheap mbt shoes
mbt sneakers store

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: