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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> ARM Ассемблер, программирование-искусство?
Tarkus
сообщение Mar 5 2009, 10:21
Сообщение #1





Группа: Участник
Сообщений: 9
Регистрация: 22-02-09
Пользователь №: 45 211



Читал heyrick.co.uk, автор - апологет принципа "код - произведение искусства" smile.gif
Например, в одну инструкцию:

BIC R0, R0, R0, ASR#31 ; IF R0 < 0 THEN R0 = 0

Или еще лучше, таблица из "N" переходов с помощью всего двух инструкций:

.swihandler
CMP R11, #((endofjumptable - startofjumptable) / 4)
ADDCC PC, PC, R11, LSL #2
B error
.startofjumptable
B swi0
B swi1
; etc...
.endofjumptable

Честно говоря, не понял принципа работы второго примера. Кто-нибудь может прояснить?
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Mar 5 2009, 10:49
Сообщение #2


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Код
.swihandler

; На вход R11 - индекс в таблице переходов 0..макс. допустимый индекс


  CMP   R11, #((endofjumptable - startofjumptable) / 4);  проверили чтоб R11 < (макс.доп индекс + 1)
  ADDCC PC, PC, R11, LSL #2; и выполнили переход
  B     error; иначе перешли на обработку ошибки "недопустимый входной параметр"
.startofjumptable
B      swi0
B    swi1
; etc...
.endofjumptable

Где-то так. Сорри, форматтер кода - полный боян, такшта несколько нечитабельно
Go to the top of the page
 
+Quote Post
scifi
сообщение Mar 5 2009, 10:55
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Tarkus @ Mar 5 2009, 13:21) *
CMP R11, #((endofjumptable - startofjumptable) / 4)
ADDCC PC, PC, R11, LSL #2
B error
.startofjumptable
B swi0
B swi1
; etc...
.endofjumptable

Честно говоря, не понял принципа работы второго примера. Кто-нибудь может прояснить?

Неужели лень заглянуть в список инструкций ARM? Сравнение для того, чтобы R11 было меньше или равно размера таблицы. Если действительно меньше или равно, то прыгнуть на адрес PC+(4*R11), где PC указывает на "B swi0". В противном случае выполняется "B error".

Цитата(Tarkus @ Mar 5 2009, 13:21) *
Читал heyrick.co.uk, автор - апологет принципа "код - произведение искусства" smile.gif

Этот принцип для досужей потехи хорош, а для профессиональной деятельности крайне вреден. Если так ковыряться в инструкциях, то времени на работу не останется :-)
Go to the top of the page
 
+Quote Post
KRS
сообщение Mar 5 2009, 10:59
Сообщение #4


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



да в этих примерах ничего удивительного нет!
а таблицу переходов таким образом любой нромальный компилятор строит!
Так что если хотите посмотреть на особености ARM ассемблера, возьмите разные компиляторы:
IAR, GCC, RVCT (только свежие) поставьте максимальную оптимизацию по времени, потом по скорости и смотрите листинг увидите много хитрых приемов.
Современный ARM компилер трудно обогнать используя ассемблер, особенно при работе с константами - сидеть и вычислять чего куда сдвинуть и счем проксорить... (особенно если вы используете текстовое имя константы, а компилер то знает ее значение...)
В общем, очень мало место осталось где стоит применять ASM ( но знать его все равно полезно)
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Mar 5 2009, 11:04
Сообщение #5


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(KRS @ Mar 5 2009, 13:59) *
Современный ARM компилер трудно обогнать используя ассемблер,


Это уж точно плюс пицот! Дык не все верят в очевидное sad.gif

Цитата
особенно при работе с константами - сидеть и вычислять чего куда сдвинуть и счем проксорить... (особенно если вы используете текстовое имя константы, а компилер то знает ее значение...)



А вот это, простите, не понял. Писанины больше получается - это факт, и выражений всяких поболее надо.
Go to the top of the page
 
+Quote Post
KRS
сообщение Mar 5 2009, 11:19
Сообщение #6


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(_Pasha @ Mar 5 2009, 14:04) *
А вот это, простите, не понял. Писанины больше получается - это факт, и выражений всяких поболее надо.

Например идет простая инициализация переферии.
т.е. надо по куче константных адресов записать константы.
Причем обычно константы представлены не числами, а символически (например не 0x12300 a ADC_REG_CTRL).
Так вот в силу специфики команд ARM не все контсатны можно оптимально загрузить в регистр, но зная их числовые представления и то что до этого было в регистрах можно получать их разными арифметическими и логическими действиями и компилер с этим прекрасно справляется, а вот руками упаришься считать. (типа что бы получиь константу DAC_INIT_1 = 0x48C04 можно (0x1233>>2)+4 а это одна команда для ARM)
Go to the top of the page
 
+Quote Post
Tarkus
сообщение Mar 5 2009, 11:23
Сообщение #7





Группа: Участник
Сообщений: 9
Регистрация: 22-02-09
Пользователь №: 45 211



Цитата(_Pasha @ Mar 5 2009, 12:49) *
.swihandler
ADDCC PC, PC, R11, LSL #2; и выполнили переход
Где-то так. Сорри, форматтер кода - полный боян, такшта несколько нечитабельно

Спасибо, действительно все прозрачно smile.gif
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Mar 5 2009, 11:32
Сообщение #8


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(KRS @ Mar 5 2009, 14:19) *
Так вот в силу специфики команд ARM не все контсатны можно оптимально загрузить в регистр

Да это понятно, обычно Peripheral-Specific макросы в помощь. Правда, я не особо широкого кругозора - дальше GNU AS не интересовался макросредствами для армов, но не сомневаюсь, что у всяких там кейлов с этим все в порядке

Цитата(Tarkus @ Mar 5 2009, 14:23) *
Спасибо

Пожалуйста
Go to the top of the page
 
+Quote Post
kons
сообщение Mar 8 2009, 07:00
Сообщение #9


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

Группа: Свой
Сообщений: 106
Регистрация: 28-09-05
Пользователь №: 9 035



Цитата
Этот принцип для досужей потехи хорош, а для профессиональной деятельности крайне вреден. Если так ковыряться в инструкциях, то времени на работу не останется :-)

Немного не так. Если неохота ковыряться в инструкциях, надо пользоваться C. Например, обсуждаемая здесь инициализация периферии - уж точно не задача для asm. На таких задачах (как и на большинстве прочих), как верно отметил KRS,
Цитата
Современный ARM компилер трудно обогнать используя ассемблер

А вот написать какой-нибудь внутренний короткий цикл на asm (фильтр какой-нибудь или демодулятор) - это часто очень даже имеет смысл. И тут уж все средства хороши. Но (по опыту) максимальный эффект в asm-модуле достигается не жонглированияем битами, а оптимизацией доступа к памяти - использованием вместо кучи LDR/STR одной LDMIA/STMIA. Компилятор так не умеет (ну, кроме входа/выхода в процедуру есс-но). Для ядра ARM7TDMI на задачах типа свертки результат подобного подхода очень даже радует.
Go to the top of the page
 
+Quote Post
ar__systems
сообщение Mar 8 2009, 13:53
Сообщение #10


self made
****

Группа: Свой
Сообщений: 855
Регистрация: 7-03-09
Из: Toronto, Canada
Пользователь №: 45 795



Цитата(kons @ Mar 8 2009, 02:00) *
Немного не так. Если неохота ковыряться в инструкциях, надо пользоваться C. Например, обсуждаемая здесь инициализация периферии - уж точно не задача для asm. На таких задачах (как и на большинстве прочих), как верно отметил KRS,
А вот написать какой-нибудь внутренний короткий цикл на asm (фильтр какой-нибудь или демодулятор) - это часто очень даже имеет смысл. И тут уж все средства хороши. Но (по опыту) максимальный эффект в asm-модуле достигается не жонглированияем битами, а оптимизацией доступа к памяти - использованием вместо кучи LDR/STR одной LDMIA/STMIA. Компилятор так не умеет (ну, кроме входа/выхода в процедуру есс-но). Для ядра ARM7TDMI на задачах типа свертки результат подобного подхода очень даже радует.

Грамотный ответ. Оптимизировать инициализацию переферии - оч глупо. Она выполняется один раз.
Оптимизировать цикл (на асм, по сравнению с С) думаю можно практически всегда, особенно если он написан на С человеком, который ассемблера в жизни не видел.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Mar 8 2009, 14:00
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(ar__systems @ Mar 8 2009, 16:53) *
....если он написан на С человеком, который ассемблера C в жизни не видел.

smile.gif так правильно.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
scifi
сообщение Mar 9 2009, 10:50
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(ar__systems @ Mar 8 2009, 16:53) *
Оптимизировать цикл (на асм, по сравнению с С) думаю можно практически всегда

Зачем оптимизировать всегда? Я хотел донести такую мысль: не нужно оптимизировать, если и без оптимизации хорошо работает. Я думаю, бессмысленная оптимизация уносит слишком большое количество человеко-лет, которые могли бы быть потрачены более эффективно.
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Mar 9 2009, 11:15
Сообщение #13


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Почти в каждой современной книге по С/С++ написано о вреде преждевременной оптимизации и выстраивается последовательность:
1. Программирование алгоритма.
2. Отладка алгоритма и его комплексное тестирование.
3. Изучение быстродействия отдельных функций и модулей.
4. Оптимизация (при необходимости) узких мест.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Mar 9 2009, 11:27
Сообщение #14


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(sergeeff @ Mar 9 2009, 15:15) *
1. Программирование алгоритма.
2. Отладка алгоритма и его комплексное тестирование.
3. Изучение быстродействия отдельных функций и модулей.
4. Оптимизация (при необходимости) узких мест.

Это квадратные советы. Они не учитывают задачи портирования, коих большинство, когда об алгоритме уже известно почти все, надо чтобы оно красиво влезло и не мешало жить наращиваемой функциональности. В таких случаях я лично начинаю с проверки и оптимизации именно узких мест.
Go to the top of the page
 
+Quote Post
KRS
сообщение Mar 9 2009, 11:46
Сообщение #15


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(kons @ Mar 8 2009, 10:00) *
Но (по опыту) максимальный эффект в asm-модуле достигается не жонглированияем битами, а оптимизацией доступа к памяти - использованием вместо кучи LDR/STR одной LDMIA/STMIA. Компилятор так не умеет (ну, кроме входа/выхода в процедуру есс-но).

Иногда очень даже умеет! К тому же использование команд LDM STM не уменьшает количество досупов к памяти данных, а только за счет уменьшения инструкций уменьшается количество досупов к программе, а это не всегда приводит к увеличению быстродействия. И команды LDM STM увеличивают время реакции на прерывание, в RVCT есть даже опция на ограничение числа регистров в этой команде.
А вы можете привести конкретный пример цикла где действительно стоит использовать асм?
Go to the top of the page
 
+Quote Post
MALLOY2
сообщение Mar 9 2009, 12:40
Сообщение #16


Знающий
****

Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317



расчет CRC32, ЦФ, свертка, FFT, практически все матиметические циклы будут на асме работать быстрее! Вопрос вы будите писать их на асм или возьмете мощнее процессор ?
Go to the top of the page
 
+Quote Post
kons
сообщение Mar 9 2009, 12:55
Сообщение #17


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

Группа: Свой
Сообщений: 106
Регистрация: 28-09-05
Пользователь №: 9 035



to KRS.
Вы правы, кол-во обращений к данным не уменьшает, но (для ARM7TDMI, у Cortex и особенно ARM9 разница не столь существенна) LDR - 3 такта/слово, LDMIA - 2+1*кол-во слов. Т.е. при загрузке, скажем, 8 регистров LDRx8 = 24 такта, LDMIA - 10 тактов. Да, забыл сказать - это при выполнении из RAM. При выполнении из флэша на AT91SAM7 добавьте к каждому LDR еще по такту - флеш медленнее, однако.

Простенький пример - цикл вычисления FIR. Данные берутся из циркулярного буфера (DL_PTR, DL_BASE, DL_SIZE). Обрабатываются 4 отвода за раз. Напишите на c, скомпилируйте, посчитайте такты, сравните. А стоит или не стоит это делать на ASM - зависит от потребной частоты вычисления и длины фильтра. В моем случае (Fд=48 кГц, L=20 отводов, и кроме этого еще куча дел) - стоило однозначно. Была бы Fд 8 кГц - не стал бы заморачиваться. Что же касается реакции на прерывания - на то DMA есть.

FIR_DELAY_LOOP MACRO
LOCAL FDL_LP
FDL_LP: LDMDB DL_PTR!,{R_SMP3-R_SMP0} ;8
CMP DL_PTR,DL_BASE
ADDLS DL_PTR,DL_PTR,DL_SIZE
LDMIA SUFF_PTR!,{R_SUFF0-R_SUFF3} ;6
MLA R_ACC,R_SUFF0,R_SMP0,R_ACC ;16
MLA R_ACC,R_SUFF1,R_SMP1,R_ACC
MLA R_ACC,R_SUFF2,R_SMP2,R_ACC
MLA R_ACC,R_SUFF3,R_SMP3,R_ACC
SUBS SUFF_CNT,SUFF_CNT,#4 ;4
BNE FDL_LP
ENDM

P.S. А как тут код нормальный вставлять? Что с цитатой, что без - все одно каша...

to Pasha:
Цитата
Это квадратные советы. Они не учитывают задачи портирования, коих большинство, когда об алгоритме уже известно почти все, надо чтобы оно красиво влезло и не мешало жить наращиваемой функциональности. В таких случаях я лично начинаю с проверки и оптимизации именно узких мест.

+500. Особенно для DSP, и особенно на этапе выбора процессора.
Go to the top of the page
 
+Quote Post
ar__systems
сообщение Mar 9 2009, 13:37
Сообщение #18


self made
****

Группа: Свой
Сообщений: 855
Регистрация: 7-03-09
Из: Toronto, Canada
Пользователь №: 45 795



Цитата(MALLOY2 @ Mar 9 2009, 07:40) *
расчет CRC32, ЦФ, свертка, FFT, практически все матиметические циклы будут на асме работать быстрее! Вопрос вы будите писать их на асм или возьмете мощнее процессор ?


Мощнее процессор решение тупое но часто приемлимое. Иногда, к счастью нет -- иначе бы Visual Basic и в embedded programming пробрался бы smile.gif Когда стоит задача добиться минимального потребления тока оптимизация на асм. очень помогает, ибо каждая лишняя инструкця цикла это сколько-то лишних nA. (При условии что программа в основном спит, и изредка включается чтобы обработать данные).
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Mar 9 2009, 13:39
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(kons @ Mar 9 2009, 15:55) *
P.S. А как тут код нормальный вставлять? Что с цитатой, что без - все одно каша...

Теги [сode] и [сodebox].
Go to the top of the page
 
+Quote Post
KRS
сообщение Mar 9 2009, 14:28
Сообщение #20


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(kons @ Mar 9 2009, 15:55) *
Простенький пример - цикл вычисления FIR. Данные берутся из циркулярного буфера (DL_PTR, DL_BASE, DL_SIZE)...

конечно компилер так не сможет скомпилировать, потому что у вас куча допущений: например длина циклического буфера кратна 4 словам! и соотвественно STUFF_CNT тоже кратно 4. Если вы сумеете объяснить это компилятору...
По поводу раскрутки циклов IAR это делать умеет простой пример:
Код
unsigned test(unsigned *dl, unsigned *suff)
{
    unsigned r;
    unsigned cnt;
    r = 0;
    cnt = 16;
    do {
        r += (*(dl++)) * (*(suff++));
    }while(--cnt);
    return r;
}

получаем листинг
Код
      1          unsigned test(unsigned *dl, unsigned *suff)
      2          {
   \                     test:
   \   00000000   00402DE9           PUSH     {LR}
   \   00000004   04D04DE2           SUB      SP,SP,#+4
      3              unsigned r;
      4              unsigned cnt;
      5              r = 0;
   \   00000008   0020A0E3           MOV      R2,#+0
      6              cnt = 16;
   \   0000000C   0430A0E3           MOV      R3,#+4
      7              do {
      8                  r += (*(dl++)) * (*(suff++));
   \                     ??test_0:
   \   00000010   04C090E4           LDR      R12,[R0], #+4
   \   00000014   04E091E4           LDR      LR,[R1], #+4
   \   00000018   9E2C22E0           MLA      R2,LR,R12,R2
      9              }while(--cnt);
   \   0000001C   04C090E4           LDR      R12,[R0], #+4
   \   00000020   04E091E4           LDR      LR,[R1], #+4
   \   00000024   9E2C22E0           MLA      R2,LR,R12,R2
   \   00000028   04C090E4           LDR      R12,[R0], #+4
   \   0000002C   04E091E4           LDR      LR,[R1], #+4
   \   00000030   9E2C22E0           MLA      R2,LR,R12,R2
   \   00000034   04C090E4           LDR      R12,[R0], #+4
   \   00000038   04E091E4           LDR      LR,[R1], #+4
   \   0000003C   9E2C22E0           MLA      R2,LR,R12,R2
   \   00000040   013053E2           SUBS     R3,R3,#+1
   \   00000044   F1FFFF1A           BNE      ??test_0
     10              return r;
   \   00000048   0200A0E1           MOV      R0,R2
   \   0000004C   04D08DE2           ADD      SP,SP,#+4       ;; stack cleaning
   \   00000050   0080BDE8           POP      {PC}            ;; return
     11          }

да LDMIA конечно не задействован, но раскрутка на лицо.

А если взять такую функцию (раскрутить цикл вручную)
Код
unsigned test(unsigned *dl, unsigned *suff, unsigned cnt)
{
    unsigned r;
    r = 0;
    do {
        unsigned d1,d2,d3,d4;
        unsigned s1,s2,s3,s4;

        d1 =  *(dl++);
        d2 =  *(dl++);
        d3 =  *(dl++);
        d4 =  *(dl++);

        s1 = *(suff++);
        s2 = *(suff++);
        s3 = *(suff++);
        s4 = *(suff++);

        r += s1*d1 + s2*d2 + s3*d3 + s4*d4;
    }while(cnt-=4);
    return r;
}

и взять компилер помощнее ( RVCT 4.0)
то получим такой asm
Код
; generated by ARM C/C++ Compiler, RVCT4.0 [Build 471]
; commandline armcc [-S -O3 -Otime test.c]
        ARM
        REQUIRE8
        PRESERVE8

        AREA ||.text||, CODE, READONLY, ALIGN=2

test PROC
        PUSH     {r4-r10}
        MOV      r3,#0
|L1.8|
        LDR      r12,[r0],#4
        LDM      r1!,{r7,r8,r10}
        LDM      r0!,{r4-r6}
        MUL      r12,r7,r12
        MUL      r5,r10,r5
        MLA      r12,r8,r4,r12
        LDR      r9,[r1],#4
        SUBS     r2,r2,#4
        MLA      r4,r9,r6,r5
        ADD      r12,r12,r4
        ADD      r3,r3,r12
        BNE      |L1.8|
        POP      {r4-r10}
        MOV      r0,r3
        BX       lr
        ENDP

так что умеют компиляторы и LDMIA использовать smile.gif

я конечно не утверждаю что надо без asm обходится! действительно многие вещи приходится писать на нем, но часто в силу того что на С не объснить компилеру некоторые ньюансы. Но не стоит недооценивать современные компиляторы.
Go to the top of the page
 
+Quote Post
kons
сообщение Mar 9 2009, 15:36
Сообщение #21


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

Группа: Свой
Сообщений: 106
Регистрация: 28-09-05
Пользователь №: 9 035



Да, хорошая штука RVCT. Мой IAR так не умеет - проверял. Однако такой код на c выходит длиннее ассемблерного. А для того, чтобы написать его и заценить понятливость компилятора, все равно надо знать asm...
Go to the top of the page
 
+Quote Post
KRS
сообщение Mar 9 2009, 16:22
Сообщение #22


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(kons @ Mar 9 2009, 18:36) *
А для того, чтобы написать его и заценить понятливость компилятора, все равно надо знать asm...

C этим не поспоришь!
Еще при этом можно узнать некоторые особенности компилятора, например если заменить строчку
Код
r += s1*d1 + s2*d2 + s3*d3 + s4*d4;

на
Код
        r += s1*d1;
        r += s2*d2;
        r += s3*d3;
        r += s4*d4;

то получим в RVCT слегка другой листинг
Код
        LDR      r12,[r0],#4
        LDM      r1!,{r7,r8,r10}
        MLA      r3,r7,r12,r3
        LDM      r0!,{r4-r6}
        MLA      r3,r8,r4,r3
        MLA      r3,r10,r5,r3
        LDR      r9,[r1],#4
        SUBS     r2,r2,#4
        MLA      r3,r9,r6,r3
        BNE      |L1.8|

тут видно что для RVCT подобные циклы лучше разворачивать на 3 операции ( 6 регистров он может выделить), а не на 4
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 23:52
Рейтинг@Mail.ru


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