Jump to content

Gotchas: Difference between revisions

3,145 bytes added ,  1 year ago
m
Line 45:
SEC
SBC #4 ;eight minus four</lang>
 
===Carry===
The 6502 (and even its revisions) have ''no way to add or subtract without involving the carry flag.'' The "carry" is essentially the same as "carrying the one" that we all learned in elementary school arithmetic. <code>ADC</code> adds an extra 1 if the carry flag was set when the <code>ADC</code> was executed. <code>SBC</code> subtracts an extra 1 if the carry was ''clear'' when the <code>SBC</code> was executed (as stated before, on most other CPUs the equivalent of <code>SBC</code> behaves the opposite to the 6502).
 
Therefore, any time you want to add two numbers without involving the carry flag you have to do this:
<lang 6502asm>CLC
ADC ___ ;your operand/addressing mode of choice goes here</lang>
 
Failure to correctly use the carry flag can often result in unexpected "off-by-one" errors.
 
===Bit Rotates===
Bit rotates are always performed "through carry." This chart will illustrate the concept:
 
<pre>Before Carry Before After Carry After
%11000000 0 ROL %10000000 1
%10000000 1 ROL %00000001 1
%00000001 1 ROL %00000011 0</pre>
 
If you were expecting <code>ROL</code> to immediately transform <code>%10000000</code> into <code>%00000001</code>, there is no single 6502 instruction that can do this. However, it can be achieved using macros.
 
As the above chart implied, all bit rotates ''depend on the value of the carry before the rotate'', so make sure you take that into account.
 
===Page Boundaries===
A "page" is a 256-byte region of memory, spanning from <tt>$xx00</tt> to <tt>$xxFF</tt>. This will often be referred to as "page <tt>xx</tt>." (e.g. page 03 = the <tt>$0300</tt> to <tt>$03FF</tt> memory range.)
 
An instruction that begins on one page and ends on another is said to "cross a page boundary." This often leads to a minor performance hit, in that the instruction may take an extra clock cycle it normally wouldn't if every byte of the instruction was on the same page. Typically this only applies to the complex addressing modes that use index registers.
 
However, the 6502 has a couple bugs regarding the following addressing modes, and they are very similar in how they operate.
* When using <code>$nn,x</code> or <code>$nn,y</code>, if <code>$nn + x</code> or <code>$nn + y</code> exceeds 255, the instruction will wrap around back to $00 rather than advancing to $0100. For a more concrete example:
 
<lang 6502asm>LDX #$FF
LDA $80,X ;loads from address $007F, not $017F</lang>
 
In other words, ''an indexed zero page addressing mode cannot exit the zero page.''
 
This also happens with the indirect JMP operation, which jumps to the 16-bit address stored at the specified address.
<lang 6502asm>LDA #$20
STA $3000
LDA #$40
STA $3001
JMP ($3000) ;evaluates to JMP $4020</lang>
 
The following will '''not''' execute in the way you expect, because this instruction has a similar bug where it doesn't advance to the next page when calculating the address.
<lang 6502asm>LDA #$20
STA $30FF
LDA #$40
STA $3100
JMP ($30FF) ;rather than take the high byte from $3100, the high byte is taken from $3000 instead.</lang>
 
=={{header|68000 Assembly}}==
1,489

edits

Cookies help us deliver our services. By using our services, you agree to our use of cookies.