使用Atmel Studio实现1-100求和至r16:r17的技术求助
Fixing Your AVR Assembly Code for 1-100 Sum Calculation
Hey there! Let's break down why your current code isn't hitting the expected result, then fix it up step by step.
What's Wrong With Your Current Code?
Your loop logic (counting down from 100 and adding each value) makes sense on paper, but two critical issues are throwing off your result:
- Unaccounted Carry Over: The
add xl, r18instruction only works on the 8-bitxlregister. Once your sum exceeds 255 (which happens almost immediately when adding 100+99+...), the overflow gets stored in the Carry flag (C) of the Status Register (SREG) — but you never add this carry to the high byte (xh). This means your 16-bit sum inxh:xlis missing all those overflow bits, leading to a wrong total. - Incorrect Initialization: You set
xhto0x01at the start, but your starting sum should be 0. This adds an extra 256 to your final result right out the gate.
Corrected Assembly Code
Here's the fixed version that properly handles carry and initializes the sum correctly:
; Initialize 16-bit sum register X (xh:xl) to 0 ldi xl, 0x00 ; Low byte of sum starts at 0 ldi xh, 0x00 ; High byte of sum starts at 0 ldi r18, 100 ; Loop counter starting at 100 ldi r19, 0x00 ; Dummy register with 0 value for carry handling loop1: add xl, r18 ; Add current counter value to sum's low byte adc xh, r19 ; Add carry flag to sum's high byte (r19=0, so only carry is added) dec r18 ; Decrement counter by 1 brne loop1 ; Repeat until counter reaches 0 ; Move final sum to r16:r17 as required mov r16, xl ; Low byte of sum → r16 (will be 0xba) mov r17, xh ; High byte of sum → r17 (will be 0x13)
How This Works
- Carry Handling: The
adc(Add with Carry) instruction grabs the overflow flag from the previousaddand adds it toxh. Sincer19is 0, this effectively just appends any overflow fromxlto the high byte of your sum. - Proper Initialization: Starting with
xh:xl = 0x0000ensures we're accumulating from a clean slate, no extra values skewing the total.
Bonus: A More Efficient Approach (Using Math Formula)
Since the sum of 1 to n is n(n+1)/2, you can calculate this directly with multiplication instead of looping — which is way faster for larger numbers:
ldi r18, 100 ; n = 100 ldi r19, 101 ; n+1 = 101 mul r18, r19 ; Multiply 100*101, result stored in r1:r0 (0x2774 = 10100) lsr r1 ; Right shift high byte to divide by 2 ror r0 ; Rotate low byte right (carries over bit from r1's shift) mov r16, r0 ; Low byte of final sum → r16 (0xba) mov r17, r1 ; High byte of final sum → r17 (0x13)
This skips the loop entirely and leverages AVR's hardware multiplier for speed — great to know as you dive deeper into assembly!
内容的提问来源于stack exchange,提问作者Supreme Super
相关产品推荐
相关产品推荐

