Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Для uint в Keil /16 не равно >>4
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > Keil
ViKo
Вот листинг, в котором видно, что поделить на 16 требует больше команд, чем сдвинуть на 4 разряда. Для чего это, числа ведь беззнаковые?
Код
;;;222      uint8_t s0, s1, s2, s3;
;;;223      uint8_t m1 = ((s1 + s2) * 9 - s0 - s3) / 16;
000106  eb0c0006          ADD      r0,r12,r6
00010a  eb0000c0          ADD      r0,r0,r0,LSL #3
00010e  eba00007          SUB      r0,r0,r7
000112  eba00006          SUB      r0,r0,r6
000116  ea4f71e0          ASR      r1,r0,#31
00011a  eb007111          ADD      r1,r0,r1,LSR #28
00011e  f3c11107          UBFX     r1,r1,#4,#8
;;;224      uint8_t m2 = ((s1 + s2) * 9 - s0 - s3) >> 4;
000122  f3c01007          UBFX     r0,r0,#4,#8

Округление, что ли?
HARMHARM
Добавьте везде volatile, и не будет никакой разницы. Деление и сдвиг производятся с помощью одной и той же команды:
UBFX r0,r0,#4,#8
Результат остальных действий сохраняется в регистрах, и используется в обоих случаях - оптимизация.
GetSmart
Цитата(HARMHARM @ Jan 26 2011, 17:43) *
Деление и сдвиг производятся с помощью одной и той же команды:
UBFX r0,r0,#4,#8

Судя по листингу - нет.
Всё-таки деление (в первом случае) почему-то знаковое.
Код
000116  ea4f71e0          ASR      r1,r0,#31
00011a  eb007111          ADD      r1,r0,r1,LSR #28
00011e  f3c11107          UBFX     r1,r1,#4,#8


А вот для проверки почему, надо бы ко всем константам приписать U в конце.
ViKo
Цитата(HARMHARM @ Jan 26 2011, 14:43) *
Добавьте везде volatile, и не будет никакой разницы

Код
;;;222      volatile uint8_t s0, s1, s2, s3;
;;;223      volatile uint8_t m1 = ((s1 + s2) * 9 - s0 - s3) / 16;
000106  eb0c0006          ADD      r0,r12,r6
00010a  eb0000c0          ADD      r0,r0,r0,LSL #3
00010e  eba00007          SUB      r0,r0,r7
000112  eba00006          SUB      r0,r0,r6
000116  ea4f71e0          ASR      r1,r0,#31
00011a  eb007111          ADD      r1,r0,r1,LSR #28
00011e  f3c11107          UBFX     r1,r1,#4,#8
;;;224      volatile uint8_t m2 = ((s1 + s2) * 9 - s0 - s3) >> 4;
000122  f3c01007          UBFX     r0,r0,#4,#8


Цитата(GetSmart @ Jan 26 2011, 14:51) *
А вот для проверки почему, надо бы ко всем константам приписать U в конце.

Код
;;;222      volatile uint8_t s0, s1, s2, s3;
;;;223      volatile uint8_t m1 = ((s1 + s2) * 9U - s0 - s3) / 16U;
000106  eb0c0006          ADD      r0,r12,r6
00010a  eb0000c0          ADD      r0,r0,r0,LSL #3
00010e  eba00007          SUB      r0,r0,r7
000112  eba00006          SUB      r0,r0,r6
000116  ea4f1010          LSR      r0,r0,#4
00011a  b2c1              UXTB     r1,r0
;;;224      volatile uint8_t m2 = ((s1 + s2) * 9U - s0 - s3) >> 4U;
00011c  b2c0              UXTB     r0,r0

Вы правы...

На эти U L я обычно "ложил с прибором". Да, видно, зря. Не пойму, 16 - оно ж и в Африке 16. Или нет?

Еще варианты
Код
;;;222      volatile uint8_t s0, s1, s2, s3;
;;;223      volatile uint8_t m1 = ((s1 + s2) * 9U - s0 - s3) / 16;
000106  eb0c0006          ADD      r0,r12,r6
00010a  eb0000c0          ADD      r0,r0,r0,LSL #3
00010e  eba00007          SUB      r0,r0,r7
000112  eba00006          SUB      r0,r0,r6
000116  ea4f1010          LSR      r0,r0,#4
00011a  b2c1              UXTB     r1,r0
;;;224      volatile uint8_t m2 = ((s1 + s2) * 9U - s0 - s3) >> 4;
00011c  b2c0              UXTB     r0,r0

Код
;;;222      volatile uint8_t s0, s1, s2, s3;
;;;223      volatile uint8_t m1 = ((s1 + s2) * 9 - s0 - s3) / 16U;
000106  eb0c0006          ADD      r0,r12,r6
00010a  eb0000c0          ADD      r0,r0,r0,LSL #3
00010e  eba00007          SUB      r0,r0,r7
000112  eba00006          SUB      r0,r0,r6
000116  f3c01107          UBFX     r1,r0,#4,#8
;;;224      volatile uint8_t m2 = ((s1 + s2) * 9 - s0 - s3) >> 4U;
00011a  f3c01007          UBFX     r0,r0,#4,#8

Да, приходит понимание, что 16 - это число со знаком, а 16U - без знака.
Спасибо! Похоже, виновник найден.
rezident
Цитата(ViKo @ Jan 26 2011, 18:06) *
На эти U L я обычно "ложил с прибором". Да, видно, зря. Не пойму, 16 - оно ж и в Африке 16. Или нет?
Или нет. Без явного указания типа (по умолчанию) все константы имеют знаковый тип signed int.
HARMHARM
Ага, понял чего не понял sm.gif
ViKo
Цитата(rezident @ Jan 26 2011, 15:10) *
Или нет. Без явного указания типа (по умолчанию) все константы имеют знаковый тип signed int.

Понял. Осознал. Искуплю. sm.gif
Но, посмотрите - в последних двух случаях - достаточно добавить U только к одной константе. После этого выражение становится беззнаковым, так, что ли?
Aurochs
Цитата(ViKo @ Jan 26 2011, 15:13) *
Но, посмотрите - в последних двух случаях - достаточно добавить U только к одной константе. После этого выражение становится беззнаковым, так, что ли?

Такова селяви. В соответствии со стандартом при выполнении арифм. операций в случае, когда один операнд знаковый, а другой - беззнаковый, производится приведение к беззнаковому типу.
ViKo
И все-же, я не уверен, что этот код
Код
000116  ea4f71e0          ASR      r1,r0,#31
00011a  eb007111          ADD      r1,r0,r1,LSR #28
00011e  f3c11107          UBFX     r1,r1,#4,#8

есть расширение знака при делении на 16.
Может, все-таки, округление?
upd. Всё, нашел! В книге "ARM System Developer’s Guide" имеется точный ответ.

If your code uses addition, subtraction, and multiplication, then there is no performance
difference between signed and unsigned operations. However, there is a difference when it
comes to division. Consider the following short example that averages two integers:
int average_v1(int a, int B )
{
return (a+B )/2;
}
This compiles to
average_v1
ADD r0,r0,r1 ; r0 = a + b
ADD r0,r0,r0,LSR #31 ; if (r0<0) r0++
MOV r0,r0,ASR #1 ; r0 = r0>>1
MOV pc,r14 ; return r0
Notice that the compiler adds one to the sum before shifting by right if the sum is
negative. In other words it replaces x/2 by the statement:
(x<0) ? ((x+1)>>1): (x>>1)

В-общем, при делении на положительную константу U лучше не игнорировать.
_Pasha
Цитата(ViKo @ Jan 27 2011, 11:23) *
(x<0) ? ((x+1)>>1): (x>>1)

Спасибо! Сами не ведая, помогли мне багу найти. sm.gif
ViKo
Цитата(_Pasha @ Jan 27 2011, 10:34) *
Спасибо! Сами не ведая, помогли мне багу найти. sm.gif

Может быть, и не только вам sm.gif Себе, так уж точно.
Книжка эта есть "в закромах". Просто бомба, а не книжка. (неуместное сравнение, извиняюсь!) Настоящая Библия! Жаль, что не про Cortex.
demiurg_spb
Цитата(ViKo @ Jan 27 2011, 11:23) *
В-общем, при делении на положительную константу U лучше не игнорировать.

Никогда об этом не задумывался. Спасибо!
Код
-3 / 2 = -1

-3 = 0b11111101

(0b11111101 + 1)/2 = 0b11111110/2 = 0b11111111 = -1 верно!

(0b11111101 + 0)/2 = 0b11111101/2 = 0b11111110 = -2  неверно!
rezident
Цитата(demiurg_spb @ Jan 27 2011, 15:26) *
Никогда об этом не задумывался.
Вообще говоря методов округления существует больше, чем один.
_Pasha
Цитата(rezident @ Jan 27 2011, 15:13) *
Вообще говоря методов округления существует больше, чем один.

дело в де-факто стандарте, а не в методах, а если его не придерживаться там, где это надо - это бага, имхо, вылезет она сразу или существенно позже..
GetSmart
Цитата(_Pasha @ Jan 27 2011, 23:37) *
... а если его не придерживаться там, где это надо - это бага

Что за бага? И кто багописатель?
У ViKo никаких багов не было.
_Pasha
Цитата(GetSmart @ Jan 27 2011, 22:50) *
Что за бага? И кто багописатель?
У ViKo никаких багов не было.

Епт, я - и бага и багописец.
GetSmart
А можно поподробней о баге... Интригующе как...
AHTOXA
Цитата(_Pasha @ Jan 27 2011, 23:55) *
Епт, я - и бага и багописец.

И багоп́исец и багопис́ец? :-)
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.