Hi All, Sometimes you find yourself wanting to start programming with a safely "blanked" memory on the old Apple II, right? Well, here's a little routine I wrote to clear out memory safely for your programming convenience. It'll put the HEX pair 00 in all memory locations from $300-$3CF and $800-$95CF. It's located at $95D0 - $95FF - enjoy! 95D0:A9 00 A8 99 00 03 C8 C0 95D8:D0 D0 F8 A9 08 85 FB A9 95E0:00 A8 85 FA 91 FA E6 FA 95E8:A6 FA D0 F8 E6 FB A6 FB 95F0:E0 95 D0 F0 A9 00 A8 99 95F8:00 95 C8 C0 CF D0 F8 60 While the routine itself is absolutely relocateable, you might wish to leave it right where it is. It'll clobber itself if moved into any of it's destination locations. If you're crafty, you might be able to squeeze it into a DOS 3.3 file buffer area and recode it slightly to blank up to $95FF. Later, Craig And for those of you who prefer a traditional disassembly listing ... 95D0- A9 00 LDA #$00 95D2- A8 TAY 95D3- 99 00 03 STA $0300,Y 95D6- C8 INY 95D7- C0 D0 CPY #$D0 95D9- D0 F8 BNE $95D3 95DB- A9 08 LDA #$08 95DD- 85 FB STA $FB 95DF- A9 00 LDA #$00 95E1- A8 TAY 95E2- 85 FA STA $FA 95E4- 91 FA STA ($FA),Y 95E6- E6 FA INC $FA 95E8- A6 FA LDX $FA 95EA- D0 F8 BNE $95E4 95EC- E6 FB INC $FB 95EE- A6 FB LDX $FB 95F0- E0 95 CPX #$95 95F2- D0 F0 BNE $95E4 95F4- A9 00 LDA #$00 95F6- A8 TAY 95F7- 99 00 95 STA $9500,Y 95FA- C8 INY 95FB- C0 CF CPY #$CF 95FD- D0 F8 BNE $95F7 95FF- 60 RTS Now I'm sure there's some way of coding it smaller that I'm just not catching onto, but hey, it works as is and only takes up $2F bytes! :) Later, Craig Craig Bower wrote: > Now I'm sure there's some way of coding it smaller > that I'm just not catching onto, but hey, it works as > is and only takes up $2F bytes! :) > 95D0- A9 00 LDA #$00 > 95D2- A8 TAY > 95D3- 99 00 03 STA $0300,Y > 95D6- C8 INY > 95D7- C0 D0 CPY #$D0 > 95D9- D0 F8 BNE $95D3 Save 1 byte: lda #$00 ldy #$cf lp sta $02ff,y dey bne lp Your loop is also 3 cycles faster without the CPY. I don't remember if the STA across a page boundary adds a cycle though. > 95DB- A9 08 LDA #$08 > 95DD- 85 FB STA $FB > 95DF- A9 00 LDA #$00 > 95E1- A8 TAY > 95E2- 85 FA STA $FA > 95E4- 91 FA STA ($FA),Y > 95E6- E6 FA INC $FA > 95E8- A6 FA LDX $FA > 95EA- D0 F8 BNE $95E4 You should be doing INY here, not INC $FA. That'll save you ~5 cycles and 3 bytes. > 95EC- E6 FB INC $FB > 95EE- A6 FB LDX $FB > 95F0- E0 95 CPX #$95 > 95F2- D0 F0 BNE $95E4 If you just do the INY above, you can leave the contents of $FB in X the entire time, and just INX/STX/CPX, saving another 3 cycles and 2 bytes. > 95F4- A9 00 LDA #$00 > 95F6- A8 TAY > 95F7- 99 00 95 STA $9500,Y > 95FA- C8 INY > 95FB- C0 CF CPY #$CF > 95FD- D0 F8 BNE $95F7 > 95FF- 60 RTS You can merge this with the STA $0300,Y loop above, since they end at (almost) the same count. You can throw an extra "STA $03CF" in at the end to handle the differeing end conditions. If you assume 65C02/65816, you can shave a byte with STZ. -- Send mail to fadden@fadden.com (Andy McFadden) - http://www.fadden.com/ CD-Recordable FAQ - http://www.cdrfaq.org/ CiderPress Apple II archive utility for Windows - http://www.faddensoft.com/ Fight Internet Spam - http://spam.abuse.net/spam/ & http://spamcop.net/ On Tue, 01 Feb 2005 18:41:46 +0000, Craig Bower wrote: > Ok, Can it get any smaller than this? :) > > ::::: $1F Bytes long ::::: > > I decided not to cross the $2FF page boundary > So as is, it won't actually blank out one memory > location: $300 ... which I can live with. > > 0400- A9 00 LDA #$00 > 0402- A0 CF LDY #$CF > 0404- 99 00 03 STA $0300,Y > 0407- 88 DEY > 0408- D0 FA BNE $0404 > > 040A- A8 TAY You don't need the TAY. Y is already 0. > 040B- A9 08 LDA #$08 > 040D- 85 FB STA $FB Can you use X here and not trash A? (It's been a while since I programmed the 6502. :) LDX #$08 STX $FB > 040F- 98 TYA And you wouldn't need the TYA. > 0410- 85 FA STA $FA > > 0412- 91 FA STA ($FA),Y > 0414- C8 INY > 0415- D0 FB BNE $0412 > 0417- E6 FB INC $FB > 0419- A6 FB LDX $FB Then you could replace the LDX $FB with INX. They would parallel each other (X = $FB's contents). > 041B- E0 96 CPX #$96 > 041D- D0 F3 BNE $0412 > > 041F- 60 RTS > > Later, > Craig - Jay Craig Bower wrote: > I decided not to cross the $2FF page boundary > So as is, it won't actually blank out one memory > location: $300 ... which I can live with. > > 0400- A9 00 LDA #$00 > 0402- A0 CF LDY #$CF > 0404- 99 00 03 STA $0300,Y > 0407- 88 DEY > 0408- D0 FA BNE $0404 If you don't like "$2ff,y", you can instead write: lda #$00 ldy #$d0 lp dey sta $300,y bne lp It's like "--i" instead of "i--" in C. The "STA" instruction doesn't affect the Z flag. FWIW, I checked the specs, and there is no performance penalty for indexing across a page boundary (I must've been thinking of something else). > 040A- A8 TAY Not necessary -- if Y wasn't zero, "BNE" would've branched. You know that Y must be zero to reach here. > 040B- A9 08 LDA #$08 > 040D- 85 FB STA $FB > 040F- 98 TYA If you use LDX / STX, A will still be zero from before, so you can avoid the TYA. > 0410- 85 FA STA $FA > > 0412- 91 FA STA ($FA),Y > 0414- C8 INY > 0415- D0 FB BNE $0412 > 0417- E6 FB INC $FB > 0419- A6 FB LDX $FB > 041B- E0 96 CPX #$96 > 041D- D0 F3 BNE $0412 > > 041F- 60 RTS BTW, that's $20 bytes long, not $1F bytes long. If you use LDX / STX above, you dont' need to INC $FB / LDX $FB, just INX then STX $FB. How about: ORG $280 ; run this in the keyboard input buffer lda #$00 ; value to fill memory with, can be anything ldy #$d0 l1 dey sta $0300,y ; $300 - $3cf bne l1 sty $fa ; set to zero (don't use STA here!) ldx #$08 stx $fb l2 sta ($fa),y ; $800 - $95ff iny bne l2 inx stx $fb ; inx/stx/cpx beats incDP/ldx/cpx cpx #$96 ; (by 1 byte and 3 cycles) bne l2 rts I think that's 29 bytes ($1d). You can also set the first LDA to any value if you want to fill memory with something else. The cassette read/write code in the monitor ROM has places where they just skip some parts of the initialization. It doesn't matter if they write 10.6 seconds of tone or 10.4, so they save a couple of bytes by not initializing counters. Kinda gives you a new perspective on things. -- Send mail to fadden@fadden.com (Andy McFadden) - http://www.fadden.com/ CD-Recordable FAQ - http://www.cdrfaq.org/ CiderPress Apple II archive utility for Windows - http://www.faddensoft.com/ Fight Internet Spam - http://spam.abuse.net/spam/ & http://spamcop.net/ On Tue, 01 Feb 2005 20:20:11 +0000, Andy McFadden wrote: > Craig Bower wrote: > > If you use LDX / STX above, you dont' need to INC $FB / LDX $FB, just > INX then STX $FB. How about: > > ORG $280 ; run this in the keyboard input buffer > lda #$00 ; value to fill memory with, can be anything > ldy #$d0 > l1 dey > sta $0300,y ; $300 - $3cf > bne l1 > > sty $fa ; set to zero (don't use STA here!) > ldx #$08 lx stx $fb > l2 sta ($fa),y ; $800 - $95ff > iny > bne l2 > > inx ;Kill this stx $fb ; inx/stx/cpx beats incDP/ldx/cpx > cpx #$96 ; (by 1 byte and 3 cycles) bne lx > rts > :) Evolution! - Jay On Tue, 01 Feb 2005 21:01:18 +0000, Jay Nabonne wrote: > On Tue, 01 Feb 2005 20:20:11 +0000, Andy McFadden wrote: > >> Craig Bower wrote: And just to be cross that line a little (no idea if my assembler syntax is right): ORG $280 ; run this in the keyboard input buffer lda #$00 ; value to fill memory with, can be anything ldy #$d0 l1 dey sta $0300,y ; $300 - $3cf bne l1 ldx #$08 lx stx l2+2 l2 sta $0800,y ; $800 - $95ff iny bne l2 inx cpx #$96 ; (by 1 byte and 3 cycles) bne lx rts - Jay Jay Nabonne wrote: > And just to be cross that line a little (no idea if my assembler syntax is > right): [...] > > lx stx l2+2 > l2 sta $0800,y ; $800 - $95ff > iny > bne l2 > inx > cpx #$96 ; (by 1 byte and 3 cycles) > bne lx > rts Good catch on the double-STX. However, I don't think switching to self-modifying code is what we want. It saves 1 cycle per iteration, but prevents it from being freely relocated. It also makes the code longer if you want to run it more than once, because you'll have to re-initialize l2+2 to $08. -- Send mail to fadden@fadden.com (Andy McFadden) - http://www.fadden.com/ CD-Recordable FAQ - http://www.cdrfaq.org/ CiderPress Apple II archive utility for Windows - http://www.faddensoft.com/ Fight Internet Spam - http://spam.abuse.net/spam/ & http://spamcop.net/ Craig Bower wrote: > I did find myself doing it from the monitor initially, > but manually typing the commands over and over > indicated to me, time for a auto-program to do it! Did you consider an EXECutable text file? You can get DOS (3.3) to boot and load/run any file you prefer. There is information on the memory addresses necessary for such things on the Beagle Peeks and Pokes chart. (Which I don't have handy.) But you can make a bootable (Dos3.3) disk to automatically execute a text file with just the monitor commands. Or you can make a nifty utility disk to do things for you. Filename this one ClearMEM.txt REM Clear Memory Call -151 300:00 301<300.3CEM 800:00 801<800.95FEM 3d0g Filename this one MergeBIN.txt REM LOAD BASIC File PRINT LOAD FILENAME PRINT REM L1 is end address of BASIC File L1= PEEK (xx)* 256 + PEEK(yy):Rem Length of Program Rem load binary after Basic File PRINT PRINT CHR$(4);"BLOAD Binary Relocatable File, A"; L1 +1 PRINT REM L2 is length of Binary File L2 = PEEK (vv) * 256 + PEEK (ww)+1 REM Move BASIC EOF marker, Calculate new length (add a couple bytes) REM L3 = new length L3 = L1 + L2 + fudge POKE xx,INT(L3/256): Poke yy, L3- INT(L3/256) REM Save new longer with binary ending BASIC File SAVE FILENAME And of course you can utilize Strings for filenames before you execute the executables, like File1$ = "Bisicfailename", File2$ = "BinaryFileName" and replace with appropriate references. Just a thought or two. Thankx, Ed