да asm()... но има доста подробности. Имаше документация, ама сега не ми се рови - ще го обясня с пример:
В случая това е функция дето съм я направил изцяло на асемблер щото GCC няма друг начин за поддръжка на SWI, както и да е асемблер може да се вгражда *навсялъде*...
Първо asm, после volatile за да не си прави шегички при оптимазия, после в кавички колкото на брой искаш асемблерски инструкции и накрая трите реда с ":", които имат следното значение:
Първия ред описва "изхода" на асемблера като променливи и/или регистри. Втория ред описва входните параметри, а третия ред описва обекти дето асемблера може и да омаже...
Ако параметъра е изходен трябва да започва с "=" след това с "r" ако е регистров, ако е типът е imidiate (константа) се описва с "I".
Всички парамтери получават номерца и после с тия номерца се ползват в асемблерския код. Примерно аз ползвам %2 в кода на SWI инструкцията - това е втори номер, т.е. usr_send_signal_swi
Една особеност - ако един параметър е едновременно входен и изходен, първо си се декларира като изходен, а после се изброява номера му. Така са ми _task и _signal - първо ги декларирам с "=r", т.е. като регистър който ще получи стойност, и после ги повтарям и като входни параметри само че без % - деректно номерчето като параметър.
Други особености:
* Пази се много от оптимизациите.... Избягвай да ползваш директно С-променливи, понеже в зависимост от оптимизацията компилатора може да ги разположи в стека или да ги направи регистрови. А в асемблера все пак трябва да знаеш дали е регистър или памет. Затова най-добре да си направиш собствени променливи дето знаеш какви са, както примерно:
В случая имам Ц-променлива "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; }
|  |
 |  |  |
Това е код, който обаче няма входни параметри и затова не се налага защита от оптимизациите на компилатора...