Assembly 如何使用1寻址模式在程序集中通过加载添加两个存储值?

Assembly 如何使用1寻址模式在程序集中通过加载添加两个存储值?,assembly,6502,Assembly,6502,我想添加存储的两个值x和y,但我只想使用1寻址模式。 以下是一个例子: 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 6502上的添加仅在蓄能器中

我想添加存储的两个值x和y,但我只想使用1寻址模式。
以下是一个例子:

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

6502上的添加仅在蓄能器中完成

  • 加载累加器中的第一个数字
  • 将第二个数字添加到累加器中
  • 将累加器存储在内存中
Z=X+Y X=X+Y X=Y+X 您的程序所做的与我的第二个代码段产生的结果相同。添加的顺序并不重要(减法不重要!)请注意,用x加载累加器而只在用y加载累加器之后直接加载累加器是没有用的

lda x   ;This is useless
lda y
add x
sta x
同样,6502指令集中没有
add
指令,也没有
sub
指令。不过,我愿意让您放心,因为定义几个宏完全可以避免每次开始新的加法或减法时都必须编写
clc
sec

使用现代FASM语法添加的示例:

macro add op
 {
  clc
  adc op
 }
使用非常旧的METACOMCO语法的
sub
示例:

sub MACRO
    sec
    sbc \1
    ENDM

如果这应该是6502代码,那么加法的操作码是
adc
,意思是“带进位的加法”。如果没有进位,则没有添加操作

lda
用一个值加载累加器,因此两个直接顺序的
lda
是完全无用的。只需使用一个
lda
,后跟一个
adc
(这将向累加器添加任何地址,并添加进位标志)

总而言之,序列看起来很简单:

lda x
adc y
sta x
例如,
x
y
可以是绝对地址

但是要注意携带标志!如果您无法了解进位状态,则需要先执行
clc
(清除进位)指令。如果您知道将设置进位,并且
y
是一个立即值,只需少加一个即可。如果你不能做到这一点,你还需要一个
clc

一般来说,总是尽量避免使用
clc
(它需要一个字节和一些周期,这在如此有限的芯片上确实很重要),但有时您会需要它


可避免
clc
(实现的一部分)的真实代码示例:

需要
clc
(实现的一部分)的真实代码示例:

下面的模式正确吗?怎么了

没有

  • 添加操作始终使用蓄能器完成
  • 没有
    ADD
    指令,只有
    ADC
    addwithcarry
  • 您需要管理进位标志
如果您有两个内存位置x和y,并且希望将结果存储在x中,则执行此操作的cannonical方法是:

; 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
您可以对y使用任何地址模式,对x使用任何地址模式,即时除外

如果x和y是16位值的地址,则16位加法如下所示:

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

这不是x86,请使用正确的体系结构标记。无论如何,
lda x
之后的
lda y
将覆盖加载的值。您只需加载
x
,然后添加
y
。容易的。也就是说,您的代码应该可以工作,但是没有必要使用lda x。y在添加之前未加载。
lda x;加y;sta结果
。或者,
lday;加x;sta结果
。请将此答案添加到回答框中,以便我可以接受。6502缺少直接添加,您需要一个
CLC+ADC
序列。然后再次给出原始代码和ISA属性,这很可能是6800代码。中没有
ADD
指令6502@JeremyP你能同意在6502号上,定义
add
sub
宏是有意义的,以避免必须编写
clc
sec
?是的,您可以创建这些宏,我看不出有任何理由不这样做,但我从未见过这样做。在进行新添加时,您无法避免使用
clc
(与多字节数的高阶字节相反),除非您已经知道进位标志的状态。@JeremyP这是我写的?您写道“一般来说,总是尽量避免
clc
”然而,事实上,它或多或少应该是自动放入的。@JeremyP您应该阅读整个答案,我首先解释了何时/如何避免它。在6502上,冗余的
clc
是不好的做法。@JeremyP这是错误的。您通常知道标志的状态。代码片段直接跳转到添加标志的位置有些东西只是你完全忘记了你的代码的标志。6502上的每个字节和每个周期都是宝贵的。
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
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)
; 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
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