реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Искусство программирования на Си/си++, Или как правильно объяснить компилятору...
haker_fox
сообщение Jan 17 2012, 02:29
Сообщение #1


Познающий...
******

Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125



Здравствуйте, уважаемые коллеги!
Вчера глянул в листинг компилятора (arm-kgp за 2009 год) и озадачился. При том, что комплятору дан ключ -Os.
Вроде бы из простых функций, получается довольно "пухлый" код на асме.
Вот например (вначале исходник на Си, затем листинг)
CODE

/*
This function gets and sends a char
IN: nothing

OUT: received char
*/
char getChar()
{
char tmp;

while( !( U0LSR & ( 1UL << 0 ) ) );
tmp = U0RBR;
putChar( tmp );

return tmp;
}

CODE
00000788 <getChar>:
     788:    e59f202c     ldr    r2, [pc, #44]; 7bc <getChar+0x34>
     78c:    e5923014     ldr    r3, [r2, #20]
     790:    e3130001     tst    r3, #1; 0x1
     794:    e59f3020     ldr    r3, [pc, #32]; 7bc <getChar+0x34>
     798:    0afffffb     beq    78c <getChar+0x4>
     79c:    e5930000     ldr    r0, [r3]
     7a0:    e20000ff     and    r0, r0, #255; 0xff
     7a4:    e5932014     ldr    r2, [r3, #20]
     7a8:    e3120020     tst    r2, #32; 0x20
     7ac:    0afffffc     beq    7a4 <getChar+0x1c>
     7b0:    e59f3004     ldr    r3, [pc, #4]; 7bc <getChar+0x34>
     7b4:    e5830000     str    r0, [r3]
     7b8:    e12fff1e     bx    lr
     7bc:    e000c000     .word    0xe000c000

или вот
CODE
int64_t getNum( F_BOOT_RESULT* flag )
{
char c;
int64_t result = 0;
uint32_t negFlag = 0;
uint32_t hexFlag = 0;

*flag = F_BOOT_NO_RESULT;

while( 1 )
{
c = getChar();

if( (c == '\r') || (c == '\n'))
{
break;
}

if( c == '-' )
{
negFlag = 1;
continue;
}

if( c == 'x' )
{
hexFlag = 1;
continue;
}

if( hexFlag )
result *= 16;
else
result *= 10;

if( hexFlag )
result += hexToDec( c );
else
result += c - 0x30;

*flag = F_BOOT_OK;
}

if( negFlag )
{
result *= -1;
}

return result;
}


CODE
00000864 <getNum>:
864: e59f2104 ldr r2, [pc, #260]; 970 <getNum+0x10c>
868: e92d0ff0 push {r4, r5, r6, r7, r8, r9, sl, fp}
86c: e3a03002 mov r3, #2; 0x2
870: e3a05000 mov r5, #0; 0x0
874: e5803000 str r3, [r0]
878: e1a08005 mov r8, r5
87c: e3a03000 mov r3, #0; 0x0
880: e3a04000 mov r4, #0; 0x0
884: e1a09002 mov r9, r2
888: e3a0a00a mov sl, #10; 0xa
88c: e5921014 ldr r1, [r2, #20]
890: e3110001 tst r1, #1; 0x1
894: 0afffffc beq 88c <getNum+0x28>
898: e5921000 ldr r1, [r2]
89c: e1a0600b mov r6, fp
8a0: e20110ff and r1, r1, #255; 0xff
8a4: e1a0700c mov r7, ip
8a8: e592c014 ldr ip, [r2, #20]
8ac: e31c0020 tst ip, #32; 0x20
8b0: 0afffffc beq 8a8 <getNum+0x44>
8b4: e351000d cmp r1, #13; 0xd
8b8: 1351000a cmpne r1, #10; 0xa
8bc: e1a0b006 mov fp, r6
8c0: e1a0c007 mov ip, r7
8c4: e5891000 str r1, [r9]
8c8: 0a000020 beq 950 <getNum+0xec>
8cc: e351002d cmp r1, #45; 0x2d
8d0: 03a08001 moveq r8, #1; 0x1
8d4: 0affffec beq 88c <getNum+0x28>
8d8: e3510078 cmp r1, #120; 0x78
8dc: 03a05001 moveq r5, #1; 0x1
8e0: 0affffe9 beq 88c <getNum+0x28>
8e4: e3550000 cmp r5, #0; 0x0
8e8: 0a000003 beq 8fc <getNum+0x98>
8ec: e3510039 cmp r1, #57; 0x39
8f0: 92411030 subls r1, r1, #48; 0x30
8f4: 9a000009 bls 920 <getNum+0xbc>
8f8: ea000005 b 914 <getNum+0xb0>
8fc: e0876a93 umull r6, r7, r3, sl
900: e027749a mla r7, sl, r4, r7
904: e2411030 sub r1, r1, #48; 0x30
908: e0963001 adds r3, r6, r1
90c: e0a74fc1 adc r4, r7, r1, asr #31
910: ea00000b b 944 <getNum+0xe0>
914: e3510041 cmp r1, #65; 0x41
918: 92411037 subls r1, r1, #55; 0x37
91c: 82411057 subhi r1, r1, #87; 0x57
920: e1a06001 mov r6, r1
924: e1a07fc6 asr r7, r6, #31
928: e1a01204 lsl r1, r4, #4
92c: e1811e23 orr r1, r1, r3, lsr #28
930: e1a0c001 mov ip, r1
934: e1a01203 lsl r1, r3, #4
938: e0963001 adds r3, r6, r1
93c: e1a0b001 mov fp, r1
940: e0a7400c adc r4, r7, ip
944: e3a01000 mov r1, #0; 0x0
948: e5801000 str r1, [r0]
94c: eaffffce b 88c <getNum+0x28>
950: e3580000 cmp r8, #0; 0x0
954: 0a000001 beq 960 <getNum+0xfc>
958: e2733000 rsbs r3, r3, #0; 0x0
95c: e2e44000 rsc r4, r4, #0; 0x0
960: e1a01004 mov r1, r4
964: e1a00003 mov r0, r3
968: e8bd0ff0 pop {r4, r5, r6, r7, r8, r9, sl, fp}
96c: e12fff1e bx lr
970: e000c000 .word 0xe000c000

Я плохо понимаю язык ассемблера для ARM7TDMI-S, но мне кажется, что слишком много кода...
Вопрос трудно поставить... Но похоже, что я плохо объясняю, что нужно сделать компилятору. Нет, код работает, есть "косметические" ошибки, но поставленный алгоритм выполняется. Дело в другом. Компялтор раздувает код (или я ошибаюсь?). Вот я и озадачился вопросом, что я делаю не правильно? Может быть не те типы данных использую? Конструкции языка? Или исходный код на Си нужно выбросить, и написать более компактный, более красивый?
В общем вопрос пока пространственный... его можно было и не задавать, ведь 512К флеши есть, но, тем не менее...
Заранее спасибо за все ответы!


--------------------
Выбор.
Go to the top of the page
 
+Quote Post
sparcmaster
сообщение Jan 17 2012, 04:27
Сообщение #2


Частый гость
**

Группа: Свой
Сообщений: 93
Регистрация: 13-01-12
Из: Гатчина
Пользователь №: 69 333



Не пытайтесь заменить компилятор, особенно с доступной вам памятью. Вы можете переписать эту функцию более оптимально, но что делать, когда проект разрастется на 10 тыс. строк?

PS: Т.к. arm 32 битный, то для скорости, я стараюсь использовать только 32 битные переменные (даже там, где нужен всего байт).
PPS: Если интересно, можете почитать эту статью.
Go to the top of the page
 
+Quote Post
am1808
сообщение Jan 17 2012, 04:56
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 125
Регистрация: 29-05-11
Из: Nizhny Novgorod, Russian Federation
Пользователь №: 65 337



Цитата(sparcmaster @ Jan 17 2012, 08:27) *
PS: Т.к. arm 32 битный, то для скорости, я стараюсь использовать только 32 битные переменные (даже там, где нужен всего байт).

скорость у вас сильно увеличилась ? biggrin.gif

дело не в том, какие переменные, а как они выравнены в памяти

Сообщение отредактировал am1808 - Jan 17 2012, 04:56
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jan 17 2012, 04:59
Сообщение #4


неотягощённый злом
******

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



Цитата(am1808 @ Jan 17 2012, 07:56) *
дело не в том, какие переменные, а как они выравнены в памяти
Дело и в том и другом.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
am1808
сообщение Jan 17 2012, 05:01
Сообщение #5


Частый гость
**

Группа: Участник
Сообщений: 125
Регистрация: 29-05-11
Из: Nizhny Novgorod, Russian Federation
Пользователь №: 65 337



Цитата(demiurg_spb @ Jan 17 2012, 08:59) *
Дело и в том и другом.

ошибаетесь)
Go to the top of the page
 
+Quote Post
sparcmaster
сообщение Jan 17 2012, 05:04
Сообщение #6


Частый гость
**

Группа: Свой
Сообщений: 93
Регистрация: 13-01-12
Из: Гатчина
Пользователь №: 69 333



Цитата(am1808 @ Jan 17 2012, 08:56) *
скорость у вас сильно увеличилась ? biggrin.gif

Для меня достаточно.
Цитата(am1808 @ Jan 17 2012, 08:56) *
дело не в том, какие переменные, а как они выравнены в памяти

Ну да, ну да. Разрядность архитектуры совсем не причем, главное как переменные "выравнены в памяти"...
Go to the top of the page
 
+Quote Post
am1808
сообщение Jan 17 2012, 05:08
Сообщение #7


Частый гость
**

Группа: Участник
Сообщений: 125
Регистрация: 29-05-11
Из: Nizhny Novgorod, Russian Federation
Пользователь №: 65 337



Цитата(sparcmaster @ Jan 17 2012, 09:04) *
Для меня достаточно.

камень не подлетает у вас от такой скорости?
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jan 17 2012, 05:08
Сообщение #8


неотягощённый злом
******

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



Цитата(am1808 @ Jan 17 2012, 08:01) *
ошибаетесь)
Хорошо. Сейчас проверим на Кейле под cortex-m3:
Код
uint8_t spi_transfer(uint8_t data)
{
//    for (int i=0; i<8; i++)                   //  Размер программы 18440
    for (uint8_t i=0; i<8; i++)             //  Размер программы 18444
    {
        SPI_SCK(0);
        SPI_MOSI(data & (1<<7));        // write data at the begin of cycle
        spi_delay();

        SPI_SCK(1);
        spi_delay();
        data = (data<<1) | SPI_MISO();  // read data at the end of cycle
    }

    return data;    
}
Достаточно? Или показать ещё и асм-листинг?
А если так:
Код
uint_fast8_t  spi_transfer(uint_fast8_t data) {...} //  Размер программы 18336
uint8_t  spi_transfer(uint8_t data) {...} //  Размер программы 18440
Не спроста?


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jan 17 2012, 05:09
Сообщение #9


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(haker_fox @ Jan 17 2012, 08:29) *
Вопрос трудно поставить... Но похоже, что я плохо объясняю, что нужно сделать компилятору.

Посмотрел, вполне нормальный код (первый пример). Единственное, что приходит в голову - если U0LSR и U0RBR рядом, то можно дать понять это компилятору, объединив их в структуру, и адресуя их указателем на эту структуру. Тогда базовый адрес будет грузиться всего один раз. А в остальном - нормальный код, руками выйдет практически такой же.
ЗЫ. Попробуйте -O2, с ним вроде получше получается местами.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
am1808
сообщение Jan 17 2012, 05:21
Сообщение #10


Частый гость
**

Группа: Участник
Сообщений: 125
Регистрация: 29-05-11
Из: Nizhny Novgorod, Russian Federation
Пользователь №: 65 337



Цитата(demiurg_spb @ Jan 17 2012, 09:08) *
Хорошо. Сейчас проверим на Кейле под cortex-m3:
Код
uint8_t spi_transfer(uint8_t data)
{
//    for (int i=0; i<8; i++)                   //  Размер программы 18440
    for (uint8_t i=0; i<8; i++)             //  Размер программы 18444
    {
        SPI_SCK(0);
        SPI_MOSI(data & (1<<7));        // write data at the begin of cycle
        spi_delay();

        SPI_SCK(1);
        spi_delay();
        data = (data<<1) | SPI_MISO();  // read data at the end of cycle
    }

    return data;    
}
Достаточно? Или показать ещё и асм-листинг?
А если так:
Код
uint_fast8_t  spi_transfer(uint_fast8_t data) {...}
то размер 18336.
Не спроста?

и как это на скорость выполнения повлияло? когда уменьшился лишь сегмент данных
я не знаком с кейлом, попрошу показать, как затайпдефайнино uint_fast8_t

Сообщение отредактировал am1808 - Jan 17 2012, 05:28
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jan 17 2012, 05:29
Сообщение #11


неотягощённый злом
******

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



Цитата(am1808 @ Jan 17 2012, 08:21) *
и как это на скорость выполнения повлияло? когда уменьшился лишь сегмент данных

Прямо пропорционально:
Код
                  |L5.8|
тело цикла
00000c  1c49              ADDS     r1,r1,#1        ;25
00000e  2908              CMP      r1,#8        ;25
000010  d3fa              BCC      |L5.8|

Код
                  |L5.8|
тело цикла
00000c  1c49              ADDS     r1,r1,#1        ;25
00000e  b2c9              UXTB     r1,r1        ;25
000010  2908              CMP      r1,#8        ;25
000012  d3f9              BCC      |L5.8|

На каждом шаге цикла проигрываем на один такт.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Idle
сообщение Jan 17 2012, 05:33
Сообщение #12


Местный
***

Группа: Участник
Сообщений: 351
Регистрация: 5-04-05
Пользователь №: 3 874



Цитата(haker_fox @ Jan 17 2012, 05:29) *
что я делаю не правильно?

всё правильно, не бери в голову
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jan 17 2012, 05:36
Сообщение #13


неотягощённый злом
******

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



Цитата(am1808 @ Jan 17 2012, 08:21) *
я не знаком с кейлом, попрошу показать, как затайпдефайнино uint_fast8_t
Это не важно кейл или gcc или iar.
Загляните в stdint.h для любого 32-битного ARM-компилятора и везде будет примерно одно:
Код
typedef unsigned           int uint_fast8_t;




--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
am1808
сообщение Jan 17 2012, 05:36
Сообщение #14


Частый гость
**

Группа: Участник
Сообщений: 125
Регистрация: 29-05-11
Из: Nizhny Novgorod, Russian Federation
Пользователь №: 65 337



Цитата(demiurg_spb @ Jan 17 2012, 09:29) *
На каждом шаге цикла проигрываем на один такт.

оптимизация выключена?
какая версия ядра arm?


Сообщение отредактировал am1808 - Jan 17 2012, 05:44
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jan 17 2012, 05:44
Сообщение #15


неотягощённый злом
******

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



Цитата(am1808 @ Jan 17 2012, 08:36) *
оптимизация выключена?
Конечно. Чего вы юлите я не пойму?
Для всех кроме вас очевидно что разрядность как переменных так и самого таргета влияют на скорость выполнения программ. Точка.
Собственно для сглаживания этого эффекта при смене архитектуры и были придуманы типы из stdint...
Цитата
какая версия ядра arm?
Да ведь вроде ясно сказал ещё в сообщении №8 что cortex-m3.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 04:03
Рейтинг@Mail.ru


Страница сгенерированна за 0.01561 секунд с 7
ELECTRONIX ©2004-2016