(12-04-2012 10:29)JaHo napisał(a): (PS. Mocno bym się zdziwił gdyby się okazało że kompilator C CodeVision stosuje znacząco inne "calling conventions", bo te używane przez avr gcc wydają się być bardzo sensowne i dobrze dopasowane do małych procków z niewielką ilością RAM.)
Kolego, JaHo lubię dyskutować ale na argumenty a nie o tym co mi się wydaję. Programuję zarówno w assemblerze jak i C na AVR z łączeniem obu języków w obie strony. Zawsze sprawdzam wygenerowany kod asm przez kompilator, jeśli jest zły to robię wstawkę w assemblerze. Proponuję zainstalować sobie demo CodeVision i na własne oczy zobaczyć jak jest zorganizowany stos danych oraz przekazywanie parametrów do funkcji.
Nigdy nie twierdziłem, że wszystkie kompilatory mają odrębny stos danych, wyraźnie podkreśliłem, że tak jest w tym którego używam czyli CodeVision.
W kompilatorze GCC dla AVR jest tak jak napisał powyżej kol. JaHo, parametry do funkcji przekazywane są poprzez rejestry co ilustruje podgląd kodu w assemblerze przykładowej funkcji.
Kod:
@0000007A: main
19: Oblicz_FTW(20000000,400000000); //oblicz FTW dla f_vfo=20MHz
+0000007A: E060 LDI R22,0x00 Load immediate
+0000007B: E27D LDI R23,0x2D Load immediate
+0000007C: E381 LDI R24,0x31 Load immediate
+0000007D: E091 LDI R25,0x01 Load immediate
+0000007E: E020 LDI R18,0x00 Load immediate
+0000007F: E834 LDI R19,0x84 Load immediate
+00000080: ED47 LDI R20,0xD7 Load immediate
+00000081: E157 LDI R21,0x17 Load immediate
+00000082: 940E0049 CALL 0x00000049 Call subroutine
20: }
+00000084: 9508 RET Subroutine return
W Code Vision te same parametry wejściowe typu long int są kładzione na stosie danych wg. wskaźnika [YH:YL] poprzez dwukrotne wywołanie procedury PUTPARD1, podgląd w assemblerze:
Kod:
_main:
;0000 0013 Oblicz_FTW(20000000,400000000); //oblicz FTW dla f_vfo=20MHz
__GETD1N 0x1312D00
CALL __PUTPARD1
__GETD1N 0x17D78400
CALL __PUTPARD1
RCALL _Oblicz_FTW
;0000 0014 }
__PUTPARD1:
ST -Y,R23
ST -Y,R22
ST -Y,R31
ST -Y,R30
RET
Język GCC powstał dużo wcześniej na inne procesory a po pojawieniu się rodziny AVR został przystosowany do tych procesorów. Moim zdanie metoda przekazywania danych zastosowana w GCC jest gorsza, mniej przejrzysta i blokuje dostęp do rejestrów. Mieszanie adresów powrotu z danymi wejściowymi na jednym stosie utrudnia dostęp do danych w kodzie funkcji. To między innymi przyczyna gorszych wyników w teście porównawczym obu kompilatorów gdzie GCC był wolniejszy i generował większy kod. Nie chcę nikogo zniechęcać do GCC ani przekonywać do CodeVision bo to sprawa indywidualnych preferencji.
Warto odnotować odmienne podejście do tematu stosu w różnych kompilatorach i od czasu do czasu sprawdzić jaki to ma wpływ na jakość generowanego kodu. Ta dyskusja powinna toczyć się w innym wątku.