Dlaczego programujesz w asemblerze? [Zamknięte]

86

Mam pytanie do wszystkich zagorzałych hakerów niskiego poziomu. Natknąłem się na to zdanie na blogu. Nie sądzę, żeby źródło miało znaczenie (jeśli naprawdę cię to obchodzi, to Haack), ponieważ wydaje się, że jest to powszechne stwierdzenie.

Na przykład wiele współczesnych gier trójwymiarowych ma swój silnik rdzeniowy o wysokiej wydajności napisany w C ++ i asemblerze.

Jeśli chodzi o asemblację - czy kod jest napisany w asemblerze, ponieważ nie chcesz, aby kompilator emitował dodatkowe instrukcje lub używał nadmiernych bajtów, lub czy używasz lepszych algorytmów, których nie możesz wyrazić w C (lub nie możesz wyrazić bez kompilator zastanawia się nad nimi)?

Całkowicie rozumiem, że ważne jest zrozumienie rzeczy niskiego poziomu. Chcę tylko zrozumieć, dlaczego program w asemblerze to zrozumiesz.

Tom Ritter
źródło
1
Myślę, że podobne pytania już tam są ...
Mehrdad Afshari
8
Eeeeehh ... technicznie to inne pytanie. Te pytania to oba po co uczyć się asemblera, to po co programować w nim, który .. myślę, że jest inny…?
cgp
4
Dlaczego programujesz w asemblerze? - Spójrzmy na kilka NIEMOŻLIWYCH odpowiedzi na te pytania: 1) Aby mój kod był
łatwy w
9
bezpieczeństwo pracy ........
San Jacinto
3
bo jest fajnie .. :)
RainingComputers

Odpowiedzi:

169

Myślę, że źle czytasz to stwierdzenie:

Na przykład wiele współczesnych gier trójwymiarowych ma swój silnik rdzeniowy o wysokiej wydajności napisany w C ++ i asemblerze.

Gry (i większość programów w dzisiejszych czasach) nie są „napisane w asemblerze” w ten sam sposób, w jaki są „napisane w C ++”. Ten blog nie mówi, że znaczna część gry jest projektowana w asemblerze lub że zespół programistów siedzi i rozwija się w asemblerze jako podstawowym języku.

To naprawdę oznacza, że ​​programiści najpierw piszą grę i uruchamiają ją w C ++. Następnie profilują to, ustalają, jakie są wąskie gardła i jeśli to jest warte zachodu, optymalizują je w montażu. Lub, jeśli mają już doświadczenie, wiedzą, które części będą wąskimi gardłami, i mają zoptymalizowane elementy z innych gier, które stworzyli.

Punkt programowania w montażu jest taka sama jak zawsze była: prędkość . Byłoby absurdem pisać dużo kodu w asemblerze, ale są pewne optymalizacje, których kompilator nie jest świadomy, a dla wystarczająco małego okna kodu człowiek poradzi sobie lepiej.

Na przykład kompilatory zmiennoprzecinkowe wydają się być dość konserwatywne i mogą nie być świadome niektórych bardziej zaawansowanych funkcji Twojej architektury. Jeśli jesteś skłonny zaakceptować jakiś błąd, zwykle możesz zrobić lepiej niż kompilator i warto napisać ten mały fragment kodu w asemblerze, jeśli okaże się, że poświęca się na to dużo czasu.

Oto kilka bardziej odpowiednich przykładów:

Przykłady z gier

  • Artykuł Intela na temat optymalizacji silnika gry przy użyciu elementów wbudowanych SSE. Ostateczny kod używa elementów wewnętrznych (nie wbudowanego asemblera), więc ilość czystego asemblacji jest bardzo mała. Ale patrzą na wyjście asemblera przez kompilator, aby dowiedzieć się, co dokładnie zoptymalizować.

  • Szybka odwrotność pierwiastka kwadratowego Quake'a . Ponownie, procedura nie zawiera asemblera, ale musisz wiedzieć coś o architekturze, aby wykonać tego rodzaju optymalizację. Autorzy wiedzą, które operacje są szybkie (mnożenie, przesuwanie), a które wolne (dzielenie, sqrt). Dlatego wymyślają bardzo skomplikowaną implementację pierwiastka kwadratowego, która pozwala całkowicie uniknąć powolnych operacji.

Obliczenia o wysokiej wydajności

  • Poza domeną gier ludzie zajmujący się komputerami naukowymi często optymalizują bzdury, aby szybko działały na najnowszym sprzęcie. Pomyśl o tym jak o grach, w których nie możesz oszukiwać w fizyce.

    Świetnym, niedawnym przykładem tego jest kratowa chromodynamika kwantowa (krata QCD) . Dokument ten opisuje, w jaki sposób problem praktycznie sprowadza się do jednej bardzo małej obliczeniowej jądra, które zostało zoptymalizowane dla PowerPC 440 ciężko jest na z IBM Blue Gene / L . Każdy 440 ma dwa FPU i obsługują one specjalne operacje trójskładnikowe, które są trudne do wykorzystania przez kompilatory. Bez tych optymalizacji Lattice QCD działałby znacznie wolniej, co jest kosztowne, gdy problem wymaga milionów godzin pracy procesora na drogich maszynach.

    Jeśli zastanawiasz się, dlaczego jest to ważne, przeczytaj artykuł w Science, który powstał w wyniku tej pracy. Używając Lattice QCD, ci faceci obliczyli masę protonu na podstawie pierwszych zasad i wykazali w zeszłym roku, że 90% masy pochodzi z energii wiązania siły silnej, a reszta z kwarków. To jest E = mc 2 w akcji. Oto podsumowanie .

W przypadku wszystkich powyższych, aplikacje nie są projektowane ani pisane w 100% w montażu - nawet nie są bliskie. Ale kiedy ludzie naprawdę potrzebują szybkości, skupiają się na pisaniu kluczowych części swojego kodu, aby latać na określonym sprzęcie.

Todd Gamblin
źródło
12
niesamowita odpowiedź. Chciałbym, żebyśmy umieścili to na wiki!
bdd
6
@Paperino ... możesz. Pytania i odpowiedzi na StackOverflow są licencjonowanym autorstwa Creative Commons.
Aaron Maenpaa
Aby uzyskać więcej informacji na temat zrozumienia asm, aby pomóc Ci pisać lepsze C / C ++, zobacz Dlaczego ten kod C ++ jest szybszy niż mój odręczny zestaw do testowania hipotezy Collatza? . Moja odpowiedź wskazuje, że czytanie danych wyjściowych kompilatora w formacie asm i modyfikowanie źródła może pomóc, gdy kompilator nie zauważa użytecznej optymalizacji. Więc myślisz (a właściwie) piszesz w asm, a potem trzymasz kompilator w ręku, aby robić, co chcesz, ale teraz masz przenośne C.
Peter Cordes
42

Od wielu lat nie kodowałem w asemblerze, ale mogę podać kilka powodów, które często widziałem:

  • Nie wszystkie kompilatory mogą korzystać z pewnych optymalizacji procesora i zestawu instrukcji (np. Nowych zestawów instrukcji, które Intel dodaje od czasu do czasu). Czekanie, aż autorzy kompilatorów nadrobią zaległości, oznacza utratę przewagi konkurencyjnej.

  • Łatwiejsze dopasowanie rzeczywistego kodu do znanej architektury procesora i optymalizacji. Na przykład rzeczy, które wiesz o mechanizmie pobierania, buforowaniu itp. Ma to być przezroczyste dla programisty, ale faktem jest, że tak nie jest, dlatego twórcy kompilatorów mogą optymalizować.

  • Pewne dostępy na poziomie sprzętu są możliwe / praktyczne tylko poprzez język asemblera (np. Podczas pisania sterownika urządzenia).

  • Formalne rozumowanie jest czasem łatwiejsze w asemblerze niż w języku wysokiego poziomu, ponieważ wiesz już, jaki jest ostateczny lub prawie ostateczny układ kodu.

  • Programowanie niektórych kart graficznych 3D (około późnych lat 90. XX wieku) przy braku API było często bardziej praktyczne i wydajne w języku asemblerowym, a czasami nie było możliwe w innych językach. Ale znowu, dotyczyło to gier na poziomie eksperckim opartych na architekturze akceleratora, takich jak ręczne przenoszenie i usuwanie danych w określonej kolejności.

Wątpię, aby wiele osób użyło asemblera, gdy zrobiłby to język wyższego poziomu, zwłaszcza gdy tym językiem jest C. Ręczna optymalizacja dużych ilości kodu ogólnego przeznaczenia jest niepraktyczna.

Uri
źródło
19

Jest jeden aspekt programowania w asemblerze, o którym inni nie wspominali - poczucie satysfakcji, które odczuwasz, wiedząc, że każdy bajt w aplikacji jest wynikiem twojego własnego wysiłku, a nie kompilatora. Nie chciałbym nawet przez sekundę wracać do pisania całych aplikacji w asemblerze, jak to robiłem na początku lat 80., ale czasami tęsknię za tym uczuciem ...


źródło
3
Heh, to wynik pracy asemblera! Zwykle piszesz dużo makr w asm.
Mehrdad Afshari
5
Nie tylko satysfakcja, ale docenienie precyzji. Zwięzły proces, w którym wszystko zostało zadeklarowane, jest przyjemnością.
deau
18

Zwykle asemblacja laika jest wolniejsza niż C (ze względu na optymalizację C), ale wiele gier ( doskonale pamiętam Doom ) musiało mieć określone sekcje gry w asemblerze, aby działała płynnie na normalnych maszynach.

Oto przykład, do którego się odwołuję.

Ólafur Waage
źródło
2
+1 Bardzo prawdziwe. Ludzie bardzo źle piszą długi kod ASM.
Martwe konto
Należy pamiętać, że wspomniane narzędzia nie zawsze były dostępne w momencie pisania asemblera.
Marco van de Voort
16

Programowanie w języku asemblerowym zacząłem w mojej pierwszej pracy (lata 80-te). W przypadku systemów wbudowanych wymagania dotyczące pamięci - RAM i EPROM - były niskie. Możesz napisać zwarty kod, który byłby łatwy w użyciu zasobów.

Pod koniec lat 80-tych przerzuciłem się na C. Kod był łatwiejszy do pisania, debugowania i utrzymania. Bardzo małe fragmenty kodu zostały napisane w asemblerze - dla mnie było to, gdy pisałem przełączanie kontekstu w systemie RTOS typu roll-your-own. (Coś, czego nie powinieneś już robić, chyba że jest to „projekt naukowy”).

W kodzie jądra Linuksa zobaczysz fragmenty kodu asemblera. Ostatnio przeglądałem go w spinlockach i innym kodzie synchronizacyjnym. Te fragmenty kodu muszą uzyskać dostęp do atomowych operacji testowania i ustawiania, manipulowania pamięciami podręcznymi itp.

Myślę, że byłoby trudno zoptymalizować nowoczesne kompilatory C dla większości programów.

Zgadzam się z @altCognito, że prawdopodobnie lepiej spędzić czas na dokładniejszym myśleniu o problemie i lepszym wykonywaniu zadań. Z jakiegoś powodu programiści często koncentrują się na mikroefektywnościach i zaniedbują makroefektywności. Asembler poprawiający wydajność to mikroefektywność. Cofnięcie się do szerszego widoku systemu może ujawnić problemy z makrami w systemie. Rozwiązanie problemów makro często może przynieść lepszy wzrost wydajności. Gdy problemy makro zostaną rozwiązane, zejdź do poziomu mikro.

Wydaje mi się, że mikro problemy są pod kontrolą jednego programisty iw mniejszej domenie. Zmiana zachowania na poziomie makro wymaga komunikacji z większą liczbą osób - czego niektórzy programiści unikają. Cały ten kowboj kontra drużyna.

DanM
źródło
10

"Tak". Ale zrozum, że w większości przypadków korzyści płynące z pisania kodu w asemblerze nie są warte wysiłku. Zwrot uzyskany za napisanie tego w trakcie montażu jest zwykle mniejszy niż zwykłe skupienie się na dokładniejszym myśleniu o problemie i spędzaniu czasu na myśleniu o lepszym sposobie wykonywania zadań.

John Carmack i Michael Abrash, którzy byli w dużej mierze odpowiedzialni za napisanie Quake'a i cały kod o wysokiej wydajności, który znalazł się w silnikach gier ID, opisują szczegółowo tę książkę w tej książce .

Zgodziłbym się również z Ólafurem Waage'em, że dziś kompilatory są dość sprytne i często wykorzystują wiele technik, które wykorzystują ukryte ulepszenia architektoniczne.

cgp
źródło
9

W dzisiejszych czasach, przynajmniej w przypadku kodów sekwencyjnych, przyzwoity kompilator prawie zawsze pokonuje nawet bardzo doświadczonego programistę asemblerowego. Ale w przypadku kodów wektorowych to inna historia. Na przykład szeroko rozpowszechnione kompilatory nie wykonują tak świetnej pracy, wykorzystując możliwości równoległości wektorów jednostki x86 SSE. Jestem autorem kompilatorów, a wykorzystanie SSE znajduje się na szczycie mojej listy powodów, dla których warto iść na własną rękę, zamiast ufać kompilatorowi.

Norman Ramsey
źródło
W takim przypadku użyłbym wewnętrznego kompilatora.
Mehrdad Afshari
Wciąż nie to samo. To jak kompilator bez optymalizatora rejestrów
Marco van de Voort
To zależy od tego, jakie przyprawy ma twój programista asm. Jeśli przeczytałeś i przeczytałeś agner.org/optimize, aby dowiedzieć się o mikroarchitekturze, do której się dostosowujesz, pokonanie kompilatora tylko dla krótkich sekwencji jest często łatwe . Co najmniej przez połowę czasu widzę pominięte drobne optymalizacje, patrząc na dane wyjściowe kompilatora dla małych funkcji. Tam, gdzie kompilatory są świetne, jest optymalizacja w dużych bazach kodu z wbudowaną i stałą propagacją.
Peter Cordes
8

Kod SSE działa lepiej w asemblerze niż elementy wewnętrzne kompilatora, przynajmniej w MSVC. (tj. nie tworzy dodatkowych kopii danych)

Macke
źródło
Słuszna uwaga, potrzebujesz kompilatora, który wykonuje dobrą robotę z elementami wewnętrznymi. Kompilatory Intela i Gnu są całkiem dobre, nie wiem, czy najnowsze z PGI i PathScale są jeszcze konkurencyjne, kiedyś nie były.
Jed
6

Mam trzy lub cztery procedury asemblera (w źródle około 20 MB) w moich źródłach w pracy. Wszystkie z nich są SSE (2) i są związane z operacjami na (dość dużych - pomyśl o 2400x2048 i większych) obrazach.

Hobby pracuję nad kompilatorem i tam masz więcej asemblera. Biblioteki środowiska wykonawczego są dość często pełne, większość z nich ma do czynienia z rzeczami, które są sprzeczne z normalnym reżimem proceduralnym (jak pomocnicy wyjątków itp.)

Nie mam żadnego asemblera do mojego mikrokontrolera. Większość współczesnych mikrokontrolerów ma tak wiele urządzeń peryferyjnych (liczniki sterowane przerwaniami, nawet całe kwadraturowe enkodery i szeregowe bloki konstrukcyjne), że używanie asemblera do optymalizacji pętli często nie jest już potrzebne. Przy obecnych cenach flash to samo dotyczy pamięci kodów. Istnieje również wiele różnych urządzeń zgodnych ze stykami, więc skalowanie w górę, jeśli systematycznie kończy się moc procesora lub przestrzeń flash, często nie stanowi problemu

Chyba że naprawdę wysyłasz 100000 urządzeń, a asembler programowania umożliwia naprawdę duże oszczędności, po prostu umieszczając chip flash o kategorii mniejszej. Ale ja nie jestem w tej kategorii.

Wiele osób uważa, że ​​systemy wbudowane są usprawiedliwieniem dla asemblera, ale ich kontrolery mają większą moc procesora niż maszyny, na których opracowano system Unix . (Microchip dostarczany z mikrokontrolerami 40 i 60 MIPS za mniej niż 10 USD ).

Jednak wiele osób utknęło w spuściźnie, ponieważ zmiana architektury mikroczipa nie jest łatwa. Również kod HLL jest bardzo zależny od architektury (ponieważ wykorzystuje peryferia sprzętowe, rejestry do sterowania I / O itp.). Czasami są więc dobre powody, aby nadal utrzymywać projekt w asemblerze (miałem szczęście, że mogłem skonfigurować sprawy na nowej architekturze od zera). Ale często ludzie oszukują samych siebie, że naprawdę potrzebują asemblera.

Nadal podoba mi się odpowiedź, jakiej udzielił profesor, gdy zapytaliśmy, czy możemy użyć GOTO (ale możesz to przeczytać również jako MONTAŻ): „jeśli uważasz, że warto napisać 3-stronicowy esej o tym, dlaczego potrzebujesz tej funkcji, możesz jej użyć . Prześlij esej z wynikami ”.

Użyłem tego jako przewodniej zasady dla funkcji niskiego poziomu. Nie bądź zbyt ciasny, aby go używać, ale upewnij się, że odpowiednio go motywujesz. Podnieś nawet sztuczną barierę lub dwie (jak w eseju), aby uniknąć zawiłego rozumowania jako uzasadnienia.

Marco van de Voort
źródło
1
Podoba mi się test pisemny; Może będę potrzebować tego częściej;)
ex nihilo
5

Niektórych instrukcji / flag / kontrolek po prostu nie ma na poziomie C.

Na przykład sprawdzanie przepełnienia na x86 jest prostą flagą przepełnienia. Ta opcja nie jest dostępna w C.

Nieznany
źródło
Możesz obliczyć flagi przepełnienia w C za pomocą operacji bitowych.
swegi
@swegi: Założę się, że to nieznacznie wolniejsze.
Brian
jak często jest to przydatne? a kiedy tak jest, nie może być jedynym powodem, dla którego warto porzucić asemblera.
5

Defekty pojawiają się zazwyczaj w każdym wierszu (instrukcja, punkt kodowy itp.); Chociaż prawdą jest, że w przypadku większości problemów asembler używałby znacznie więcej linii niż języki wyższego poziomu, czasami zdarzają się przypadki, w których najlepiej (najbardziej zwięzłe, najmniej wierszy) jest odwzorowanie danego problemu. Większość z tych przypadków dotyczy zwykłych podejrzanych, takich jak sterowniki i bicie bitów w systemach wbudowanych.

Po prostu zakochany
źródło
3

Innym powodem może być sytuacja, w której dostępny kompilator nie jest wystarczająco dobry dla danej architektury, a ilość kodu potrzebnego w programie nie jest tak długa ani skomplikowana, aby programista mógł się w nim zgubić. Spróbuj zaprogramować mikrokontroler dla systemu wbudowanego, zwykle montaż będzie znacznie łatwiejszy.

alkar
źródło
3

Oprócz innych wymienionych rzeczy, wszystkie wyższe języki mają pewne ograniczenia. Dlatego niektórzy decydują się na programowanie w ASM, aby mieć pełną kontrolę nad swoim kodem.

Inni cieszą się bardzo małymi plikami wykonywalnymi, w zakresie 20-60KB, na przykład sprawdź HiEditor , który jest zaimplementowany przez autora kontrolki HiEdit, znakomitą, potężną kontrolę edycji dla Windows z podświetlaniem składni i zakładkami tylko ~ 50kb). W swojej kolekcji mam ponad 20 takich złotych kontrolek, od Excell jak ssheets po rendery html.

majkinetor
źródło
3

Myślę, że wielu twórców gier byłoby zaskoczonych tą odrobiną informacji.

Większość znanych mi gier używa możliwie najmniej asemblacji. W niektórych przypadkach w ogóle, aw najgorszym przypadku jedna lub dwie pętle lub funkcje.

Ten cytat jest zbyt uogólniony i nie jest tak prawdziwy, jak dziesięć lat temu.

Ale hej, same fakty nie powinny przeszkadzać prawdziwej krucjacie hakera na rzecz zgromadzeń. ;)

jalf
źródło
3

Jeśli programujesz low-endowy 8-bitowy mikrokontroler ze 128 bajtami pamięci RAM i 4K pamięci programu, nie masz dużego wyboru, jeśli chodzi o użycie asemblera. Czasami jednak, gdy używasz mocniejszego mikrokontrolera, potrzebujesz określonej akcji, która ma zostać wykonana w określonym czasie. Przydaje się wtedy język asemblera, ponieważ możesz liczyć instrukcje i mierzyć cykle zegara używane przez kod.

IanW
źródło
2

Gdybyś był w pobliżu wszystkich wysiłków naprawczych Y2K, mógłbyś zarobić dużo pieniędzy, gdybyś znał Assembly. Wciąż istnieje wiele starszego kodu, który został w nim napisany, a ten kod czasami wymaga konserwacji.

DOK
źródło
2

Poza bardzo małymi projektami na bardzo małych procesorach, nie zamierzałbym kiedykolwiek programować całego projektu w asemblerze. Jednak często zdarza się, że wąskie gardło wydajności można złagodzić dzięki strategicznemu kodowaniu ręcznemu niektórych wewnętrznych pętli.

W niektórych przypadkach wszystko, co jest naprawdę potrzebne, to zastąpić jakąś konstrukcję językową instrukcją, której nie można oczekiwać od optymalizatora, aby dowiedzieć się, jak go użyć. Typowym przykładem są aplikacje DSP, w których operacje wektorowe i operacje wielokrotnej akumulacji są trudne do wykrycia dla optymalizatora, ale kod jest łatwy w obsłudze.

Na przykład niektóre modele SH4 zawierają macierz 4x4 i 4 instrukcje wektorowe. Widziałem ogromną poprawę wydajności algorytmu korekcji kolorów poprzez zastąpienie równoważnych operacji C na macierzy 3x3 odpowiednimi instrukcjami, niewielkim kosztem powiększenia macierzy korekcji do 4x4, aby dopasować się do założenia sprzętowego. Osiągnięto to, pisząc nie więcej niż tuzin linii montażowych i przenosząc dopasowania dopasowanych do powiązanych typów danych i pamięci w kilku miejscach w otaczającym kodzie C.

RBerteig
źródło
2

Wydaje się, że nie ma o tym wzmianki, więc pomyślałem, że dodam to: w tworzeniu nowoczesnych gier myślę, że przynajmniej część tworzonego zestawu w ogóle nie jest przeznaczona dla procesora. To jest dla GPU w postaci programów shaderowych .

Może to być potrzebne z różnych powodów, czasami po prostu dlatego, że jakikolwiek używany język cieniowania wyższego poziomu nie pozwala na wyrażenie dokładnej operacji w dokładnej liczbie żądanych instrukcji, w celu dopasowania do pewnego ograniczenia rozmiaru, szybkości lub dowolnej kombinacji . Wydaje mi się, że tak jak zwykle w przypadku programowania w języku asemblerowym.

rozwijać
źródło
2

Prawie każdy średni i duży silnik lub biblioteka gier, które widziałem do tej pory, ma kilka ręcznie zoptymalizowanych wersji montażu dostępnych dla operacji na macierzach, takich jak łączenie macierzy 4x4. Wydaje się, że kompilatory nieuchronnie pomijają niektóre sprytne optymalizacje (ponowne wykorzystanie rejestrów, rozwijanie pętli w maksymalnie efektywny sposób, wykorzystanie instrukcji specyficznych dla maszyny itp.) Podczas pracy z dużymi macierzami. Te funkcje manipulacji macierzą są prawie zawsze „aktywnymi punktami” w profilu.

Widziałem również ręcznie kodowany zestaw używany często do niestandardowej wysyłki - rzeczy takie jak FastDelegate, ale specyficzne dla kompilatora i maszyny.

Wreszcie, jeśli masz procedury obsługi przerwań, asm może zrobić wielką różnicę na świecie - są pewne operacje, których po prostu nie chcesz, aby były wykonywane w trakcie przerwania, i chcesz, aby programy obsługi przerwań „wchodziły i wychodziły szybko”. .. prawie dokładnie wiesz , co się stanie w twoim ISR, jeśli jest w asm, i zachęca cię to do skracania cholernych rzeczy (co i tak jest dobrą praktyką).

leander
źródło
2

Gry są dość wymagające wydajności i chociaż w międzyczasie optymalizatory są całkiem niezłe, „główny programista” wciąż jest w stanie wycisnąć trochę więcej wydajności, ręcznie kodując odpowiednie części podczas montażu.

Nigdy, przenigdy nie rozpoczynaj optymalizacji programu bez uprzedniego jego sprofilowania. Po profilowaniu powinieneś być w stanie zidentyfikować wąskie gardła, a jeśli znalezienie lepszych algorytmów i tym podobnych, już ich nie usunie, możesz spróbować ręcznie zakodować coś w asemblerze.

robert.berger
źródło
2

Osobiście rozmawiałem tylko z jednym deweloperem o jego zastosowaniu w montażu. Pracował nad oprogramowaniem, które zajmowało się sterowaniem przenośnego odtwarzacza mp3. Wykonywanie prac montażowych miało 2 cele:

  1. Szybkość: opóźnienia musiały być minimalne.
  2. Koszt: ponieważ kod jest minimalny, sprzęt potrzebny do jego uruchomienia może być nieco mniej wydajny. Przy masowej produkcji milionów jednostek może to się sumować.
Paul Williams
źródło
2

Jedyne kodowanie asemblera, które nadal robię, dotyczy wbudowanego sprzętu z niewielkimi zasobami. Jak wspomina Leander, assembler nadal dobrze pasuje do ISR gdzie kod musi być szybki i dobrze zrozumiany.

Drugim powodem jest dla mnie utrzymanie mojej wiedzy na temat montażu. Możliwość zbadania i zrozumienia kroków, które podejmuje procesor, aby wykonać moje rozkazy, jest po prostu przyjemna.

ParoXoN
źródło
2

Ostatni raz, kiedy pisałem w asemblerze, nie mogłem przekonać kompilatora do generowania wolnego od libc, niezależnego od pozycji kodu.

Następnym razem prawdopodobnie będzie z tego samego powodu.

Oczywiście miałem inne powody .

Joshua
źródło
2

Wiele osób uwielbia oczerniać język asemblera, ponieważ nigdy nie nauczyli się go kodować i napotkali go tylko niejasno, a to wprawiło ich w przerażenie lub nieco onieśmielenie. Prawdziwie utalentowani programiści zrozumieją, że walenie w C lub Assembly jest bezsensowne, ponieważ są komplementarne. w rzeczywistości zaletą jednego jest wada drugiego. Zorganizowane reguły składniowe języka C poprawiają klarowność, ale jednocześnie rezygnują z wszelkich reguł strukturalnych, jakie zgromadzenie mocy ma! Instrukcje kodu C mają na celu utworzenie kodu nieblokującego, który można argumentować, wymusza przejrzystość intencji programowania, ale jest to utrata mocy. W C kompilator nie pozwoli na skok do wnętrza if / elseif / else / end. Lub nie możesz napisać dwóch pętli for / end na różnych zmiennych, które nakładają się na siebie, nie możesz pisać samomodyfikującego się kodu (lub nie możesz w łatwy sposób) itp. konwencjonalni programiści są wystraszeni powyższym i nie mieliby pojęcia, jak wykorzystać moc tych podejść, ponieważ zostały one wychowane zgodnie z konwencjonalnymi zasadami . Oto prawda: dziś mamy maszynę o mocy obliczeniowej, która może zrobić znacznie więcej niż aplikacja, do której ich używamy, ale ludzki mózg jest zbyt niezdolny do kodowania ich w środowisku kodowania wolnym od reguł (= montaż) i potrzebuje restrykcyjnych reguł, które bardzo zmniejszyć widmo i upraszcza kodowanie. Sam napisałem kod, którego nie da się napisać w języku C, nie stając się nieefektywnym ze względu na wspomniane powyżej ograniczenia. I jeszcze nie mówiłem o szybkości, która według większości ludzi jest głównym powodem pisania na montażu, cóż, jeśli umysł jest ograniczony do myślenia w języku C, to na zawsze jesteś niewolnikiem swojego kompilatora. Zawsze myślałem, że mistrzowie szachistów będą idealnymi programistami asemblerowymi, podczas gdy programiści C po prostu grają w „Damy”.

Eric W.
źródło
1
samomodyfikujący się kod nie jest przydatny dla wydajności na większości nowoczesnych procesorów, poza scenariuszami JIT-once / run-many. Ale wypełnianie stałych jako natychmiastowych jest fajną możliwością. C gotopozwala jednak na nieustrukturyzowane skoki w funkcji. Włączanie do bloku wewnątrz if()pętli lub w tej samej funkcji. np . godbolt.org/z/IINHTg . Zobacz także Urządzenie Duffa, w którym używa się przełącznika / obudowy do do{}while()pętli, aby wyrazić skok do rozwiniętej pętli. Ale w pewnym momencie pisanie jako asm może stać się jaśniejsze, jeśli schodzisz do tego poziomu bałaganu.
Peter Cordes,
1
(Oczywiście urządzenie Duffa jest przydatne tylko na maszynach z adresowaniem post-inkrementacyjnym, w przeciwnym razie te punkty wejścia wewnątrz rozwiniętej pętli po prostu pokonują większość celu optymalizacji.)
Peter Cordes,
1

Już nie prędkość, ale kontrola . Szybkość czasami zależy od kontroli, ale jest to jedyny powód do kodowania w asemblerze. Każdy inny powód sprowadza się do kontroli (tj. Optymalizacji SSE i innych stron, sterowników urządzeń i kodu zależnego od urządzenia itp.).

Kelden Cowan
źródło
1

Jeśli będę w stanie przewyższyć GCC i Visual C ++ 2008 (znanym również jako Visual C ++ 9.0), ludzie będą zainteresowani przeprowadzeniem ze mną wywiadu, jak to jest możliwe.

Dlatego w tej chwili po prostu czytam rzeczy w asemblerze i po prostu piszę __asm ​​int 3, gdy jest to wymagane.

Mam nadzieję, że ta pomoc ...

Mandragora
źródło
1

Od kilku lat nie pisałem w asemblerze, ale dwa powody to:

  • Wyzwanie! Przeszedłem kilka miesięcy temu lata temu, kiedy pisałem wszystko w asemblerze x86 (czasy DOS i Windows 3.1). Zasadniczo nauczył mnie kawałka operacji niskopoziomowych, sprzętu we / wy itp.
  • Dla niektórych rzeczy utrzymywał mały rozmiar (ponownie DOS i Windows 3.1 podczas pisania TSR )

Wciąż patrzę na montaż kodowania i to nic innego jak wyzwanie i radość z tego. Nie mam innego powodu :-)

Chris J
źródło
1

Kiedyś przejąłem projekt DSP, który poprzedni programista napisał głównie w kodzie asemblera, z wyjątkiem logiki wykrywania tonów, która została napisana w C, używając zmiennoprzecinkowego (na stałym punkcie DSP!). Logika wykrywania tonu działała około 1/20 czasu rzeczywistego.

Skończyło się na przepisaniu prawie wszystkiego od zera. Prawie wszystko było w C, z wyjątkiem kilku małych programów obsługi przerwań i kilkudziesięciu linii kodu związanych z obsługą przerwań i wykrywaniem niskich częstotliwości, które działają ponad 100 razy szybciej niż stary kod.

Myślę, że ważną rzeczą, o której należy pamiętać, jest to, że w wielu przypadkach będzie znacznie większe możliwości zwiększenia szybkości przy użyciu małych procedur niż dużych, zwłaszcza jeśli ręcznie napisany asembler może zmieścić wszystko w rejestrach, ale kompilator nie całkiem poradzić sobie. Jeśli pętla jest na tyle duża, że ​​i tak nie może przechowywać wszystkiego w rejestrach, jest znacznie mniej okazji do poprawy.

supercat
źródło
0

Maszyna wirtualna Dalvik, która interpretuje kod bajtowy aplikacji Java na telefonach z systemem Android, korzysta z asemblera jako dyspozytora. Ten film (około 31 minut, ale warto obejrzeć cały film!) Wyjaśnia, jak to zrobić

„wciąż są przypadki, w których człowiek może sobie poradzić lepiej niż kompilator”.

Będzie
źródło
0

Nie robię tego, ale postanowiłem przynajmniej spróbować i bardzo się postarać w przyszłości (miejmy nadzieję, że wkrótce). Nie może być nic złego, aby dowiedzieć się więcej na temat rzeczy niskiego poziomu i tego, jak działają one za kulisami, gdy programuję w języku wysokiego poziomu. Niestety, trudno o pracę na pełny etat jako programista / konsultant i rodzic. Ale poddam się w odpowiednim czasie, to na pewno.

Henric
źródło