ViKo 1 26 января, 2011 Опубликовано 26 января, 2011 · Жалоба Вот листинг, в котором видно, что поделить на 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 0 26 января, 2011 Опубликовано 26 января, 2011 · Жалоба Добавьте везде volatile, и не будет никакой разницы. Деление и сдвиг производятся с помощью одной и той же команды: UBFX r0,r0,#4,#8 Результат остальных действий сохраняется в регистрах, и используется в обоих случаях - оптимизация. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 26 января, 2011 Опубликовано 26 января, 2011 · Жалоба Деление и сдвиг производятся с помощью одной и той же команды: 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 1 26 января, 2011 Опубликовано 26 января, 2011 · Жалоба Добавьте везде 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 А вот для проверки почему, надо бы ко всем константам приписать 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 0 26 января, 2011 Опубликовано 26 января, 2011 · Жалоба На эти U L я обычно "ложил с прибором". Да, видно, зря. Не пойму, 16 - оно ж и в Африке 16. Или нет?Или нет. Без явного указания типа (по умолчанию) все константы имеют знаковый тип signed int. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HARMHARM 0 26 января, 2011 Опубликовано 26 января, 2011 · Жалоба Ага, понял чего не понял :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 26 января, 2011 Опубликовано 26 января, 2011 · Жалоба Или нет. Без явного указания типа (по умолчанию) все константы имеют знаковый тип signed int. Понял. Осознал. Искуплю. :) Но, посмотрите - в последних двух случаях - достаточно добавить U только к одной константе. После этого выражение становится беззнаковым, так, что ли? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Aurochs 0 26 января, 2011 Опубликовано 26 января, 2011 · Жалоба Но, посмотрите - в последних двух случаях - достаточно добавить U только к одной константе. После этого выражение становится беззнаковым, так, что ли? Такова селяви. В соответствии со стандартом при выполнении арифм. операций в случае, когда один операнд знаковый, а другой - беззнаковый, производится приведение к беззнаковому типу. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 27 января, 2011 Опубликовано 27 января, 2011 · Жалоба И все-же, я не уверен, что этот код 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 0 27 января, 2011 Опубликовано 27 января, 2011 · Жалоба (x<0) ? ((x+1)>>1): (x>>1) Спасибо! Сами не ведая, помогли мне багу найти. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 27 января, 2011 Опубликовано 27 января, 2011 · Жалоба Спасибо! Сами не ведая, помогли мне багу найти. :) Может быть, и не только вам :) Себе, так уж точно. Книжка эта есть "в закромах". Просто бомба, а не книжка. (неуместное сравнение, извиняюсь!) Настоящая Библия! Жаль, что не про Cortex. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 27 января, 2011 Опубликовано 27 января, 2011 · Жалоба В-общем, при делении на положительную константу U лучше не игнорировать. Никогда об этом не задумывался. Спасибо! -3 / 2 = -1 -3 = 0b11111101 (0b11111101 + 1)/2 = 0b11111110/2 = 0b11111111 = -1 верно! (0b11111101 + 0)/2 = 0b11111101/2 = 0b11111110 = -2 неверно! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 27 января, 2011 Опубликовано 27 января, 2011 · Жалоба Никогда об этом не задумывался.Вообще говоря методов округления существует больше, чем один. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 27 января, 2011 Опубликовано 27 января, 2011 · Жалоба Вообще говоря методов округления существует больше, чем один. дело в де-факто стандарте, а не в методах, а если его не придерживаться там, где это надо - это бага, имхо, вылезет она сразу или существенно позже.. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 27 января, 2011 Опубликовано 27 января, 2011 · Жалоба ... а если его не придерживаться там, где это надо - это бага Что за бага? И кто багописатель? У ViKo никаких багов не было. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться