Assembly for loop repeating 2 times when it's only suppose to do it once
The problem is that the register r17, which you use as a PWM timing
ramp, overflows twice every time you enter pwm_pre_loop:


when you increments it past 127, it overflows to −128
when you increment it past 255, it overflows to 0.


When using a counter the way you are using r17 here, you usually have
it overflow only once per cycle: either you consider it holds a signed
number which overflows from 127 to −128, or you consider it holds an
unsigned number which overflows from 255 to 0. I guess the latter is
more common. Your code is confused about that register's signedness:


The instruction brge (named “Branch if Greater or Equal (Signed)” in
the instruction set datasheet) tests the S (sign flag) bit of the
status register, which is useful for signed comparisons.
The instruction brlo (“Branch if Lower (Unsigned)”) tests the carry
flag, which is used for unsigned comparisons.


You should decide once on the signedness of the counter, and then use it
consistently. Since here unsigned makes more sense, you can just replace
brge by brsh (“Branch if Same or Higher (Unsigned)”).

Or better yet, remove the second test, which is redundant:

pwm_loop:
    lds r16, value
    cp r17, r16
    brsh off  ; if (r17 &gt;= r16) goto off;
    rjmp on   ; else goto on;


Note by the way that you can name your RAM variables. And you can use
some of the other available registers instead of the RAM.