2016-04-24 8 views
0

1からnまでのすべての自然数の合計を計算するルーチンを実装したいと思います。 nはRAMに格納された変数です。結果はRAM内のバイトの2バイトのにも格納する必要があります。私はアセンブリプログラミングでは非常に新しいので、これを達成するためのアルゴリズムを見つけようとしています。これまでのところ、私はこれをやった:AVRアセンブリでの集計

.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 

私はR17R18の初期化をした私は、サブルーチンLOOPがそれn回をやっまで1により、この数字の1が増加するような何かをしなければならないと思ったので。私を最も複雑にしているのは、結果が2バイトであり、合計される各数字がちょうど1バイトで構成されているという事実です。私はこれに対処する方法を知らない。どんな助けもありがとう。

+1

あなたのコードは混乱していて、LOOPの部分が欠落しているため、コードを辿るのは難しいです。重要なアイデアは、現在の1バイトの数値をADDで結果の下位バイトに加算し、次にキャリーADCで結果の上位バイトに0を加算することです。その後、現在の1バイトを減らし、停止する必要があるかどうかを確認します。 – UncleO

+0

私はあなたの考えを得ました、それは非常に明確でした。ありがとう、 – Tendero

+1

(AVR8と仮定)最初の文には '1からnまでのすべての自然数の和を計算する 'という文が含まれています。よく知られている式があります。これが悪用されるかどうかは、MUL命令の可用性によります。 – greybeard

答えて

0
何が必要


ADDのR18で、R24 // sumL + = nLの
ADC R19、R25 // sumH + = nHの+

と2バイトの変数をキャリー最大合計はそれほど65535になります
ため 1 + 2 + 3 + ... + N = N *(N + 1)/ 2 < = 65535、次いでN < = 361 = 0x0169
1 + 2 + 3 + ... + 361 = 361 * 362/2 = 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