Сб окт 23, 2021 09:12:25
Сб окт 23, 2021 09:18:09
При том, что именно эта ветка дискуссии была про AVR, естественно.Не понял - а при чём тут AVR если тема про ARM?
for(;;);
Сб окт 23, 2021 09:33:18
Сб окт 23, 2021 10:12:55
Сб окт 23, 2021 10:19:40
COKPOWEHEU, а как насчет на F0 проверить?
#define B35 (1ULL<<35)
char* utoa10(uint32_t x, char *str){
#define D ((B35 + 5) / 10)
uint32_t i;
char *s1, *s = str;
do{
x = (i=x) * D >> 35;
*(s++) = i - x * 10 + '0';
}while(x);
s[0] = 0;
s1 = str;
while((uint32_t)--s > (uint32_t)str){
i = s[0];
s[0] = str[0];
*(str++) = i;
}
return s1;
#undef D
}
char* u32toa(uint32_t val, char *buf){
buf+=11;
buf[0] = 0;
do{
buf--;
buf[0] = val % 10;
val /= 10;
if(buf[0] < 10)buf[0] += '0'; else buf[0] = buf[0] - 0x0A + 'A';
}while(val);
return buf;
}
#define B35 (1ULL<<35)
char* utoa10_2(uint32_t x, char *str){
#define D ((B35 + 5) / 10)
uint32_t i;
char *s = str+11;
s[0] = 0;
do{
x = (i=x) * D >> 35;
*(--s) = i - x * 10 + '0';
}while(x);
return s;
#undef D
}
Сб окт 23, 2021 10:33:27
Сб окт 23, 2021 11:15:47
Пруфы где? Пока я вижу, что разница незначительная, причем иногда даже в пользу моего варианта.потому твой вариант с делением и взятием остатка - это один из самых медленных подходов.
Сб окт 23, 2021 11:27:18
Сб окт 23, 2021 12:03:43
char* u32toa(uint32_t val, char* buf)
{
buf += 11;
*buf = 0;
do
{
buf--;
buf[0] = val % 10;
val /= 10;
if (buf[0] < 10) buf[0] += '0';
else buf[0] -= 0x0A + 'A';
} while (val);
return buf;
}
char* u32toa2(uint32_t val, char* buf)
{
buf += 11;
*buf = 0;
do
{
buf--;
uint32_t tmp = val;
val /= 10;
*buf = tmp - val * 10;
if (*buf < 10) *buf += '0';
else *buf -= 0x0A + 'A';
} while (val);
return buf;
}
uint32_t divu10(uint32_t val) { return val * (((1ULL << 35) + 5) / 10) >> 35; }
char* u32toa3(uint32_t val, char* buf)
{
buf += 11;
*buf = 0;
do
{
buf--;
uint32_t tmp = val;
val = divu10(val);
*buf = tmp - val * 10;
if (*buf < 10) *buf += '0';
else *buf -= 0x0A + 'A';
} while (val);
return buf;
}
..........
volatile uint32_t val = 4294967295;
PerfCounter pc;
pc.start();
for (uint32_t i = 100; i > 0; i--)
{
u32toa(val, buf); // 258'906
//u32toa2(val, buf); // 138'506
//u32toa3(val, buf); // 95'713
}
auto t = pc.getElapsedTicks();
rtt.println(t);
Сб окт 23, 2021 12:27:25
void printuhex(uint32_t val){
addtobuf("0x");
uint8_t *ptr = (uint8_t*)&val + 3;
int i, j, z = 1;
for(i = 0; i < 4; ++i, --ptr){
if(*ptr == 0){ // omit leading zeros
if(i == 3) z = 0;
if(z) continue;
}
else z = 0;
for(j = 1; j > -1; --j){
uint8_t half = (*ptr >> (4*j)) & 0x0f;
if(half < 10) bufputchar(half + '0');
else bufputchar(half - 10 + 'a');
}
}
}
Сб окт 23, 2021 12:34:30
Сб окт 23, 2021 12:42:15
Напомню что язык Си совершенно бесплатно даёт возможность отстрелить себе все конечности. У нас именно такой случай.
В идеале нужно обвесить функцию проверками размера стека,
Да, именно это мне и нужно, что ж вы изворачиваетесь-то постоянно от прямого вопроса! Где тесты? Опять от вас одни "логические соображения".Берем STM32G0(M0+) и тестим(-O2)
Сб окт 23, 2021 13:10:07
buf[0] = val % 10;
val /= 10;
Сб окт 23, 2021 13:55:40
Три разных функции это хорошо, жаль вы не выложили по ним результаты.я написал три разных функции, протестил их и результаты
Деление выполняется единажды, о чем я уже писал. Получение частного и остатка это одна функция.т.е. деление выполняется дважды
Сб окт 23, 2021 14:26:40
COKPOWEHEU писал(а):Деление выполняется единажды, о чем я уже писал. Получение частного и остатка это одна функция.
buf[0] = val % 10;
0x20001ec4 movs r1, #10
0x20001ec6 movs r0, r5
0x20001ec8 bl 0x20001824 <__aeabi_uidivmod>
val /= 10;
0x20001ecc movs r0, r5
0x20001ece uxtb r4, r1
0x20001ed0 movs r1, #10
0x20001ed2 bl 0x20001718 <__udivsi3> ; раз udiv
__aeabi_uidivmod:
0x20001824 cmp r1, #0
0x20001826 beq.n 0x20001818 <__udivsi3+256>
0x20001828 b.n 0x20001718 <__udivsi3> ; два udiv
0x2000182a bx lr
Сб окт 23, 2021 15:33:13
Да? И где там исходный вариант jcxz - который с переворотом строки?Под спойлером есть все, что нужно
Даже не знаю что еще считать, если я уже даже название этой функции выложил. Ну ладно. Вот для AVR, с которого мы начали обсуждение:Ну давай считать:
char* u32toa(uint32_t val, char *buf){
c0: cf 92 push r12
c2: df 92 push r13
c4: ef 92 push r14
c6: ff 92 push r15
c8: cf 93 push r28
ca: df 93 push r29
cc: dc 01 movw r26, r24
ce: cb 01 movw r24, r22
buf+=10;
d0: ea 01 movw r28, r20
d2: 2a 96 adiw r28, 0x0a ; 10
buf[1] = 0;
d4: fa 01 movw r30, r20
d6: 13 86 std Z+11, r1 ; 0x0b
do{
buf[0] = val % 10;
d8: 2a e0 ldi r18, 0x0A ; 10
da: c2 2e mov r12, r18
dc: d1 2c mov r13, r1
de: e1 2c mov r14, r1
e0: f1 2c mov r15, r1
val /= 10;
e2: bc 01 movw r22, r24
e4: cd 01 movw r24, r26
e6: a7 01 movw r20, r14
e8: 96 01 movw r18, r12
ea: 36 d0 rcall .+108 ; 0x158 <__udivmodsi4>
ec: da 01 movw r26, r20
ee: c9 01 movw r24, r18
if(buf[0] < 10)buf[0] += '0'; else buf[0] = buf[0] - 0x0A + 'A';
f0: 60 5d subi r22, 0xD0 ; 208
f2: 68 83 st Y, r22
buf--;
f4: 21 97 sbiw r28, 0x01 ; 1
}while(val);
f6: 23 2b or r18, r19
f8: 24 2b or r18, r20
fa: 25 2b or r18, r21
fc: 91 f7 brne .-28 ; 0xe2 <u32toa+0x22>
return buf;
}
fe: ce 01 movw r24, r28
100: df 91 pop r29
102: cf 91 pop r28
104: ff 90 pop r15
106: ef 90 pop r14
108: df 90 pop r13
10a: cf 90 pop r12
10c: 08 95 ret
08000534 <u32toa>:
char* u32toa(uint32_t val, char *buf){
buf+=11;
buf[0] = 0;
8000534: 2200 movs r2, #0
char* u32toa(uint32_t val, char *buf){
8000536: b510 push {r4, lr}
do{
buf--;
buf[0] = val % 10;
val /= 10;
8000538: 240a movs r4, #10
char* u32toa(uint32_t val, char *buf){
800053a: 4603 mov r3, r0
buf[0] = 0;
800053c: 72ca strb r2, [r1, #11]
buf+=11;
800053e: f101 000b add.w r0, r1, #11
val /= 10;
8000542: fbb3 f1f4 udiv r1, r3, r4
buf[0] = val % 10;
8000546: fb04 3211 mls r2, r4, r1, r3
if(buf[0] < 10)buf[0] += '0'; else buf[0] = buf[0] - 0x0A + 'A';
}while(val);
800054a: 2b09 cmp r3, #9
if(buf[0] < 10)buf[0] += '0'; else buf[0] = buf[0] - 0x0A + 'A';
800054c: f102 0230 add.w r2, r2, #48 ; 0x30
8000550: f800 2d01 strb.w r2, [r0, #-1]!
}while(val);
8000554: d800 bhi.n 8000558 <u32toa+0x24>
return buf;
}
8000556: bd10 pop {r4, pc}
val /= 10;
8000558: 460b mov r3, r1
800055a: e7f2 b.n 8000542 <u32toa+0xe>
Сб окт 23, 2021 16:06:48
Сб окт 23, 2021 17:31:11
При чем здесь M0? На AVR, где нет не только аппаратного умножения и деления, но хоть какой-то работы с числами больше 8 бит, разница незначительная.Какое отношение к медленной работе функции на M0
Посмотрите вот на это сообщение, вот на это. И потом на свое. И сравните где результаты измерений, а где куски кода.И после этого ты попросил пруфы, которые с первого раза вообще не заметил
Сб окт 23, 2021 18:49:11
Сб окт 23, 2021 21:46:44
Если говоря про M0, при этом цитируя пост про L151
А в 2.7 раза это сколько в тактах? Может, там как и в AVR десять тысяч тактов и оба варианта годятся только отладочную информацию раз в вечность передавать. То есть не "данные для любознательных" закопаны под спойлер, а просто какие-то сырые данные без пояснений.было написано, что последняя функция, у которой убрано вычисление остатка от деления и заменено само деление выполняется в 2.7 раза быстрее