|
ARM Ассемблер, программирование-искусство? |
|
|
|
Mar 5 2009, 10:21
|
Группа: Участник
Сообщений: 9
Регистрация: 22-02-09
Пользователь №: 45 211

|
Читал heyrick.co.uk, автор - апологет принципа "код - произведение искусства"  Например, в одну инструкцию: 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 Честно говоря, не понял принципа работы второго примера. Кто-нибудь может прояснить?
|
|
|
|
|
Mar 5 2009, 10:55
|
Гуру
     
Группа: Свой
Сообщений: 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, автор - апологет принципа "код - произведение искусства"  Этот принцип для досужей потехи хорош, а для профессиональной деятельности крайне вреден. Если так ковыряться в инструкциях, то времени на работу не останется :-)
|
|
|
|
|
Mar 5 2009, 11:04
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(KRS @ Mar 5 2009, 13:59)  Современный ARM компилер трудно обогнать используя ассемблер, Это уж точно плюс пицот! Дык не все верят в очевидное  Цитата особенно при работе с константами - сидеть и вычислять чего куда сдвинуть и счем проксорить... (особенно если вы используете текстовое имя константы, а компилер то знает ее значение...) А вот это, простите, не понял. Писанины больше получается - это факт, и выражений всяких поболее надо.
|
|
|
|
|
Mar 5 2009, 11:19
|

Профессионал
    
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
Mar 5 2009, 11:23
|
Группа: Участник
Сообщений: 9
Регистрация: 22-02-09
Пользователь №: 45 211

|
Цитата(_Pasha @ Mar 5 2009, 12:49)  .swihandler ADDCC PC, PC, R11, LSL #2; и выполнили переход Где-то так. Сорри, форматтер кода - полный боян, такшта несколько нечитабельно Спасибо, действительно все прозрачно
|
|
|
|
|
Mar 5 2009, 11:32
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(KRS @ Mar 5 2009, 14:19)  Так вот в силу специфики команд ARM не все контсатны можно оптимально загрузить в регистр Да это понятно, обычно Peripheral-Specific макросы в помощь. Правда, я не особо широкого кругозора - дальше GNU AS не интересовался макросредствами для армов, но не сомневаюсь, что у всяких там кейлов с этим все в порядке Цитата(Tarkus @ Mar 5 2009, 14:23)  Спасибо Пожалуйста
|
|
|
|
|
Mar 8 2009, 07:00
|
Частый гость
 
Группа: Свой
Сообщений: 106
Регистрация: 28-09-05
Пользователь №: 9 035

|
Цитата Этот принцип для досужей потехи хорош, а для профессиональной деятельности крайне вреден. Если так ковыряться в инструкциях, то времени на работу не останется :-) Немного не так. Если неохота ковыряться в инструкциях, надо пользоваться C. Например, обсуждаемая здесь инициализация периферии - уж точно не задача для asm. На таких задачах (как и на большинстве прочих), как верно отметил KRS, Цитата Современный ARM компилер трудно обогнать используя ассемблер А вот написать какой-нибудь внутренний короткий цикл на asm (фильтр какой-нибудь или демодулятор) - это часто очень даже имеет смысл. И тут уж все средства хороши. Но (по опыту) максимальный эффект в asm-модуле достигается не жонглированияем битами, а оптимизацией доступа к памяти - использованием вместо кучи LDR/STR одной LDMIA/STMIA. Компилятор так не умеет (ну, кроме входа/выхода в процедуру есс-но). Для ядра ARM7TDMI на задачах типа свертки результат подобного подхода очень даже радует.
|
|
|
|
|
Mar 8 2009, 13:53
|
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 на задачах типа свертки результат подобного подхода очень даже радует. Грамотный ответ. Оптимизировать инициализацию переферии - оч глупо. Она выполняется один раз. Оптимизировать цикл (на асм, по сравнению с С) думаю можно практически всегда, особенно если он написан на С человеком, который ассемблера в жизни не видел.
|
|
|
|
|
Mar 9 2009, 12:55
|
Частый гость
 
Группа: Свой
Сообщений: 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, и особенно на этапе выбора процессора.
|
|
|
|
|
Mar 9 2009, 13:37
|
self made
   
Группа: Свой
Сообщений: 855
Регистрация: 7-03-09
Из: Toronto, Canada
Пользователь №: 45 795

|
Цитата(MALLOY2 @ Mar 9 2009, 07:40)  расчет CRC32, ЦФ, свертка, FFT, практически все матиметические циклы будут на асме работать быстрее! Вопрос вы будите писать их на асм или возьмете мощнее процессор ? Мощнее процессор решение тупое но часто приемлимое. Иногда, к счастью нет -- иначе бы Visual Basic и в embedded programming пробрался бы  Когда стоит задача добиться минимального потребления тока оптимизация на асм. очень помогает, ибо каждая лишняя инструкця цикла это сколько-то лишних nA. (При условии что программа в основном спит, и изредка включается чтобы обработать данные).
|
|
|
|
|
Mar 9 2009, 14:28
|

Профессионал
    
Группа: Модераторы
Сообщений: 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 использовать  я конечно не утверждаю что надо без asm обходится! действительно многие вещи приходится писать на нем, но часто в силу того что на С не объснить компилеру некоторые ньюансы. Но не стоит недооценивать современные компиляторы.
|
|
|
|
|
Mar 9 2009, 16: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
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|