A dlaczego dla porównania nie napisałeś takiego samego migacza w asemblerze? Kod wynikowy będzie liczył pewnie kilkadziesiąt bajtów, kod źródłowy nie będzie raczej dłuższy ani bardziej skomplikowany niż w języku C. Porównuj lepiej długość kodu binarnego (po konwersji hex2bin) a nie pliku hex.
Wracając do tematu: sam kod wynikowy "właściwy" funkcji migającej w C ma kilkanaście bajtów, dodatkowo funkcja opóźniająca nieco dodaje. Reszta to biblioteka standardowa (głównie start programu w C). Można oczywiście pewnymi sztuczkami wyeliminować te dodatki, ale tylko w tym konkretnym przypadku.
Twoją funkcję sprawdziłem kompilując kod dla procesora ATmega128 kompilatorem avr-gcc 4.1.1 (WinAVR 20070122). No to po kolei:
1) używasz chyba starego kompilatora gcc, w nowej wersji nie ma już makr sbi ani cbi - zastąpiłem odpowiednimi sekwencjami |= i &=~
2) wynikowy plik binarny ma 228 bajtów (w Makefile'u nie dołączam bibliotek do printf'ów ani matematycznej - może to u Ciebie jest problemem?)
3) pierwsze 140 bajtów kodu wynikowego to wektory przerwań, tu można oszczędzić najwięcej nie korzystając ze standardowych plików startowych (opcja -nostartfiles) ale wtedy najczęściej musiałbyś zapewnić także własne funkcje: zerującą sekcję danych .bss (__do_clear_bss) i przepisującą sekcję .data (__do_copy_data) a wcześniej ustawić wskaźnik stosu i wyzerować r1
4) oczywiście dla mniejszych procesorów będzie mniej wektorów przerwań - program skompilowany dla np. ATtiny22 (wykorzystujący PORTB i DDRB bo nie ma portu D w tym procu) ma tylko 88 bajtów binariów
5) możesz zainicjować raz a dobrze rejestr DDR a potem tylko migać pinem portu - binaria schodzą do 86 bajtów
6) na koniec rozwiązanie totalne czyli wywalenie standardowego startupu (patrz pkt. 3) i niekorzystanie z biblioteki standardowej (opcja
-nostdlib) daje wynikowy plik binarny długości 28 bajtów.
Czy taka optymalizacja ma sens? Oczywiście nie ale to już inna sprawa.
Finalny kod źródłowy w C dający 28-bajtowy binarny plik wynikowy (do linkera dorzucone opcje -nostartfiles i -nostdlib):
Wiem, wiem ale nie napisałem dlatego, że niestety nie znam assemblera :(
Zdecydowaną poprawę wniosło ustawienie opcji -Os zaproponowanej przez kol. Krzysztof Kajstura oraz wyeliminowaniu zbędnych bibliotek.
Masz rację. Mam avr-gcc-3.4.1 Zabieram się do aktualizacji :)
Powiem tak, skompilowałem to "standardowo" jak leci w AVRStudio bez zastosowania wszelakich "optymizerów" kodu. Stąd wyszło jak wyszło. Do następnych kompilacji zastosuję się do porad Twoich jak i innych kolegów.
Dzięki Tobie i innym za fajną lekcję :)
Dopiero startuję z pisaniem w C na AVRy więc Twoje uwagi są dla mnie cenne. Jak by co to pozwolę sobie zamącić Wam w tym temacie głowę.
Nie udało mi się dogonić mistrza. Wpisując Twoje parametry udało mi się osiągnąć postęp który jest dość znaczny :)
349 bajtowy plik hex i 116 bajtowy bin
Gdybyś był uprzejmy przeglądnąć plik makefile byłbym Ci wdzięczny. Oto on:
############################################################################### # Makefile for the project Migacz ###############################################################################
## General Flags PROJECT = Migacz MCU = atmega8 TARGET = Migacz.elf CC = avr-gcc.exe
## Options common to compile, link and assembly rules COMMON = -mmcu=$(MCU)
## Compile options common for all C compilation units. CFLAGS = $(COMMON) CFLAGS += -Wall -gdwarf-2 -nostartfiles -nostdlib -DF_CPU=4000000UL
Pod pojęciem "finalny kod źródłowy" przytoczyłem poprawioną wersję kodu źródłowego załączonego przykładu programu w języku C, uwzględniającą ograniczenia wymuszane przez nowszą wersję kompilatora avr-gcc takie jak brak makr cbi i sbi. Poza tym w języku C często na kilka sposobów można zapisać sekwencję dającą ten sam binarny kod wynikowy - więc mój "finalny kod źródłowy" to tylko przykład poprawienia programu migającego diodą na jeden z wielu możliwych sposobów.
ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here.
All logos and trade names are the property of their respective owners.