Вот еще пример, как другая Ваша подпрограмма из этих-же исходников дает неверный результат http://src.caxapa.ru/329
http://caxapa.ru/135412.html
;-------------------------------------------------------------------------
; Scaling test code
;-------------------------------------------------------------------------
.include <m128def.inc>
ldi r16, high(RAMEND)
out SPH, r16
ldi r16, low(RAMEND)
out SPL, r16
scalings:
; unsigned*signed scaling test
; Проверяем правильность работы Вашей подпрограммы на таких данных
ldi r16,low(0x20C0) ; coeff = 0,255859375
ldi r17,high(0x20C0)
ldi r18,low(0x40C0) ; myint = 16576
ldi r19,high(0x40C0)
; 0,255859375*16576=4241,125=0x1091 Microsoft Калькулятор
rcall scale16ss
; r9r8 = 0x1090
; Результат неправильный!!! Разница 1,125 больше 1 двоичного разряда.
; При других данных разница может достигать почти двух.
; Это не неточность вычисления а неправильность вычисления
; изза совместного (неправильного) использования fmulх и mulх
; Проверяем правильность работы моей подпрограммы
; У меня диапазон коэффициента для этого случая тоже -1,0..1,0 в формате 1.15
ldi r20,low(0x20C0) ; coeff = 0,255859375
ldi r21,high(0x20C0)
ldi r22,low(0x40C0) ; myint = 16576
ldi r23,high(0x40C0)
rcall scale16ss_
; r19r18 = 0x1091
; Результат правильный!!!
; Вывод: Нельзя использовать MULx совместно с FMULx без учета
; сдвига результата последней командой.
rjmp scalings
;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
; Scaling routines
;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
; Scales signed int r19r18 by signed r17r16 value
; presented as signed fractional (0x8000 = -1, 0x7FFF = +0.99998)
;
; Only r16..r23 registers can be used as operands
; due to the xMULSx command limitations
;
; Result stored in r9r8
; 16 program words, 19 clocks + ret
;
; (c) 2008 leon_, MBedder
;
scale16ss:
clr r2
fmuls r17,r19
movw r8,r0
mul r18,r16
mov r7,r1
fmulsu r19,r16
sbc r9,r2
add r7,r0
adc r8,r1
adc r9,r2
fmulsu r17,r18
sbc r9,r2
add r7,r0
adc r8,r1
adc r9,r2
ret
;-------------------------------------------------------------------------
; 4. Знаковые данные, знаковый коэффициент и знаковый результат.
; данные АЦП в диапазоне 0x8000..0x7FFF | 1.15-> -1,0..1,0 | 0.16-> -0,5..0,5
; коэффициент в диапазоне 0x8000..0x7FFF | 0.16-> -0,5..0,5 | 1.15-> -1,0..1,0
; результат в диапазоне 0x8000..0x7FFF | 0.16-> -0,5..0,5 | 0.16-> -0,5..0,5
; данные АЦП в диапазоне 0x8000..0x7FFF | 1.15-> -1,0..1,0 | 0.16-> -0,5..0,5
; коэффициент в диапазоне 0x8000..0x7FFF | 16.0-> -32767..32767 | 17.0-> -65535..65535
; результат в диапазоне 0x8000..0x7FFF | 16.0-> -32767..32767 | 16.0-> -32767..32767
; Для формата 17.0 в R21:R20 записывать только 16 старших разрядов коэффициента
; r19:r18:r17:r16 = ( r23:r22 * r21:r20 ) << 1
scale16ss_:
clr r2
fmuls r23, r21
movw r18, r0
fmul r22, r20
adc r18, r2
mov r17, r0
fmulsu r23, r20
sbc r19, r2
add r17, r0
adc r18, r1
adc r19, r2
fmulsu r21, r22
sbc r19, r2
add r17, r0
adc r18, r1
adc r19, r2
ret