Jump to content



0

It doesn't use one's complement, does it?


5 replies to this topic

#1 Abscissa OFFLINE  

Abscissa

    Combat Commando

  • 5 posts
  • Location:Cleveland, OH, US

Posted Sat Aug 27, 2005 2:25 PM

Pardon if this is a stupid question...

I've come across a strange thing (I'm using the Z26 emulator, if it makes any difference). At first, I had my VBlank loop look like this:
           ldx #37
VBlankLoop
           sta WSYNC
           dex
           bne VBlankLoop
(It's a slighly modified form of what was in one of Andrew Davie's tutorials.) I was using the X register, and needed X to be 0 later on anyway, so I just looped by decrementing from 37 to 0.

But then, I wanted to switch it to use A. So I changed it to this, but this now makes the screen go blank:
           lda #37
VBlankLoop
           sta WSYNC
           adc #$FF; Decrement, by adding the two's complement of 1
           bne VBlankLoop
(This was before I remembered there was a subtract instruction ;) )

But then it worked again when I changed it to this:
           lda #37
VBlankLoop
           sta WSYNC
           adc #$FE; Decrement, by adding the one's complement of 1 (aka the two's complement of 2)
           bne VBlankLoop
Which seems to tell me one of three things:
1. I've run into a strange bug in either Z26 or the 6502/6507 (doubtful)
2. The 6502 (or at least the 6507 variant) uses one's compliment arithmetic instead of two's complement (which I would find very surprising, since I didn't think one's complement was ever used in something this common)
3. I screwed up something somewhere else (entirely plausable ;) )

But this other variant I made seems to make #1 or #2 more likely than #3:
           lda #37
VBlankLoop
           sta WSYNC
           sbc #1; Decrement, by subtracting 1
           bne VBlankLoop
That code does work, unlike adding $FF.

So what do the experts think? Am I nuts for not realizing that the Atari 2600 is a one's complement machine, or have I probably just screwed up something else? (Or is there some other thing going on?)

EDIT: I guess this board doesn't like bold within a code block.

Edited by Abscissa, Sat Aug 27, 2005 2:30 PM.


#2 CPUWIZ OFFLINE  

CPUWIZ

    Rarity 11

  • 26,327 posts
  • Cartridge Recycler
  • Location:SoCal

Posted Sat Aug 27, 2005 2:29 PM

Just took a quick glance and I don't see you setting or clearing the carry flag anywhere, which leads me to believe that when this code is run, the carry flag could be random. :ponder:

#3 Abscissa OFFLINE  

Abscissa

    Combat Commando

  • 5 posts
  • Location:Cleveland, OH, US

Posted Sat Aug 27, 2005 2:34 PM

CPUWIZ, on Sat Aug 27, 2005 3:29 PM, said:

Just took a quick glance and I don't see you setting or clearing the carry flag anywhere, which leads me to believe that when this code is run, the carry flag could be random.  :ponder:

View Post

Took me a minute to realize why you said the carry flag instead of the zero flag ;). But, that's a good call, I'll try that.

EDIT: Aha! That's it! I tried clearing the carry flag before each "adc #$FF", and it worked:
           lda #37
VBlankLoop
           sta WSYNC
           clc
           adc #$FF; Add two's complement of 1
           bne VBlankLoop
Obviously, I'll still use the subtract instruction instead. But thanks, thought I was going nuts for a minute :)

Edited by Abscissa, Sat Aug 27, 2005 2:41 PM.


#4 CPUWIZ OFFLINE  

CPUWIZ

    Rarity 11

  • 26,327 posts
  • Cartridge Recycler
  • Location:SoCal

Posted Sat Aug 27, 2005 2:39 PM

The reason why I said that, is the fact that adc and sbc add/subtract the immediate value and the carry from the accumulator.

E.G.

A = A + (immediate + carry)

or

A = A - (immediate + carry)

#5 Abscissa OFFLINE  

Abscissa

    Combat Commando

  • 5 posts
  • Location:Cleveland, OH, US

Posted Sat Aug 27, 2005 2:46 PM

CPUWIZ, on Sat Aug 27, 2005 3:39 PM, said:

The reason why I said that, is the fact that adc and sbc add/subtract the immediate value and the carry from the accumulator.

E.G.

A = A + (immediate + carry)

or

A = A - (immediate + carry)

View Post

Right, yea. Although I guess that means that even though I'm going to use the SBC instead of ADC, I should still clear the flag before starting the loop, right? (I realize I won't need it in the loop, since the loop itself won't be causing a carry.)

#6 CPUWIZ OFFLINE  

CPUWIZ

    Rarity 11

  • 26,327 posts
  • Cartridge Recycler
  • Location:SoCal

Posted Sat Aug 27, 2005 2:54 PM

Take a look at this...

   Arithmetic Instructions
   =======================
   
   ADC  - ADd to accumulator with Carry
   SBC  - SuBtract from accumulator with Carry
   
   The 6502 has two arithmetic modes, binary and decimal.  Both addition 
   and subtraction implement the carry flag to track carries and borrows 
   thereby making multibyte arithmetic simple.  Note that in the case of 
   subtraction it is necessary to SET the carry flag as it is the opposite 
   of the carry that is subtracted.
   
   Addition should follow this form:
   
   CLC
   ADC ...    
   .
   .
   ADC ...
   .
   .
   .
   
   Clear the carry flag, and perform all the additions.  The carry 
   between additions will be handled in the carry flag.  Add from low 
   byte to high byte.  Symbolically, the net effect of an ADC instruction is:
   
   A + M + C  -->  A
   
   
   Subtraction follows the same format:
   
   SEC
   SBC ...
   .
   .
   SBC ...
   .
   .
   .
   
   In this case set the carry flag first and then do the subtractions.  
   Symbolically,
   
   A - M - ~C  -->  A  ,  where ~C is the opposite of C
   
   
   Ex.1
   ----
        A 16-bit addition routine.  $20,$21 + $22,$23 = $24,$25
        
           CLC         clear the carry
           LDA $20     get the low byte of the first number
           ADC $22     add to it the low byte of the second
           STA $24     store in the low byte of the result
           LDA $21     get the high byte of the first number
           ADC $23     add to it the high byte of the second, plus carry
           STA $25     store in high byte of the result
           
           ... on exit the carry will be set if the result could not be
               contained in 16-bit number.
               
   Ex.2
   ----
        A 16-bit subtraction routine.  $20,$21 - $22,$23 = $24,$25
        
           SEC         clear the carry
           LDA $20     get the low byte of the first number
           SBC $22     add to it the low byte of the second
           STA $24     store in the low byte of the result
           LDA $21     get the high byte of the first number
           SBC $23     add to it the high byte of the second, plus carry
           STA $25     store in high byte of the result
           
           ... on exit the carry will be set if the result produced a 
               borrow
               
   Aside from the carry flag, arithmetic instructions also affect the N, 
   Z, and V flags as follows:
   
      Z = 1  if result was zero, 0 otherwise
      N = 1  if bit 7 of the result is 1, 0 otherwise
      V = 1  if bit 7 of the accumulator was changed, a sign change
      





0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users