Прошу помощи по ассемблеру.
Не могу найти ошибку!!!
Имеется код на асме, который в CodeVision отлично работает.
Код: Выделить всё
#include <avr/io.h>
// Умножение (возведение в квадрат) 2-х 16-ти битных чисел (погрешность - 2 младших байта)
unsigned int mul16x16_square(unsigned int a, unsigned int b)
{
unsigned int result;
unsigned char tmp = 0;
asm volatile(
"clr %[TMP]" "\n\t"
"mul %B[A], %B[B]" ";Ah * Bh \n\t"
"movw %C[RES], r0" "\n\t"
"mul %A[A], %A[B]" ";Al * Bl \n\t"
"movw %A[RES], r0" "\n\t"
"fmul %B[A], %A[B]" ";Ah * Bl \n\t"
"adc %D[RES], %[TMP]" "\n\t"
"add %B[RES], r0" "\n\t"
"adc %C[RES], r1" "\n\t"
"adc %D[RES], %[TMP]" "\n\t"
: [RES]"=&r" (result), [TMP]"=&r" (tmp)
: [A]"a" (a), [B]"a" (b)
);
return result;
}
int main(void)
{
uint16_t qqq= 0x1234;
while(1)
{
mul16x16_square(qqq, qqq);
asm("nop"::);
}
}
Это часть дизассемблера, которая интересует (без оптимизации):
Код: Выделить всё
+0000002E: 818C LDD R24,Y+4 Load indirect with displacement
+0000002F: 819D LDD R25,Y+5 Load indirect with displacement
+00000030: 812E LDD R18,Y+6 Load indirect with displacement
+00000031: 813F LDD R19,Y+7 Load indirect with displacement
+00000032: 01AC MOVW R20,R24 Copy register pair
+00000033: 24FF CLR R15 Clear Register
+00000034: 9F53 MUL R21,R19 Multiply unsigned
[b]+00000035: 0190 MOVW R18,R0 Copy register pair
+00000036: 9F42 MUL R20,R18 Multiply unsigned[/b]
+00000037: 0180 MOVW R16,R0 Copy register pair
+00000038: 035A FMUL R21,R18 Fractional multiply unsigned
+00000039: 1D3F ADC R19,R15 Add with carry
+0000003A: 0D10 ADD R17,R0 Add without carry
+0000003B: 1D21 ADC R18,R1 Add with carry
+0000003C: 1D3F ADC R19,R15 Add with carry
+0000003D: 831B STD Y+3,R17 Store indirect with displacement
+0000003E: 830A STD Y+2,R16 Store indirect with displacement
+0000003F: 82F9 STD Y+1,R15 Store indirect with displacement
А это - та же интересующая часть, только с полной оптимизацией:
Код: Выделить всё
+0000001C: 01AC MOVW R20,R24 Copy register pair
+0000001D: 2788 CLR R24 Clear Register
+0000001E: 9F57 MUL R21,R23 Multiply unsigned
[b]+0000001F: 01A0 MOVW R20,R0 Copy register pair
+00000020: 9F46 MUL R20,R22 Multiply unsigned[/b]
+00000021: 0190 MOVW R18,R0 Copy register pair
+00000022: 035E FMUL R21,R22 Fractional multiply unsigned
+00000023: 1F58 ADC R21,R24 Add with carry
+00000024: 0D30 ADD R19,R0 Add without carry
+00000025: 1D41 ADC R20,R1 Add with carry
+00000026: 1F58 ADC R21,R24 Add with carry
Соответствующий выделенным в тексте строкам код:
Не обращая особо ваше внимание на алгоритм, у меня такой вопрос.
Почему в строках (в дизасме они выделены жирным) задействованы одинаковые регистры. Ведь в коде, вроде бы, все правильно стоит (имеется в виду вывод в новый регистр -
модификатор '&' в строке вывода -
: [RES]"=&r" (result), [TMP]"=&r" (tmp)), а используется один и тот же регистр. В данных случаях - это
R18 и
R20.
Соответственно результат, который должен быть равен: 1234h * 1234h =
14B 5A90h не получается правильным.
В моих случаях (и в одном и в другом мне интересны только старшие байты) такие результаты:
1(оптимизация откл.) -
1 4Dh
2(оптимизация вкл.) -
1 44h
Ассемблерный код рабочий (проверен в CV).
Где я ошибаюсь?