Skocz do zawartości

[C] Przyśpieszanie, optymalizacja kodu. Wstawki asemblerowe w c.


Pomocna odpowiedź

No trudno, ale żeby na przyszłość nikt nie bał się wstawek asemblerowych małe wyjaśnienie.

Po pierwsze przykłady trzeba przepisywać dokładnie:

"brne 1"           "\n\t" 

Ta linijka nie zadziała, brakuje wspomnianego wcześniej b:

"brne 1b   \n\t"

Teraz można spróbować "odtworzyć" oryginalny przykład z książki (książki nie mam, więc zgaduję).

Po pierwsze opóźnienie było stałą, więc tak napiszmy:

void s_del(uint8_t cnt)
{
 uint8_t tmp; 
 asm volatile( 
   "ldi %0, [ticks]"  "\n" 
   "1: dec %0"        "\n\t" 
   "brne 1b"           "\n\t" 
   :"=d" (tmp) 
   : [ticks] "M" (5));
} 

Parametr cnt nie jest używany, stała to po prostu 5 - ale chodzi o sprawdzenie koncepcji - program się kompiluje poprawnie, a o to chodziło.

Zmiana to wyrzucenie % przed [ticks], dzięki temu ldi ma sens, bo jak już wiemy można go używać tylko dla stałych. Oczywiście nie możemy zamiast 5 wstawić cnt - stała musi być stała.

Spróbujmy więc pomyśleć co należałoby zmienić, żeby program używał zmiennej cnt.

Pierwsza sprawa to ldi zamieniamy na mov. Dodajemy też %, który poprzednio skasowaliśmy:

mov %0, %[ticks] \n\t 

Teraz problemem jest ograniczenie "M". Pasowało do stałej, ale dla zmiennej musimy użyć innego. Parametr cnt przekazywany jest w rejestrze, więc zamiast "M" użyjemy np. "a".

Program wygląda więc tak:

void s_del(uint8_t cnt)
{
 uint8_t tmp; 
 asm volatile( 
   "mov %0, %[ticks] \n\t" 
   "1: dec %0"        "\n\t" 
   "brne 1b"           "\n\t" 
   :"=d" (tmp) 
   : [ticks] "a" (cnt));
}

Wstawki asemblerowe to bardzo wygodne narzędzie, chociaż raczej do zaawansowanych zastosowań. Jeśli nie umiemy pisać w asemblerze, lepiej zostawić to kompilatorowi. A do nauki łatwiej użyć "czystego" asemblera, bez mieszania z C.

Dopiero jak opanujemy asembler oraz porządnie C, warto opanować wstawki.

To jeszcze tyle, że gdyby w najnowszej formie "handmade by Elvis" pozwolić kompilatorowi na większą swobodę i zamiast a użyć np. d to na 100% (zgaduję z głowy) zostałby użyty jako %0 rejestr r24 i dostalibyśmy mov r24,r24 co jest masłem maślanym i spokojnie można by tę instrukcję usunąć. Oczywiście pod warunkiem, że nie używamy tego count/ticks gdzieś dalej. Ale w końcu jest to funkcja opóźniająca więc im więcej instrukcji i czasu wykonania tym lepiej 🙂

Ja wcale nie twierdzę, że moja wersja jest optymalna, nawet nie wiem czy działa. Piszę wstawki na ARM-ach, z AVR mam teraz mało do czynienia - chciałem tylko pokazać, że to nie czarna magia, ani plamy na słońcu są winne że program się nie kompilował.

A do zabawy we wstawki asemblerowe najpierw trzeba dobrze poznać platformę. No i dużo, bardzo dużo testować - przy okazji poznając procesor jeszcze lepiej.

I o to właśnie chodziło. Dzięki Elvis - jesteś najlepszy! Mam teraz solidny punkt wyjścia bez nadmiaru domniemania a do całej reszty z czasem dojdę.

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...