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

 
 
> Искусство программирования на Си/си++, Или как правильно объяснить компилятору...
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
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 27)
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
am1808
сообщение Jan 17 2012, 05:51
Сообщение #16


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

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



Цитата(demiurg_spb @ Jan 17 2012, 09:44) *
Конечно. Чего вы юлите я не пойму?
Для всех кроме вас очевидно что разрядность переменных влияет на скорость выполнения программ. Точка.

разрядность используемых в вашем примере выше никак не влияет,
влияет unsigned или signed переменная.
компилятор явно приводит в случае uint_fast8_t к unsigned, что и приводит к лишней операции, за счет цикла кол-во операций увеличивается в вашем примере на 8 тактов.
это просто конкретная фича компилятора, и в принципе, другой компилятор может явно не делать
Код
UXTB     r1,r1


так что зря вы так, в приведенном вашем примере не влияет РАЗРЯДНОСТЬ, выше я объяснил почему.
так что ваш пример плох и не подтверждает ваше высказывание выше
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jan 17 2012, 05:55
Сообщение #17


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

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



Вам что в лоб что по лбу. Честное слово!
Проверил специально для вас:
Разница лишь в том что стало SXTB вместо UXTB
Код
00000e  b249              SXTB     r1,r1;25


А вы продолжайте наедятся на безграничные возможности оптимизирующего компилятора.
За сим, откланяюсь. Удачи!


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


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

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



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

Я использую 32-битные и 64-битные переменные. Ну от типа char не уйти.
За статью - отдельное спасибо! Обязательно почитаю!
QUOTE (AHTOXA @ Jan 17 2012, 13:09) *
А в остальном - нормальный код, руками выйдет практически такой же.
ЗЫ. Попробуйте -O2, с ним вроде получше получается местами.

Хорошо!
QUOTE (Idle @ Jan 17 2012, 13:33) *
всё правильно, не бери в голову

Может быть действительно переволновался...

Опять же, говоря, что код большой, я не могу представить, чего ожидаю увидеть от компилятора... Наверно это чисто эмоциональное восприятие...


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


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

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



Цитата(demiurg_spb @ Jan 17 2012, 09:55) *
Вам что в лоб что по лбу. Честное слово!

Не тратьте свое время на этого индивида. По-моему об уровне am1808 можно понять по первым ответам в этой теме. Вы же ему даже разжевали все подробно - не помогло.
Go to the top of the page
 
+Quote Post
am1808
сообщение Jan 17 2012, 06:03
Сообщение #20


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

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



Цитата(demiurg_spb @ Jan 17 2012, 09:55) *
Вам что в лоб что по лбу. Честное слово!

не нервничайте, уважаемый biggrin.gif
Цитата(demiurg_spb @ Jan 17 2012, 09:55) *
Проверил специально для вас:
Разница лишь в том что стало SXTB вместо UXTB
Код
00000e  b249              SXTB     r1,r1;25

так проверьте теперь для int и unsigned int, и сделайте для себя вывод

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


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

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



И снова здравствуйте!
Все варианты исчерпали? За упорство a14.gif
Код
    for (int32_t i=0; i<8; i++)// 18324
    for (uint32_t i=0; i<8; i++)// 18324
И что?


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


Знающий
****

Группа: Участник
Сообщений: 783
Регистрация: 22-11-08
Пользователь №: 41 858



Цитата(am1808 @ Jan 17 2012, 09:51) *
так что ваш пример плох и не подтверждает ваше высказывание выше


У современных ARM нет 8/16 битных регистров и компилятору приходится эмулировать их, в частности переполнение. В некоторых случаях компилятор сглаживает этот факт и не генерирует лишнего кода - но все равно рекомендуется локальные переменные, передаваемые и возвращаемые данные в ф-ции делать соразмерными с регистрами, кроме тех случаев когда нужно именно такое поведение - 8 или 16 битная переменная или когда переменные глобальные (для экономии памяти).
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jan 17 2012, 08:21
Сообщение #23


Универсальный солдатик
******

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



В закромах была книжка Arm System Developer's Guide.
Настоятельно советую am1808 скачать. Там куча примеров по данной теме.
Go to the top of the page
 
+Quote Post
am1808
сообщение Jan 17 2012, 08:26
Сообщение #24


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

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



Цитата(sasamy @ Jan 17 2012, 12:07) *
У современных ARM нет 8/16 битных регистров и компилятору приходится эмулировать их, в частности переполнение. В некоторых случаях компилятор сглаживает этот факт и не генерирует лишнего кода - но все равно рекомендуется локальные переменные, передаваемые и возвращаемые данные в ф-ции делать соразмерными с регистрами, кроме тех случаев когда нужно именно такое поведение - 8 или 16 битная переменная или когда переменные глобальные (для экономии памяти).

на сколько мне известно, все локальные переменные в отличии от 32b, выравниваются по word, т.е. 4 байта.
то, что кейл в вышеприведенном примере добавляет инструкцию, это причиндалы самого компилятора, который таким образом пытается занулить память, которая выделилась по причине выравнивания. т.е. получается, что кейл лишний раз себя как бы страхует
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jan 17 2012, 08:30
Сообщение #25


Универсальный солдатик
******

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



Цитата(am1808 @ Jan 17 2012, 10:26) *
на сколько мне известно, все локальные переменные в отличии от 32b, выравниваются по word, т.е. 4 байта.
то, что кейл в вышеприведенном примере добавляет инструкцию, это причиндалы самого компилятора, который таким образом пытается занулить память, которая выделилась по причине выравнивания. т.е. получается, что кейл лишний раз себя как бы страхует

локальные переменные в регистрах хранятся, пока место есть
Go to the top of the page
 
+Quote Post
am1808
сообщение Jan 17 2012, 08:39
Сообщение #26


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

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



Цитата(ViKo @ Jan 17 2012, 12:30) *
локальные переменные в регистрах хранятся, пока место есть

я не про регистры говорю, а то что выделяется на стеке
Go to the top of the page
 
+Quote Post
sasamy
сообщение Jan 17 2012, 10:17
Сообщение #27


Знающий
****

Группа: Участник
Сообщений: 783
Регистрация: 22-11-08
Пользователь №: 41 858



Цитата(am1808 @ Jan 17 2012, 12:26) *
то, что кейл в вышеприведенном примере добавляет инструкцию, это причиндалы самого компилятора, который таким образом пытается занулить память, которая выделилась по причине выравнивания. т.е. получается, что кейл лишний раз себя как бы страхует


Он как раз эмулирует поведение 8 битного регистра - обнуляет старшие разряды, потому что не знает заранее произойдет или нет переполнение 8 бит.

Код
short sum_v1(char *data)
{
    char i;
    int sum = 0;

    for (i = 0; i<32; i++)
        sum += *(data++);

    return (short)sum;
}

short sum_v2(char *data)
{
    char i;
    short sum = 0;

    for (i = 0; i<32; i++)
        sum += *(data++);

    return sum;
}


Код
sasa@sasa-laptop:~/test$ arm-linaro-linux-gnueabi-gcc -c -g -O3 int_vs_short.c && arm-linaro-linux-gnueabi-objdump -d ./int_vs_short.o

./int_vs_short.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <sum_v1>:
   0:    2300          movs    r3, #0
   2:    f100 0120     add.w    r1, r0, #32
   6:    f810 2b01     ldrb.w    r2, [r0], #1
   a:    4288          cmp    r0, r1
   c:    4413          add    r3, r2
   e:    d1fa          bne.n    6 <sum_v1+0x6>
  10:    b218          sxth    r0, r3
  12:    4770          bx    lr

00000014 <sum_v2>:
  14:    2300          movs    r3, #0
  16:    f100 0120     add.w    r1, r0, #32
  1a:    f810 2b01     ldrb.w    r2, [r0], #1
  1e:    18d3          adds    r3, r2, r3
  20:    4288          cmp    r0, r1
  22:    b29b          uxth    r3, r3 @ подготовка к следующей итерации - регистр должен содержать не больше 16 бит
  24:    d1f9          bne.n    1a <sum_v2+0x6>
  26:    b218          sxth    r0, r3
  28:    4770          bx    lr
  2a:    bf00          nop


как видишь он заранее знал что char i не переполнится поэтому ничего не сгенерировал и оказался совершенно без понятия о том переполнится или нет short sum, поэтому вынужден всегда занулять старшие разряды.

Сообщение отредактировал sasamy - Jan 17 2012, 10:25
Go to the top of the page
 
+Quote Post
haker_fox
сообщение Jan 18 2012, 11:31
Сообщение #28


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

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



Скачал материалы, рекомендованные к прочтению. Спасибо!!!


--------------------
Выбор.
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 - 09:10
Рейтинг@Mail.ru


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