Reputation: 21
I want to add two values x and y which are stored but I only want to use 1 addressing mode.
Following is the example:
lda x
sta x
// store the final result in x
lda y
sta y
// store the final result in y
//now I want to add x and y like x+y. Is the following pattern correct? whats wrong?
lda x
lda y
add x
sta x
Upvotes: 2
Views: 7263
Reputation: 9899
Additions on the 6502 are done exclusively in the accumulator.
lda x
add y
sta z ;Leaves x and y unchanged
lda x
add y
sta x
What your program did produces the same result as my second snippet. The order in which you add is not important (not so for the subtraction!) Do notice that it is useless to load the accumulator with x only to reload it directly after with y!
lda x ;This is useless
lda y
add x
sta x
As others have commented, there's no add
instruction in the 6502 instruction set, nor is there a sub
instruction. However I am willing to give you the benefit of the doubt since it's perfectly OK to have a few macros defined in order to avoid having to write clc
and sec
every time you start a fresh addition or subtraction.
Example of add
using modern day FASM syntax:
macro add op
{
clc
adc op
}
Example of sub
using very old METACOMCO syntax:
sub MACRO
sec
sbc \1
ENDM
Upvotes: 5
Reputation:
If this should really be 6502 code, the opcode for addition is adc
which means "add with carry". There's no addition operation without carry available.
lda
loads the accumulator with a value, so two lda
in direct sequence are utterly useless. Just use one lda
followed by an adc
(which will add whatever you address to the accumulator and add the carry flag).
All in all, the sequence looks simply like:
lda x
adc y
sta x
where x
and y
could for example be absolute addresses.
But be aware of the carry flag! If you have no way to know the status of carry, you need a clc
(clear carry) instruction first. If you know that carry will be set, and y
is an immediate value, just add one less. If you can't do that, you need a clc
as well.
In general, always try to avoid the clc
(it takes a byte and some cycles, which indeed matters on such a limited chip), but sometimes you will need it.
Real-world example of code that can avoid the clc
(part of a double dabble implementation):
nts_addloop: lda nc_string,x
cmp #$5 ; value >= 5 ?
bcc nts_noadd ; after not branching here, we know C=1
adc #$2 ; then add 3 (2 + carry)
sta nc_string,x
nts_noadd: dex
Real-world example of code that needs clc
(part of a long multiplication implementation):
mul_rorloop: ror mpm_arg1,x
dex
bpl mul_rorloop
bcc mul_noadd ; we know carry is set when not branching
ldx #($80-NUMSIZE)
clc ; clear it because we have to add a variable value
mul_addloop: lda mpm_arg2+NUMSIZE-$80,x
adc mpm_res+NUMSIZE-$80,x
sta mpm_res+NUMSIZE-$80,x
inx
bpl mul_addloop
mul_noadd: ldx #($81-NUMSIZE)
Upvotes: 4
Reputation: 86651
Is the following pattern correct? whats wrong?
No.
ADD
instruction only ADC
add with carryIf you have two memory locations x and y and you want to store the result in x, the cannonical way to do this is:
; x = x + y
LDA x ; Load one operand into the accumulator.
CLC ; Clear the carry flag so it does not get added into the result
ADC y ; Add the other operand
STA x ; Store the operand back to x
You can use any address mode for y and any address mode for x except immediate.
If x and y are the addresses of 16 bit values, the 16 bit addition will look like this:
LDA x ; Load one operand into the accumulator.
CLC ; Clear the carry flag so it does not get added into the result
ADC y ; Add the other operand
STA x ; Store the operand back to x
LDA x+1 ; Now do the high byte
ADC y+1 ; Note we do not clear the carry this time.
STA x+1
Upvotes: 7