logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[LPC2129][C]Rzutowanie typów, duża objętość kodu wynikowego

mklos1 22 Lis 2009 15:57 3071 9
REKLAMA
  • #1 7294426
    mklos1
    Poziom 25  
    Posty: 717
    Pomógł: 68
    Ocena: 121
    Witam!

    W kodzie mam taką konstrukcję:

    zmienna_uint = (zmienna_uint * 10) + (uint)zmienna_float;

    gdzie uint oznacza zmienną typu unsigned int. Ta linia po skompilowaniu zajmuje 1800 B. Kompilator ustawiony jest na optymalizację -Os oraz mcu ma ustawiony tryb thumb. Nie ważne czy zrobię rzutowanie jawne czy niejawne, kod z tą linią zajmuje praktycznie tyle samo. Powodem jest fraza "+ (uint)zmienna_float", gdyż po jej wyrzuceniu kod jest mniejszy o wielkość, którą przytoczyłem wcześniej. Kompilator GCC (toolchain CodeSourcery). Czy rzutowanie ze z float na int może aż tyle zajmować?
  • REKLAMA
  • #2 7295714
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Może, bo do takiej konwersji wywoływana jest funkcja która zapewne będzie się nazywać f2u() albo f2i() - zobacz sam w plikach .map albo w listingu jaka jest jej objętość.

    4\/3!!
  • REKLAMA
  • #3 7297246
    mklos1
    Poziom 25  
    Posty: 717
    Pomógł: 68
    Ocena: 121
    Znalazłem w listingu skok rozkazem BL do funkcji f2uiz. Jedyne co mnie jeszcze frapuje, to rozmiar w pliku MAP, który wynosi 0x54, więc jakoś mi się to nie kalkuluje z efektami kompilacji.
  • #4 7297373
    markosik20
    Poziom 33  
    Posty: 2261
    Pomógł: 208
    Ocena: 147
    Ja u siebie zauważyłem że kompilator z włączoną optymalizacją nie zachowuje się liniowo tzn. piszę dodatkowe funkcje a wielkość generowanego pliku proporcjonalnie wzrasta. Czasami jest tak że po dopisaniu paru linijek wielkość pliku .bin maleje, czasami przez "długi czas" utrzymuje się na podobnym poziomie a czasami wystarczy jedna prosta linijka i wielkość pliku gwałtownie rośnie.
  • #5 7297572
    mieczotronix
    Poziom 16  
    Posty: 163
    Pomógł: 12
    Ocena: 4
    0x54 to tylko 84 bajty, czyli kilkanaście instrukcji, tyle co nic. Na bank ten f2uiz wywołuje ze środka coś jeszcze i pewnie to się linkuje.
  • REKLAMA
  • #6 7298553
    mklos1
    Poziom 25  
    Posty: 717
    Pomógł: 68
    Ocena: 121
    Wniosek chyba jest taki, że przejdę na liczby o stałym przecinku i float'y sobie daruję.

    Co do liniowości kompilatora, to zauważyłem podobne zjawisko jak bawiłem się ATmega8 i WinAVR.
  • REKLAMA
  • #8 7299332
    mklos1
    Poziom 25  
    Posty: 717
    Pomógł: 68
    Ocena: 121
    Tak, bo docelowy uC ma 16kB (lub 32kB) flashu, a mam dopiero "zarys" funkcjonalny tego co będzie robić. 256kB mam na płytce ewaluacyjnej. Nie to, żeby mnie te 1,8kB jakoś bardzo przerażało nawet przy 16kB, ale chciałem wiedzieć skąd ono się bierze, żeby ewentualnie potem mieć z czego uszczknąć.

    Dodano po 5 [godziny] 10 [minuty]:

    Mam jeszcze jeden problem, który zauważyłem. Opcja: -Wl,--gc-sections nie działa prawidłowo. Gdy pojawi się ona jako opcja linkera, plik *.hex staje się pusty (prawie pusty, jest tylko coś takiego :00000001FF). Zauważyłem to, gdy testowałem funkcję. Po jej wykomentowaniu z main'a rozmiar kodu wynikowego się nie zmienił. Miałem błąd w opcji linkera (źle wpisałem --gc-sections). Teraz chyba jest dobrze, ale dzieje się właśnie to to napisałem powyżej.

    Makefile:
    # Automatic makefile for GNUARM (C/C++)
    
    #tutaj wpisz nazwe pliku hex
    TARGET	   = AWS_InterfaceTest
    
    #Format wyjsciowy (moze byc srec,ihex,binary)
    FORMAT	= ihex
    
    #Optymalizacja [0,1,2,3,s]
    # 0 - brak optymalizacji, s -optymalizacja rozmiaru
    OPT 	= s
    
    #Debug format 
    #DEBUG = stabs
    #DEBUG = dwarf-2
    DEBUG = 
    
    
    #Typ procesora
    MCU	= arm7tdmi
    
    #Skrypt linkera
    SCRIPTLINK = LPC2129-ROM
    
    #Opcje kompilatora C
    CFLAGS += -Wall
    CFLAGS += -std=gnu99
    
    #Opcje kompilatora C++
    CXXFLAGS += -Wall
    
    
    
    #Port szeregowy programatora ISP
    ISPPORT = com1
    
    #Predkosc portu szeregowego programatora
    ISPBAUD = 19200
    
    #Czestotliwosc rezonatora kwarcowego mikrokontrolera (kHz)
    ISPXTAL = 12000
    
    #Definicje programow
    CC      = arm-none-eabi-gcc
    CXX	= arm-none-eabi-g++
    AR      = arm-none-eabi-ar
    CP      = arm-none-eabi-objcopy
    OBJDUMP = arm-none-eabi-objdump
    SIZE    = arm-none-eabi-size 
    ISPPROG  = lpc21isp
    
    
    #Pozostale ustawienia kompilatora
    
    ASFLAGS += -Wa,-mapcs-32 -mcpu=$(MCU) -g$(DEBUG) 
    LDFLAGS +=  -nostartfiles -T$(SCRIPTLINK).ld -Wl,-Map=$(TARGET).map,--cref,--gc-sections -mthumb-interwork 
    CFLAGS  += -O$(OPT) -mcpu=$(MCU) -g$(DEBUG) -ffunction-sections -fdata-sections -mthumb-interwork -mthumb 
    CXXFLAGS += -O$(OPT) -mcpu=$(MCU) -g$(DEBUG) 
    CPFLAGS =  -O $(FORMAT) -S 
    ASLST = -Wa,-adhlns=$(<:.S=.lst)
    CLST = -Wa,-adhlns=$(<:.c=.lst)
    CPPLST = -Wa,-adhlns=$(<:.cpp=.lst)
    
    all:	clean build
    
    install: build program
    
    clean:
    	rm -f $(TARGET).hex
    	rm -f $(TARGET).elf
    	rm -f $(TARGET).map
    	rm -f $(TARGET).lss
    	rm -f $(OBJ)
    	rm -f $(ASRC:.S=.lst) $(SRC:.c=.lst) $(CPPSRC:.cpp=.lst)
    	rm -f $(SRC:.c=.dep) $(CPPSRC:.cpp=.dep) $(ASRC:.S=.dep)
    
    program:
    	$(ISPPROG) -control $(TARGET).hex $(ISPPORT) $(ISPBAUD) $(ISPXTAL)
    
         
    build:	$(TARGET).elf $(TARGET).hex $(TARGET).lss
    
    
    
    #pliki zrodlowe C
    SRC = $(wildcard *.c)
    #pliki zrodlowe C++
    CPPSRC = $(wildcard *.cpp)
    #pliki assemblerowe
    ASRC = $(wildcard *.S) 
    
    
    #wszystkie zaleznosci
    $(TARGET).elf: $(OBJ) $(SCRIPTLINK).ld
    -include $(SRC:.c=.dep)
    -include $(CPPSRC:.cpp=.dep)
    -include $(ASRC:.S=.dep)
    
     
    #Objects files
    OBJ = $(SRC:.c=.o) $(CPPSRC:.cpp=.o) $(ASRC:.S=.o)
    # Define all listing files.
    LST = $(SRC:.c=.lst) $(CPPSRC:.cpp=.lst) $(ASRC:.S=.lst)
    
    
    %.dep: %.c
    	$(CC) -M $(CFLAGS) $< > $@.$$$$; \
    	sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
    	rm -f $@.$$$$
    
    %.dep: %.cpp 
    	$(CXX) -M $(CXXFLAGS) $< > $@.$$$$; \
    	sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
    	rm -f $@.$$$$
    
    %.dep: %.S
    	$(CC) -M $(ASFLAGS) $< > $@.$$$$; \
    	sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
    	rm -f $@.$$$$
    
    %.lss: %.elf
    	@echo "Create extended listing..."
    	$(OBJDUMP) -h -S $< > $@ 
    	#$(SIZE) -d -A $(TARGET).elf 
    	$(SIZE) -d $(TARGET).hex 
    
    %.hex: %.elf
    	@echo "Converting to hex..."
    	$(CP) $(CPFLAGS) $< $@ 
    
    
    %.elf: $(OBJ)
    	@echo "Linking..."
    	$(CXX) $(CXXFLAGS) $(OBJ) -o $@ $(LDFLAGS)
    
    %.o : %.S
    	@echo "Assembling..."
    	$(CC) -c $(ASFLAGS) $(ASLST) $< -o $@ 
    
    
    %.o : %.c	
    	@echo "Compiling C..."
    	$(CC) -c $(CFLAGS) $(CLST) $< -o $@
    
    %.o : %.cpp
    	@echo "Compiling C++..."
    	$(CXX) -c $(CXXFLAGS) $(CPPLST) $< -o $@
    
    


    Fragment skryptu linkera dotyczący kodu:

     /* Sekcja .text zawiera kod programu */
      . = 0;	
      .text :
      {
        *boot.o (.text)         /* Startup code */
        *(.text)                /*   remaining code */
        *(.text.*) 
        *(.glue_7t) 
        *(.glue_7)
        *(.gnu.linkonce.t.*)
        *(.gcc_except_table)
      } >CODE
    
      . = ALIGN(4);
  • #9 7301622
    Konto nie istnieje
    Konto nie istnieje  
  • #10 7301662
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Ja myślę, że w skrypcie linkera nie masz nigdzie dyrektywy ENTRY(), która jako parametr zawiera nazwę funkcji wywoływanej po resecie (handler resetu). Bez tego w istocie kompilator stwierdza, że cały program jest zbędny.

    Zerknij tutaj - https://www.elektroda.pl/rtvforum/topic1339518.html - i popatrz jak jest zrobiony skrypt linkera. Z nim naprawdę nie warto experymentować zbytnio, bo nie ma to sensu - wystarczy jeden dobry i gotowe.

    4\/3!!

Podsumowanie tematu

✨ W dyskusji poruszono problem związany z dużą objętością kodu wynikowego generowanego przez kompilator GCC dla konstrukcji rzutowania zmiennej typu float na unsigned int. Użytkownik zauważył, że linia kodu zajmuje 1800 B, co jest znaczną wartością, zwłaszcza przy ustawieniach optymalizacji -Os i trybie thumb. Odpowiedzi wskazują, że konwersja ta może wywoływać dodatkowe funkcje, takie jak f2u() lub f2uiz, co wpływa na rozmiar kodu. Użytkownik rozważa przejście na liczby o stałym przecinku, aby zredukować objętość kodu. Dodatkowo, poruszono problem z opcją linkera --gc-sections, która może prowadzić do pustego pliku wynikowego, co może być spowodowane brakiem odpowiednich dyrektyw w skrypcie linkera.
Podsumowanie wygenerowane przez AI na podstawie treści dyskusji.
REKLAMA