Jump to content
IGNORED

Clearing a Section of Memory


Recommended Posts

Ok, me again with another assembly problem to solve: clearing out a large block of RAM. 6502.org has a short little routine for clearing up to 256 bytes, but what about clearing out 8K? Let's say I want to store zeros in memory locations 32000 to 40000. The X and Y registers only hold one byte each, so I can't very well INX 8000 times. What about nested loops? I could INX up to 255, store a running total, then INY, and perform the X loop again. I can use two bytes to store the running total. Am I on the right track? I haven't been able to find a routine that does this.

Link to comment
Share on other sites

Depends what you exactly need. If clearing by pages is enough, you can use self-modifying code like this for example.

 

    lda #0
    ldx #0
    ldy #<number of pages to clear>
loop sta <address>,x
    inx
    bne loop
    inc loop+2  ; increasing HI-byte of the clearing address
    dey
    bne loop

Link to comment
Share on other sites

Very cool code MaPa. I have not used self modifying code yet.

 

Tex - please take a look at my blog post here for a nice short example that can be called from BASIC via USR call. It is relocatable, and takes 2 parameters - starting address (must be page aligned) and # of pages to clear. Blog has more details - I'll repost the code here as well.

 

;Original create date 01/06/10 - This is assembled to "MEMCLEAR.OBJ"

;This will be called from a USR function
;1st parameter is # of parms (1 byte)
;2nd parameter is STARTing page of mem to clear (2 bytes hi-lo)
;3rd parameter is # of pages to clear (2 bytes hi-lo)
;E.G. X=USR($600,2,3)
;STACK will contain
;02 - #paramaters
;02 - hi (address to clear - valid is 00 to FF)
;00 - lo (address to clear, will always want this to be 00)
;00 - hi (DISCARD)
;03 - lo (save in X as # pages to clear)

;BENCHMARK - according to a tracefile (A800Win+) clearing 3 pages of RAM
;takes 2326 instructions, 7749 cycles, .004 seconds
;Atari BASIC loop takes 4.76 seconds (acording to $13,$14)
;ASM version is 1,192 times faster!

;Equates
MEMTOCLR	equ $CE			;$CE and $CF will contain the address of RAM to clear	

	org $0600		;This code will be overwritten once used

;since calling from BASIC, clear stack and set up variables
	pla			;clear # parameters from stack
	pla
	sta MEMTOCLR+1		;hi-byte
	pla
	sta MEMTOCLR		;lo-byte
	pla			;discard since we can't clear more than $FF pages
	pla
	tax			;# of pages to clear

;stack is clean, variables set, now do the work
	lda #0			;so we can clear RAM
	;# of pages to clear has been preloaded in X
L2		ldy #0			;will be our countdown timer
L1		sta (MEMTOCLR),y	;
	dey
	bne L1
;when we fall through to here we have cleared one page
	inc	MEMTOCLR+1	;prepare to clear the next page 
	dex			;decrease page counter
	bne L2			;if not zero, jump back and clear another page

	rts			;All done - return control to BASIC	

 

Stephen

Link to comment
Share on other sites

If you were doing this in BASIC, you could assign a string to the memory location you wanted to clear, through the variable offset technique

 

This article tells you how to set up the string offset:

 

http://www.atarimagazines.com/compute/issue74/block_peek_poke.php

 

Then, any op you do on the string affects the memory location. So to blank out, say, 1K of memory, you'd do this:

 

100 S$="[heart]": S$(1024)="[heart]":S$(2)=S$

 

Simple as that. :)

Link to comment
Share on other sites

If you were doing this in BASIC, you could assign a string to the memory location you wanted to clear, through the variable offset technique

 

This article tells you how to set up the string offset:

 

http://www.atarimagazines.com/compute/issue74/block_peek_poke.php

 

Then, any op you do on the string affects the memory location. So to blank out, say, 1K of memory, you'd do this:

 

100 S$="[heart]": S$(1024)="[heart]":S$(2)=S$

 

Simple as that. :)

Yes - that is a very cool tip. The reason I had this called from BASIC is I planned on doing some stuff in 100% assembler, but still need the "crutch" of BASIC for quickly prototyping the control flow, easy I/O, etc. So I was writing everything in BASIC and then taking the slowest pieces and converting to ASM.

Link to comment
Share on other sites

I am definitely an amateur assembly language programmer, but my 2cents is that your idea of a nested loop is a fine way to do it. MaPa's code is ingenious - it actually changes the actual program on the fly. Stephen's can be called from Basic. In the end, both examples still use a nested loop, and will loop through 8000 STA instructions for your application. You can also do the following, but I don't think it is any more efficient. Rather than nesting a loop, you can do one iteration of incrementing the X register from 0 to 255 and then have this:

STA 32000,X

STA 32000+256,X

STA 32000+512,X

STA 32000+768,X

STA 32000+1024,X

Etc... Until yo do all 8K. In this example, you are writing a lot more code, and still doing 8000 STA's, so I think nesting is still the better way to go.

Link to comment
Share on other sites

My example is pretty basic piece of code IMHO, nothing extraordinary :)

 

Oh one question-- Stephen in your routine you use +1 to address the HI byte of your MEMTOCLR. MaPa's code is using +2 to INC the HI byte of the clearing address. I would have guessed "+1" for both examples, I don't think I'm following why they are different.

No, in my example +2 is right, in the other +1 is right. Because I increment memory location at label LOOP+2, there is sta <address>,x instruction which in memory looks like STA instruction code, LOW byte, HI byte. The other example is using indirect addressing and the label MEMTOCLR points to zero page location where is stored LOW byte, and +1 there is HI byte. I hope you understand.

Edited by MaPa
Link to comment
Share on other sites

In MaPa's example, it is adding 1 to the hi byte. The expression, "loop+2" calculates an address and the assembler treats it like a new label. It does not add 2 to the hi byte. It may be easier to visualize if you view a disassembly of it. You will see that loop+2 refers to the location of the hi byte of <address>. Therefore, inc loop+2 increments the value of the hi byte of <address>.

Link to comment
Share on other sites

My generic macro to set memory to a predefined value:

 

;--------------------------------------------------------------------------------
; SetMemory [address] [bytes] [value]
;--------------------------------------------------------------------------------

; warning, using some page zero memory

.macro SetMemory

setMemPtr	= 254
setMemCounter	= 252

   .if :0 <> 3
      .error "SetMemory error"

   .else
      ldy #0

      lda #<:1
      sta setMemPtr
      lda #>:1
      sta setMemPtr+1

      .if :2 < 256
         lda #:3
setMemLoop1
         sta (setMemPtr),y
         iny
         cpy #:2
         bne setMemLoop1

      .else
         lda #<:2
         sta setMemCounter
         lda #>:2
         sta setMemCounter+1

setMemLoop2
         lda #:3
         sta (setMemPtr),y
         iny
         bne setMemB1
         inc setMemPtr+1
setMemB1
         lda setMemCounter
         bne setMemB2
         dec setMemCounter+1
setMemB2
         dec setMemCounter

         lda setMemCounter
         ora setMemCounter+1
         bne setMemLoop2
      .endif
   .endif

.endm

 

This doesn't need the address aligned to a page, or the number of "bytes" to be a multiply of 256..

 

For your example: "Let's say I want to store zeros in memory locations 32000 to 40000", the usage would be:

 

SetMemory 32000, [40000-32000+1], 0

 

(yep, 8001 bytes because you specified 40000 inclusive :D)

 

This is all in MADS assembler syntax.

Link to comment
Share on other sites

I do it exactly like Mapa's example for multiple pages and also similarly too with self mod when moving pages of data.

If you only have a few of pages to wipe or locations that are not sequential, you can also just simply do ...

 

lda #0
tax
_lp	sta <address>,x
sta <address>+256,x
sta <address>+512,x
inx
bne _lp

 

EDIT.. I just noticed post #7 mentioning similar.

P.S. What's important is getting the task done efficiently and using the least resources.

Edited by Tezz
Link to comment
Share on other sites

It's worth mentioning that's it's essential to have such subroutines/procedures that can be called when required. Mapa's self modifying code for the memory wipe is a good example whereby you can set the destination address before calling the procedure:

 

    lda <newaddress
    sta loop+1
    lda >newaddress
    sta loop+2
    jsr page_clear

 

or with mads...

     mwa #$newaddress loop+1
    jsr page_clear

 

page_clear
    lda #0
    ldx #0
    ldy #<number of pages to clear>
loop sta <address>,x
    inx
    bne loop
    inc loop+2  ; increasing HI-byte of the clearing address
    dey
    bne loop
    rts

 

 

A preferable method would be to use A,X to hold the lsb/msb of the address before calling..

 

    lda <startingaddress
    ldx >startingaddress
    ldy #<number of pages to clear>
    jsr page_clear

 

page_clear
    sta loop+1
    stx loop+2
    lda #0
    tax
loop sta <address>,x
    inx
    bne loop
    inc loop+2  ; increasing HI-byte of the clearing address
    dey
    bne loop
    rts

 

This is the method I use to copy data which I will use for example when copying data to higher memory..

 

	mwa #<src_adr> src
	mwa #<dest_adr> dst

	ldy #$12		; copy 18 pages from source to destination address
	ldx #0
move		lda $ffff,x
src		equ *-2

	sta $ffff,x
dst		equ *-2

	inx
	bne move

	inc src+1
	inc dst+1

	dey
	bne move

 

... sometimes just the simple method I mentioned in post 12 which wipes 3 pages with a 19 byte proc is all you'll need, it just depends on whether or not you'll need to do something several times in your program.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...