简体   繁体   中英

How to add two stored values by load in assembly using 1 addressing mode?

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

Additions on the 6502 are done exclusively in the accumulator.

  • Load the first number in the accumulator
  • Add the second number to the accumulator
  • Store the accumulator in memory

Z=X+Y

lda x
add y
sta z  ;Leaves x and y unchanged

X=X+Y

lda x
add y
sta x

X=Y+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

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)

Is the following pattern correct? whats wrong?

No.

  • Addition is always done with the accumulator.
  • There is no ADD instruction only ADC add with carry
  • You need to manage the carry flag.

If 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM