Отговори на тема  [ 7 мнения ] 
GCC (ARM) инструкции на асемблер в C кода - как? 
Автор Съобщение
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пон Сеп 27, 2004 9:22 am
Мнения: 15501
Местоположение: София
Мнение GCC (ARM) инструкции на асемблер в C кода - как?
Как се вмъкват асемблерски инструкции в C код под GCC?

Трябва да нахакам едни микрозакъснения, т.е. за няколко NOP-a иде реч.

А пуста документация на GCC.... :(

_________________
"Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.


Сря Май 20, 2009 10:02 am
Профил ICQ
Ранг: Професионалист
Ранг: Професионалист
Аватар

Регистриран на: Сря Май 11, 2005 3:47 pm
Мнения: 534
Мнение Re: GCC (ARM) инструкции на асемблер в C кода - как?
Цецо написа:
Как се вмъкват асемблерски инструкции в C код под GCC?

Трябва да нахакам едни микрозакъснения, т.е. за няколко NOP-a иде реч.

А пуста документация на GCC.... :(


asm("NOP");


Сря Май 20, 2009 10:20 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пон Сеп 27, 2004 9:22 am
Мнения: 15501
Местоположение: София
Мнение 
Екстра.

А как да вкарам малко повече инструкции, с някой етикет/джъмп евентуално?

И къде въобще е документирано това? В GCC документацията не го откривам?

_________________
"Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.


Сря Май 20, 2009 10:33 am
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 6:52 pm
Мнения: 11266
Местоположение: Добрич
Мнение 
да asm()... но има доста подробности. Имаше документация, ама сега не ми се рови - ще го обясня с пример:

Цитат:
inline static __swi __arm void tsk_send_signal(volatile Task * task, unsigned int signal)
{
volatile register Task *_task asm("r0") = task;
volatile register unsigned int _signal asm("r1") = signal;

asm volatile ("swi %2"
: "=r" (_task), "=r"(_signal)
: "I" (usr_send_signal_swi), "0" (_task), "1"(_signal)
: "r2", "r3", "r12");
}


В случая това е функция дето съм я направил изцяло на асемблер щото GCC няма друг начин за поддръжка на SWI, както и да е асемблер може да се вгражда *навсялъде*...

Първо asm, после volatile за да не си прави шегички при оптимазия, после в кавички колкото на брой искаш асемблерски инструкции и накрая трите реда с ":", които имат следното значение:
Първия ред описва "изхода" на асемблера като променливи и/или регистри. Втория ред описва входните параметри, а третия ред описва обекти дето асемблера може и да омаже...

Ако параметъра е изходен трябва да започва с "=" след това с "r" ако е регистров, ако е типът е imidiate (константа) се описва с "I".
Всички парамтери получават номерца и после с тия номерца се ползват в асемблерския код. Примерно аз ползвам %2 в кода на SWI инструкцията - това е втори номер, т.е. usr_send_signal_swi

Една особеност - ако един параметър е едновременно входен и изходен, първо си се декларира като изходен, а после се изброява номера му. Така са ми _task и _signal - първо ги декларирам с "=r", т.е. като регистър който ще получи стойност, и после ги повтарям и като входни параметри само че без % - деректно номерчето като параметър.

Други особености:
* Пази се много от оптимизациите.... Избягвай да ползваш директно С-променливи, понеже в зависимост от оптимизацията компилатора може да ги разположи в стека или да ги направи регистрови. А в асемблера все пак трябва да знаеш дали е регистър или памет. Затова най-добре да си направиш собствени променливи дето знаеш какви са, както примерно:
Код:
volatile register Task *_task asm("r0") = task;

В случая имам Ц-променлива "task" и за да не завися от това каква е, си правя "копие" на променливата в регистрова и то точно определен регистър. Като volatile е задължителен ако не искаш да гониш духове...
Не се притеснявай за тези междинни присвоявания - компилатора не е толкова глупав и не прави излишен код. Просто ти му казваш да не пипа твойта версия и съптветно той оптимизира "оригинала".


Ето пък пример с повечко инструкции:

Цитат:
static unsigned int get_clocks_per200ms(void)
{
unsigned int res;

asm volatile (
"1: \n\t"
" mov %0, #0 \n\t"
" mov r1, r8 \n\t" //REG_MTASK
" mov r2, #200 \n\t"
" ldr r3, [r1, %1] \n\t"
"2: \n\t"
" add %0, %0, #8 \n\t"
" ldr r4, [r1, %1] \n\t"
" cmp r3, r4 \n\t"
" beq 2b \n\t"
" bhi 1b \n\t"

" add r3, r3, #1 \n\t"
" sub r2, r2, #1 \n\t"
" bne 2b \n\t"

: "=r"(res)
: "I" (tsk_time)
: "r1", "r2", "r3", "r4"
);
return res;
}


Това е код, който обаче няма входни параметри и затова не се налага защита от оптимизациите на компилатора...


Сря Май 20, 2009 10:55 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пон Сеп 27, 2004 9:22 am
Мнения: 15501
Местоположение: София
Мнение 
Благодарско.

Засега ми трябва съвсем праволинеен код, без предаване на параметри.

_________________
"Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.


Сря Май 20, 2009 11:10 am
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 6:52 pm
Мнения: 11266
Местоположение: Добрич
Мнение 
Всъщност малко поизлъгах с входните и изходните параметри...

Като му кажеш, че искаш да ползваш като параметър в регистър някаква променлива с "r"(foo) - компилатора се грижи да намери някой своден регистър и да ти качи стойността на тази променлива в този регистър. Същото е и при изхода, като му кажеш че изкарваш резултат, то ще ти го запише където трябва.

Проблемът в моя случай със SWI функциите е, че по разни причини искам да са static функция, а при static функциите GCC се прави на тарикат и заебава calling конвенцията, т.е. няма гаранция че функцията ще получава параметрите си точно с R0-R3 +стек. Може да си избере други регистри. Но от друга страна аз при SWI викам хендлъри и асемблерски код, който не е inline и ми трябва първия параметър да е в R0, втория в R1 и т.н. както си е по arm calling convention.
Та затова трябваше да минавам с тия междинни volatile register променливи...

Ако на асемблера не му пука кой параметър в кой регистър, май спокойно може да е простичко както във втория пример....


Сря Май 20, 2009 11:18 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Яну 26, 2005 2:01 pm
Мнения: 1952
Местоположение: Варна
Мнение 
http://www.ethernut.de/en/documents/arm-inline-asm.html

_________________
Най-опасният враг на истината и свободата е мнозинството.


Сря Май 20, 2009 4:42 pm
Профил
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 7 мнения ] 

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 0 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни