Jakie są zalety / wady używania C w stosunku do złożenia? [Zamknięte]


15

Obecnie studiuję inżynierię w telekomunikacji i elektronice i przeprowadziliśmy migrację z asemblera do C w programowaniu mikroprocesorowym. Mam wątpliwości, czy to dobry pomysł. Jakie są zalety i wady C w porównaniu do montażu?

Widzę zalety / wady:

Zalety:

  • Mogę powiedzieć, że składnia C jest o wiele łatwiejsza do nauczenia się niż składnia asemblera.
  • C jest łatwiejszy w użyciu do tworzenia bardziej złożonych programów.
  • Nauka języka C jest w jakiś sposób bardziej produktywna niż nauka asemblera, ponieważ wokół C jest więcej rzeczy do rozwijania niż asembler.

Niedogodności:

  • Asembler jest językiem programowania niższego poziomu niż C, dzięki czemu nadaje się do programowania bezpośrednio na sprzęcie.
  • Jest o wiele bardziej elastyczny, nawiązując do pracy z pamięcią, przerwaniami, mikro-rejestrami itp.

17
Uhm ... witamy w nowym wieku. Spodoba ci się tutaj. Mamy mikrokontrolery z systemem .NET , Java , Linux , a nawet ludzie używający Pythona do programowania PIC .
ZJR

@ZJR Jak używasz Pythona do programowania PIC? Który obrazek?
detly

2
@detly To nie jest pełnoprawny python, tylko podzbiór rdzenia. Warstwa składni Pythona nad funkcjonalnością kontrolera , jeśli chcesz. pyastra jest pierwszym przykładem, w którym wycofałem się z Google'a , ale przypominam sobie, że przeczytałem dokumentację innego, która również zrobiła ATMEL.
ZJR

4
Szczerze mówiąc, przy złożoności współczesnych procesorów byłbym zaskoczony, gdyby wielu programistów napisało mocniejszy, wydajniejszy asembler, niż i tak mógłby wygenerować nowoczesny kompilator C. Nie chciałbym na przykład programować procesora architektury EPIC w asemblerze - Mel byłby w domu z Itanium . * 8 ')
Mark Booth

5
@ZJR Ten nowy wiek brzmi ekscytująco! Jestem jednak ciekawy, w jakim języku napisano środowisko uruchomieniowe .NET, Java VM i Linux dla tych mikrokontrolerów? Jak w jakim języku zostało wykonane rzeczywiste programowanie mikrokontrolera? Och ... C lub asembler również w tym wieku ...

Odpowiedzi:


17

Oto kilka odpowiedzi na przepełnienie stosu, które mogą ci pomóc (są to najlepsze odpowiedzi, zaakceptowane odpowiedzi):

Zalety

/programming/143561/is-there-a-need-to-use-assembly-these-days (tylko dla użytkowników 10 000) lub Archiwum

  • Montaż jest wykorzystywany na najwcześniejszych etapach programu ładującego. Gdy procesor włącza się na stosie, nie jest dostępny, a kompilator C nie może próbować zapisywać rzeczy na stosie. Większość bootloadera jest jednak zapisywana w języku C, po najwcześniejszej inicjalizacji.
  • Asemblacja służy do pisania operacji blokujących muteks. Zasadniczo niemożliwe jest uzyskanie kompilatora C do emitowania instrukcji bariery pamięci w wymaganych miejscach.
  • Procedury takie jak memset () lub memcpy () są często wykonywane w asemblerze. Na przykład napisałem memset () z dużą rozwiniętą pętlą, która dynamicznie oblicza adres rozgałęzienia, aby przeskoczyć do środka tej pętli w celu wykonania ostatniej iteracji. Procedura AC wygenerowałaby więcej kodów, przyjmując dodatkowe błędy I $. Podobnie, zestawy instrukcji procesora często zawierają obciążenie linii pamięci podręcznej lub inne instrukcje, które mogą radykalnie przyspieszyć memcpy (), których kompilator C nie wykorzysta.

Niedogodności

/programming/2684364/why-arent-programs-written-in-assembly-more-often

  • ASM ma słabą czytelność i nie jest tak naprawdę łatwy do utrzymania w porównaniu z językami wyższego poziomu.
  • Ponadto jest o wiele mniej programistów ASM niż w przypadku innych bardziej popularnych języków, takich jak C.
  • Ponadto, jeśli używasz języka wyższego poziomu i stają się dostępne nowe instrukcje ASM (na przykład SSE), wystarczy zaktualizować kompilator, a stary kod może łatwo korzystać z nowych instrukcji.

Przykład

Ostatni post poniżej jest przepełnieniem stosu opisującym scenariusz, który pokaże przykład złożenia, który jest szybszy niż C (podczas wykonywania tej samej funkcji).

/programming/577554/when-is-assembler-faster-than-c


20
  • C jest łatwiejszy do zaprogramowania niż w asemblerze. Istnieją oczywiste powody, dla których nie warto przerabiać.

  • Będąc łatwiejszym w użyciu, C pozwala szybciej pisać programy. Zasadniczo programy te są również łatwiejsze do debugowania i łatwiejsze w utrzymaniu. Ponadto łatwiej jest zarządzać dużymi, złożonymi programami w C.

  • Często kod generowany przez kompilator jest równie dobry (pod względem szybkości i wydajności) jak asembler napisany ręcznie - jeśli nie lepszy.

  • C jest dość cholernie niski i rzadko zdarza się, że chcesz zejść znacznie niżej. Posiadanie dodatkowej warstwy abstrakcji rzadko jest złą rzeczą.

  • Kiedy musisz zejść niżej, możesz użyć Asemblera, w przeciwnym razie możesz użyć C.

  • Możesz napisać Asembler w kodzie C, ale nie C w kodzie Asemblera.


6
Powiedziałbym, że czasami zobaczysz, że kod maszynowy zoptymalizowany pod kątem kompilatora C jest lepszy niż Twój ręcznie napisany kod asemblera
użytkownik

@crucified - było to już powszechne (i zwykle uzasadnione) roszczenie w połowie lub pod koniec lat 90. Kompilator stosuje optymalizacje w sposób niezawodny i systematyczny - nie tylko wtedy, gdy zauważy taką możliwość.
Steve314,

15

Program AC można skompilować do różnych architektur mikroprocesorów.


4

przeprowadziliśmy migrację z asemblera do C w programowaniu mikroprocesorowym. Mam wątpliwości, czy to dobry pomysł

Nie obawiaj się, nikt już nie tworzy nowych programów w 100% asemblerze. W dzisiejszych czasach C może być używany nawet w najmniejszych, najbardziej cholernych architekturach 8-bitowych. Jednak znajomość jakiegoś asemblera sprawia, że ​​jesteś znacznie lepszym programistą C. Ponadto w programie zawsze są jakieś małe lub dwa detale, które należy napisać w asemblerze.

Mogę powiedzieć, że składnia C jest o wiele łatwiejsza do nauczenia się niż składnia asemblera.

Tak, z pewnością składnia jest łatwiejsza. Jednak nauka całego języka C ze wszystkimi irytującymi szczegółami jest o wiele bardziej złożona niż nauka wszystkich szczegółów konkretnego asemblera. C to znacznie większy i szerszy język. Ale z drugiej strony może nie być konieczne poznanie wszystkich szczegółów.

C jest łatwiejszy w użyciu do tworzenia bardziej złożonych programów.

Rzeczywiście, C zapewnia mechanizmy modułowego projektowania programów, takie jak enkapsulacja i lokalne zakresy / zmienne lokalne. A C ma standardową bibliotekę oraz ogromną ilość zasobów napisanych w ciągu ostatnich 30 lat. A co najważniejsze, C jest przenośny.

Nauka języka C jest w jakiś sposób bardziej produktywna niż nauka asemblera, ponieważ wokół C jest więcej rzeczy do rozwijania niż asembler.

C ma wiele gotowych funkcji, bibliotek i zasobów, więc będzie mniej ponownego wymyślania koła. Ale poza tym twoje stwierdzenie jest subiektywne. Uważam, że jest to kwestia osobistych preferencji.

Na przykład jestem doświadczonym programistą C, od czasu do czasu programując w C ++. Uważam, że jestem znacznie mniej produktywny w C ++, ponieważ nie znam tego języka tak dobrze, jak znam C. Ale tylko dlatego, że tak uważam, niekoniecznie oznacza to, że programowanie w C jest bardziej produktywne niż programowanie w C ++. Doświadczony programista C ++ z pewnością miałby przeciwną opinię.

Istnieje wiele aspektów „produktywności”. Bardzo ważnym aspektem jest czas konserwacji, a zwłaszcza czas potrzebny na usunięcie błędów wywołanych przez konserwację. C jest znacznie łatwiejszy w utrzymaniu niż asembler.

Asembler jest językiem programowania niższego poziomu niż C, dzięki czemu nadaje się do programowania bezpośrednio na sprzęcie.

Programowanie sprzętowe można wykonać bezpośrednio w dowolnym języku. Jedyne, czego nie możesz zrobić w C, to dostęp do wskaźników stosu i rejestrów stanu itp. Samego rdzenia procesora. Więc jeśli przez programowanie sprzętowe masz na myśli rozmowę z własnym procesorem, to tak, asembler pozwala nieco więcej niż C. Jeśli masz na myśli dostęp do zewnętrznego sprzętu, to asembler nie ma przewagi nad C. Ale być może wady, ponieważ często trudniej jest pisać ogólny kod asemblera dla konkretnego urządzenia zewnętrznego, niż ogólny kod C.

Jest o wiele bardziej elastyczny, nawiązując do pracy z pamięcią, przerwaniami, mikro-rejestrami itp.

To nie jest poprawne. C pozwala ci to wszystko zrobić, chociaż być może będziesz musiał polegać na kodzie C specyficznym dla kompilatora, takim jak słowo kluczowe interrupt.


Na koniec musisz znać oba języki, aby programować MCU, z naciskiem na C.


W jaki sposób cały język C jest bardziej złożony niż niektóre bardziej tajemne języki maszynowe? Po zrobieniu obu, myślę, że C bez bibliotek jest znacznie mniej złożony. Jeśli masz na myśli C Standard Library, potrzebujesz czegoś takiego w asemblerze, aby zrobić coś pożytecznego. C może być większym i szerszym językiem, ale nie musisz znać go z tym samym poziomem szczegółowości. a = b[i] + c;jest o wiele mniej skomplikowane niż instrukcje ładowania b[i](które wymaga obliczeń) i crejestrów (które muszą być dostępne), dodawania i przechowywania.
David Thornley,

1
@DavidThornley Im więcej dowiadujesz się o C, tym bardziej zdajesz sobie sprawę z jego złożoności. Czy znasz wszystkie setki przypadków zachowań nieokreślonych / nieokreślonych / zdefiniowanych? Czy znasz szczegółowo wszystkie zasady promocji typu domyślnego (promocje na liczby całkowite, zwykłe konwersje arytmetyczne)? Wszystkie szczególne reguły i składnia dotyczące specyfikatorów typów? Wszystkie różne formy statycznych / dynamicznych tablic wielowymiarowych, w tym wskaźniki tablicy (nie mylić ze wskaźnikami do 1. elementu tablicy) Wszystkie cechy C99 i C11? I tak dalej.

1
@Lundin: Najważniejsze w C jest to, że możesz zadać wszystkie te pytania i znaleźć konkretne odpowiedzi. Kompilatory zgodne ze standardem są wymagane do udokumentowania, jak zachowują się w przypadku zachowań zdefiniowanych w implementacji 62 (a nie „setki”). Prostota asemblera sprawia, że ​​jest to propozycja na lunch, która z kolei odciąża złożoność języka C od własnego kodu. Mógłbym odeprzeć twój argument, pytając, ile bibliotek zmiennoprzecinkowych zostało napisanych w asemblerze dla dowolnej architektury i dlaczego ich zachowanie jest zdefiniowane w implementacji.
Blrfl

1
@Lundin: 62 to liczba zachowań zdefiniowanych przez kompilator wymienionych w sekcji 4 podręcznika GCC. Pozostawienie tego, co zdefiniowano w bibliotece, powoduje porównanie jabłek z jabłkami, ponieważ nie ma standardowej biblioteki do składania. Wymóg udokumentowania jest pierwszym zdaniem §J.3. GCC i garść komercyjnych kompilatorów, które kupiłem lub używałem od C89, został ratyfikowany (Intel, Sun, IBM, Portland Group) dokument, więc „większość”, która nie przeszkadza, nie może nazywać się zgodną. Mówiąc o standardach, jak działa dla Ciebie zestawienie x86 napisane ze składnią Intela na asemblerze ze składnią AT&T?
Blrfl

1
@Lundin: Mój samochód jest świetny, dzięki. Kierownica, pedał przyspieszenia, hamulec, sprzęgło i kierunkowskazy znajdują się w standardowych miejscach, mają standardowe zachowanie, a pozostałe elementy sterujące są wyraźnie oznaczone symbolami ISO. Wszystkie zdefiniowane w implementacji rzeczy, takie jak system rozrywki, HVAC, nawigacja, tempomat itp. Są udokumentowane w grubej książce w schowku. Montaż jest jak mój Plymouth z 1973 roku: nie było tego wiele, ale w surowej formie nie było tak blisko, jak to, czym teraz jeżdżę. Montaż jest taki sam; złożoność wynika z tego, co do niej dodajesz.
Blrfl,

1

W zależności od tego, jak osadzone musisz przejść, C będzie produkować duże, wolne programy. Co znacznie zwiększy koszt tej części produktu. Może to być kropla w oceanie dla całego produktu lub radykalnie zmienić produkt. Tak, niektórzy mogą powiedzieć, że wysiłki związane z tworzeniem oprogramowania i konserwacją są tańsze, co może być prawdą lub fałszem, jeśli jest ono głęboko osadzone i dąży do części o tak małej mocy, małej i niedrogiej, że nie mówimy o dużej ilości kodu. Ten kod jest głównie specyficzny dla tego dostawcy lub tego konkretnego układu, więc będąc w C nie ma żadnych korzyści w zakresie przenoszenia, musisz przepisać przed każdym celem. Dzięki serii cortex-m firmy ARM dopiero teraz zaczynamy być w stanie konkurować z C asmem, nie dlatego, że ludzie nie używali C lub innych języków wyższego poziomu w swoich wbudowanych produktach,

Debata C vs ASM, profesjonalnie, zawsze sprowadza się do napisania jej w C i użycia ASM tam, gdzie można to uzasadnić. I możesz to uzasadnić. W świecie osadzonym występuje wydajność i rozmiar.

Musisz uwzględnić cel w tej dyskusji. Chociaż wiele osób używało C z Microchipem (starsze zdjęcia, nie pic32, który jest mips) za ogromną cenę, jest to straszny zestaw instrukcji dla kompilatorów, bardzo edukacyjny i interesujący zestaw instrukcji, ale kompilator nieprzyjazny. msp430, avr, arm, thumb, mips, wszystko dobre dla kompilatorów. 8051 też źle.

Nawet więcej niż język narzędzi. Zwłaszcza w przypadkach, gdy kłopoty związane z tworzeniem kodu i zarządzaniem są argumentem, potrzebujesz narzędzi, aby być tam dziś i jutro. Posiadanie narzędzia z pojedynczym źródłem, w tym nawet jednego mod gcc, zarządzanego przez jedną grupę, jest ryzykowne z perspektywy biznesowej. Prawdopodobnie znajdziesz więcej niż jednego asemblera, a każdy godny bycia w tym zespole może podnieść asemblera w weekend (o ile zestaw, który piszesz, nie jest zgodny z dyrektywą ghee i jest szczęśliwy makro). Zarówno w przypadku asm, jak i C chciałbyś użyć narzędzi open source (lub własnych narzędzi domowych), gdzie masz większą szansę, nawet jeśli oznacza to użycie maszyny wirtualnej do uruchomienia 10-letniej dystrybucji Linuksa, posiadania narzędzi dostępnych dla żywotność produktu.

Podsumowując, ponownie użyj / naucz / naucz zarówno C, jak i asm, zacznij od C i użyj asm tam, gdzie możesz to uzasadnić.


Te argumenty wydają mi się staromodne. Jeśli używasz nowoczesnego kompilatora, który został napisany w ciągu ostatnich 10 lat, to uważam, że trudno ci będzie napisać program asemblera, który jest znacznie bardziej efektywny niż program C. Chyba że używasz 30-letniej architektury dinozaurów, takiej jak PIC lub 8051, będziesz mieć wolny program bez względu na to, co robisz ...

Naprawdę trywialne jest naprawianie powolnego montażu generowanego przez najnowocześniejsze gcc i lvvm. Gcc 4.x produkuje wolniejszy, mniej wydajny kod niż seria 3.x (dla niektórych celów, przynajmniej tych, które oceniłem, na przykład ARM). Myślę, że ważne jest, aby rozproszyć pogląd, że kompilator radzi sobie lepiej niż ludzie, ponieważ tak nie jest. I nawet gdy to robi, robi to tylko wtedy, gdy człowiek wie, co robi. „poznaj swoje narzędzia”, jeśli chcesz ich skutecznie używać. Zacznij od C i w razie potrzeby użyj ASM, jeśli możesz to uzasadnić ...
old_timer

Ponieważ gcc jest oprogramowaniem typu open source, jest dziwną bestią. Może ten konkretny port jest źle wykonany. Wszystkie optymalizacje kodu muszą być wykonane dla konkretnej platformy, co nie jest łatwym zadaniem. Bardziej sprawiedliwe byłoby porównanie wydajności ręcznego asemblera z komercyjnym kompilatorem dla tej platformy.

gcc jest wielozadaniowy, więc wykonuje całkiem dobrą robotę, ale nie jest świetną robotą dla żadnego konkretnego celu. I tego się oczekuje. ale twój punkt widzenia na temat nowoczesnego kompilatora, ostatnich 10 lat itp. Po prostu nie ma znaczenia, kompilatory nie są coraz lepsze, jeśli chodzi o produkowany kod, są coraz lepsze, jeśli chodzi o języki, cele i funkcje kosztem wytworzonego kodu. Przekonanie, że jakikolwiek nowoczesny kompilator umożliwia najlepszy możliwy kod, jest po prostu fałszywe. Bardzo prawdą jest, że średnio jest DUŻO lepszy niż ręcznie kodowany asembler, ciężko jest zrobić jakikolwiek projekt o przyzwoitych rozmiarach w asm lepszy niż C
old_timer

dlatego większość ludzi mówi, że używaj C, dopóki nie pojawi się problem, a następnie napraw go ręcznie w asm, jeśli możesz to uzasadnić. czy naprawdę potrzebujesz tego niewielkiego przyrostu wydajności, czy naprawdę tam, gdzie jest twój problem z wydajnością, czy chcesz zachować ten kod z asmem, czy będziesz nadal sprawdzał każdy przyszły kompilator, aby sprawdzić, czy jego wyjście naprawia lub zmniejsza twój problem do akceptowalnego poziomu itp.
old_timer

1

W przypadku montażu istnieje nieunikniony kompromis między utrzymywalnością kodu a wydajnością. Możesz napisać łatwy do odczytu / konserwacji zestaw lub możesz napisać wysoce zoptymalizowany kod; ale nie możesz zrobić obu.

W przypadku C kompromis nie całkiem znika, ale jest znacznie mniej zauważalny - możesz napisać łatwe do odczytania / utrzymania C, które jest dość dobrze zoptymalizowane.

Doskonały programista w asemblerze będzie w stanie przezwyciężyć kompilator prawie cały czas, ale przez większość czasu celowo zdecyduje się na napisanie łatwego do odczytania / utrzymania kodu; dlatego też znakomity programista w asemblerze będzie przez większość czasu bity przez kompilator.

Sprytnym sposobem jest użycie zarówno asemblera, jak i C (zamiast tylko asemblera lub tylko C) - np. Użyj C do części kodu, w których znakomity programista w asemblerze wybrałby pisanie kodu możliwego do utrzymania / powolnego i użycie asemblera do reszta (gdzie „wysoce zoptymalizowany i trudny w utrzymaniu” jest faktycznie uzasadniony).


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.