|
Для uint в Keil /16 не равно >>4, используются разные команды |
|
|
|
Jan 26 2011, 12:39
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Вот листинг, в котором видно, что поделить на 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 Округление, что ли?
|
|
|
|
|
Jan 26 2011, 12:51
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(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 в конце.
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Jan 26 2011, 13:06
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(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 - без знака. Спасибо! Похоже, виновник найден.
|
|
|
|
|
Jan 26 2011, 13:45
|
Ортодокс
  
Группа: Свой
Сообщений: 219
Регистрация: 26-10-07
Из: Смела, Украина
Пользователь №: 31 775

|
Цитата(ViKo @ Jan 26 2011, 15:13)  Но, посмотрите - в последних двух случаях - достаточно добавить U только к одной константе. После этого выражение становится беззнаковым, так, что ли? Такова селяви. В соответствии со стандартом при выполнении арифм. операций в случае, когда один операнд знаковый, а другой - беззнаковый, производится приведение к беззнаковому типу.
|
|
|
|
|
Jan 27 2011, 08:23
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
И все-же, я не уверен, что этот код Код 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 лучше не игнорировать.
|
|
|
|
|
Jan 27 2011, 10:26
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(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 неверно!
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|