# of bytes to move minus 1?

Building your first 6502-based project? We'll help you get started here.
Post Reply
jeffythedragonslayer
Posts: 114
Joined: 03 Oct 2021

# of bytes to move minus 1?

Post by jeffythedragonslayer »

Hi, I am curious why the MVN instruction decrements C until it rolls under to $FFFF instead of stopping at zero. I know many programming languages increment loop counters until they are one past the last valid value in a for loop, so maybe it's something like that.

Is there a hardware reason for this? The way it works, according to Eyes & Lichty, seems to be that you need to put the # of bytes to move minus 1 into C, not simply the # of bytes.
User avatar
drogon
Posts: 1671
Joined: 14 Feb 2018
Location: Scotland
Contact:

Re: # of bytes to move minus 1?

Post by drogon »

jeffythedragonslayer wrote:
Hi, I am curious why the MVN instruction decrements C until it rolls under to $FFFF instead of stopping at zero. I know many programming languages increment loop counters until they are one past the last valid value in a for loop, so maybe it's something like that.

Is there a hardware reason for this? The way it works, according to Eyes & Lichty, seems to be that you need to put the # of bytes to move minus 1 into C, not simply the # of bytes.
I don't know exactly, but I suspect 2 reasons - one is that it might take less logic to detect bit 15 of the counter going from 0 to 1 than to test for bits 0:15 = 0, also if it were the exact number of bytes then you would not be able to move 65536 bytes without needing a 17-bit register.

-Gordon
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/
User avatar
BigDumbDinosaur
Posts: 9425
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: # of bytes to move minus 1?

Post by BigDumbDinosaur »

jeffythedragonslayer wrote:
Hi, I am curious why the MVN instruction decrements C until it rolls under to $FFFF instead of stopping at zero. I know many programming languages increment loop counters until they are one past the last valid value in a for loop, so maybe it's something like that.

Is there a hardware reason for this? The way it works, according to Eyes & Lichty, seems to be that you need to put the # of bytes to move minus 1 into C, not simply the # of bytes.

I see Gordon replied and echoed my thoughts. It's likely the internal logic needed to determine when terminal count has been reached was simpler by having all bits in .C flipped to 1 at the end. So, yes, .C has to be loaded with the COUNT - 1, which means COUNT = 0 will copy one byte.

Note that MVN and MVP, unlike all other instructions, can be interrupted. That being the case, it is essential that your interrupt service routine (ISR) exactly preserve the microprocessor's state and exactly restore it when interrupt servicing has completed. Otherwise the copy operation will likely go off the rails when the ISR returns control to the foreground.

The front end I use in my ISR is:

Code: Select all

         rep #%00110000        ;16-bit everything
         phy                   ;preserve MPU state
         phx
         pha
         phb
         phd
         ...program continues...

The return is:

Code: Select all

         rep #%00110000        ;16-bit everything
         pld                   ;restore MPU state
         plb
         pla
         plx
         ply
         rti

The above methods work because when RTI is executed the status register (SR) will be pulled, putting all the flags back the way they were when the interrupt was serviced. Since the m and x flags in SR determine register sizes, the pulling of SR when RTI is executed will automatically set the registers to whatever size they were before the interrupt.

Another "quirk" of MVN and MVP is they tinker with DB, setting it to the destination data bank. Therefore is wise to push DB before the copy and then pull it afterwards to put things back in order:

Code: Select all

         rep #%00110000        ;16-bit everything
         lda #count-1          ;bytes to copy -1
         ldx #source & $FFFF   ;source address LSW
         ldy #dest & $FFFF     ;destination address LSW
         phb                   ;protect current data bank
         mvn #source,dest      ;execute copy
         plb                   ;back to current data bank
         ...program continues...

The official WDC assembly language syntax for MVN and MVP has the full 24-bit source and destination addresses as the operands. The WDC assembler performs <address> >> 16 to extract the banks. In the Kowalski assembler, only the banks are used as the operands. The WDC syntax is more logical in terms of how the programmer would think about the source and destination, but the Kowalski syntax is easier for the assembler to parse. In a 65C816 machine language monitor, only the banks would be assembled with the instruction.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
BigDumbDinosaur
Posts: 9425
Joined: 28 May 2009
Location: Midwestern USA (JB Pritzker’s dystopia)
Contact:

Re: # of bytes to move minus 1?

Post by BigDumbDinosaur »

drogon wrote:
...one is that it might take less logic to detect bit 15 of the counter going from 0 to 1 than to test for bits 0:15 = 0...

That seems likely.

Quote:
...also if it were the exact number of bytes then you would not be able to move 65536 bytes without needing a 17-bit register.

If MVN/MVP had been designed to use the exact count I supposed setting the initial count to $0000 would give you the full 64 KB copy when .C returned to $0000. However, bit 15 flipping from 0 to 1 is an easy test.
x86?  We ain't got no x86.  We don't NEED no stinking x86!
User avatar
Dr Jefyll
Posts: 3525
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: # of bytes to move minus 1?

Post by Dr Jefyll »

Welcome, jeffythedragonslayer!

As for your question, I think WDC simply provided what the programmer would want. As Gordon noted, C is a register with only 16 bits, and that means a choice had to be made. So, just ask yourself which seems more useful. Would you rather have...
  • a minimum move of 0 bytes and a maximum move of $FFFF bytes, or
    a minimum move of 1 bytes and a maximum move of $10000 bytes ?

As for the screen name you've chosen for yourself, jeffythedragonslayer seems intended to resonate with Buffy the Vampire Slayer -- is that right?

For me, that's somewhat interesting and amusing, given that my own handle -- a nickname I acquired as a teenager -- is intended to resonate with Dr Jekyll from Robert Louis Stevenson's Strange Case of Dr Jekyll and Mr Hyde. :P

-- Jeff
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
jeffythedragonslayer
Posts: 114
Joined: 03 Oct 2021

Re: # of bytes to move minus 1?

Post by jeffythedragonslayer »

Thank you for your enlightening replies. It's a nickname a friend game me in high school - I've never asked him if it had anything to do with Buffy.
Post Reply