我想实现一个例程来计算从1到n
的所有自然数之和。 n
是存储在RAM中的变量。结果必须存储在RAM中的双字节变量中。我在汇编编程方面非常新,所以我很难找到实现这一目标的算法。到目前为止,我已经这样做了:
.DSEG
.ORG 0x100
n: .BYTE l_n
result: .BYTE l_result
.CSEG
.ORG 0x100
SUM:
LDI XL, n ;the direction of n is stored in XL
LD R16, X ;now r16=n
LDI XL, LOW(result)
LDI XH, HIGH(result) ;X points to result
CLC ;in case C is full with trash
LDI R17, 0x0 ;R17 = 0
LDI R18, 0x1 ;R18 = 1
CALL LOOP
LDI R16,0
LDI R17,0
ADC R16, R17 ;if C is on when the loop finishes, then it has to be summed as well
ST X, R16
RET ;returns to the program that called the routine
我做了R17
和R18
的初始化,因为我认为子例程LOOP
应该做一些事情,比如逐个增加这个数字,直到n
次为止。使我最困难的事情是结果有两个字节,而每个被求和的数字只包含一个字节。我不知道如何处理这件事。任何帮助将不胜感激。
答案 0 :(得分:0)
你需要的是什么
ADD R18,R24 // sumL + = nL
ADC R19,R25 // sumH + = nH +进位
对于2字节变量,最大总和将为65535,因此对于
1 + 2 + 3 + ... + n = n *(n + 1)/ 2&lt; = 65535然后N <= 361 = 0x0169
1 + 2 + 3 + ... + 361 = 361 *2分之362= 65341
代码将如下所示:
//CPU: ATmega128A
.include "m128Adef.inc"
.DSEG
//.ORG 0x100
n: .BYTE 2 // define 2 bytes var
result: .BYTE 2 // define 2 bytes var
.CSEG
.ORG 0
RJMP boot
n0: .DW 0x0169 //init value for n=361 (max value for 2 byte result)
//in: N=R24:R25
//out: Sum=R18:R19
//calc sum 1 to n (n >=1 and n <=361)
//1+2+3+...+n=n*(n+1)/2 <= 65535 => n<=361= 0x0169
Sum1toN:
LDI R18,0x00 //sumL=0
LDI R19,0x00 //sumH=0
Lsum:
ADD R18,R24 //sumL + = nL
ADC R19,R25 //sumH += nH + C
SBIW R24,0x01 //n--
BRNE Lsum // n >0 ?
RET
boot:
CLR R1
OUT SREG,R1 //Clear all
//init stack pointer
LDI R28,LOW(RAMEND) //LDI R28,0xFF
LDI R29,HIGH(RAMEND) //LDI R28,0x10
OUT SPH,R29
OUT SPL,R28
//init
LDI ZL,LOW(n0<<1)
LDI ZH,HIGH(n0<<1)
LDI XL,LOW(n)
LDI XH,HIGH(n)
LDI R24,2
LDI R25,0
init:
LPM R0,Z+
ST X+,R0
SBIW R24,1
BRNE init
//calc:
LDS R24,n // LDS R24,0x0100
LDS R25,n+1 // LDS R25,0x0101
RCALL Sum1toN
STS result,R18
STS result+1,R19
main:
RJMP main