Programuję w językach wyższego poziomu (Python, C #, VBA, VB.NET) od około 10 lat i zupełnie nie rozumiem, co się dzieje „pod maską”.
Zastanawiam się, jakie są korzyści z nauki asemblera i jak pomoże mi to jako programista? Czy możesz podać mi zasób, który pokaże mi dokładnie związek między tym, co piszę w kodzie wyższego poziomu, a tym, co dzieje się w asemblerze?
for
pętlę, deklarując zmienne poza nią. przykładOdpowiedzi:
Ponieważ zrozumiesz, jak to naprawdę działa.
Sprowadza się to do tego, że wszystkie rzeczy, które piszemy w języku C # lub Python, muszą zostać przetłumaczone na sekwencję podstawowych działań, które komputer może wykonać. Łatwo jest myśleć o komputerze w kategoriach klas, ogólnych i listowych, ale istnieją one tylko w naszych językach programowania wysokiego poziomu.
Możemy myśleć o konstrukcjach językowych, które wyglądają naprawdę ładnie, ale nie przekładają się zbyt dobrze na niskopoziomowy sposób robienia rzeczy. Wiedząc, jak to naprawdę działa, lepiej zrozumiesz, dlaczego rzeczy działają tak, jak działają.
źródło
Zapewni to lepsze zrozumienie tego, co „dzieje się pod maską” oraz w jaki sposób działają wskaźniki oraz znaczenie zmiennych rejestru i architektury (przydzielanie i zarządzanie pamięcią, przekazywanie parametrów (według wartości / przez odniesienie) itp.).
Na szybki rzut oka z C, jak to jest?
skompiluj
gcc -S so.c
i spójrz na dane wyjściowe zestawu wso.s
:źródło
so.c
plik do pytań o przepełnienie stosu (jak mamso.py
,so.awk
itp.), Aby szybko przetestować. So.S .. :)gcc -O -c -g -Wa,-ahl=so.s so.c
, możesz zobaczyć dane wyjściowe zestawu dla każdej linii kodu C. To sprawia, że trochę łatwiej jest zrozumieć, co się dzieje.5:so.c
kod w wierszu 5so.c
.Myślę, że odpowiedź, której szukasz, znajduje się tutaj: http://www.codeproject.com/Articles/89460/Why-Learn-Assembly-Language
Cytat z artykułu:
Dodatkowo polecam tę książkę, ponieważ ma ona uproszczoną wersję architektury komputera: Wprowadzenie do systemów obliczeniowych: od Bits and Gates do C i Beyond, 2 / e Yale N. Patt, University of Texas w Austin Sanjay J. Patel, Uniwersytet illinois w Urbana-Champaign
źródło
Moim skromnym zdaniem niewiele to pomaga.
Bardzo dobrze znałem montaż x86. Pomogło mi to trochę, gdy na moich kursach pojawił się montaż, pojawił się raz podczas wywiadu i pomógł mi udowodnić, że kompilator (Metrowerks) generuje zły kod. To fascynujące, jak naprawdę działa komputer, i czuję się bogatszy intelektualnie, że się go nauczyłem. W tym czasie gra była bardzo przyjemna.
Jednak dzisiejsze kompilatory lepiej generują asemblowanie niż prawie każdy na prawie dowolnym fragmencie kodu. O ile nie piszesz kompilatora lub nie sprawdzasz, czy kompilator działa prawidłowo, prawdopodobnie marnujesz czas, ucząc się go.
Przyznaję, że wiele pytań, które programiści C ++ wciąż z powodzeniem zadają, jest udzielanych przez znajomość asemblera. Na przykład: czy powinienem używać zmiennych stosu lub sterty? powinienem przekazać według wartości lub stałej referencji? Jednak prawie we wszystkich przypadkach uważam, że tych wyborów należy dokonywać w oparciu o czytelność kodu, a nie oszczędność czasu obliczeniowego. (Np. Używaj zmiennych stosu, ilekroć chcesz ograniczyć zmienną do zakresu.)
Moja skromna sugestia polega na skoncentrowaniu się na umiejętnościach, które naprawdę mają znaczenie: projektowaniu oprogramowania, analizie algorytmów i rozwiązywaniu problemów. Z doświadczeniem w tworzeniu dużych projektów poprawi się Twoja intuicja, co znacznie zwiększy twoją wartość niż znajomość montażu (moim zdaniem).
źródło
Powinieneś znać jeden poziom „głębiej” w systemie, nad którym pracujesz. Przeskakiwanie za daleko za jednym razem nie jest złe, ale może nie być tak pomocne, jak by się chciało.
Programista w języku wysokiego poziomu powinien nauczyć się języka niższego poziomu (C to doskonała opcja). Nie musisz iść do samego montażu, aby poznać to, co dzieje się pod przykryciem, gdy mówisz komputerowi, aby utworzył instancję obiektu, utworzył tablicę skrótów lub zestaw - ale powinieneś być w stanie kodować im.
Dla programisty Java, nauczenie się trochę C pomogłoby ci w zarządzaniu pamięcią, przekazywaniu argumentów. Napisanie części obszernej biblioteki Java w C pomogłoby zrozumieć, kiedy użyć jakiej implementacji Seta (chcesz skrótu? Lub drzewa?). Postępowanie z char * w środowisku wątkowym pomoże zrozumieć, dlaczego String jest niezmienny.
Przeniesiony na wyższy poziom ... Programista AC powinien znać się na montażu, a typy montażu (często spotykane w sklepach z systemami wbudowanymi) prawdopodobnie dobrze sobie radzą ze zrozumieniem rzeczy na poziomie bramek. Ci, którzy pracują z bramami, powinni znać fizykę kwantową. A ci fizycy kwantowi, cóż, wciąż próbują dowiedzieć się, jaka jest następna abstrakcja.
źródło
Ponieważ nie wspomniałeś o C lub C ++ w językach, które znasz. Poleciłbym MOCNIE nauczenie się ich, zanim nawet pomyśli o montażu. C lub C ++ poda wszystkie podstawowe pojęcia, które są całkowicie przejrzyste w językach zarządzanych, a większość pojęć wymienionych na tej stronie zrozumiesz w jednym z najważniejszych języków, których możesz używać w projektach w świecie rzeczywistym. To prawdziwa wartość dodana do twoich umiejętności programowania. Należy pamiętać, że asembler jest używany w bardzo specyficznych obszarach i nie jest tak przydatny jak C lub C ++.
Chciałbym nawet powiedzieć, że nie powinieneś nurkować na zgromadzeniu, zanim zrozumiesz, jak działają języki niezarządzane. To prawie obowiązkowa lektura.
Powinieneś nauczyć się montażu, jeśli chcesz zejść jeszcze niżej. Chcesz wiedzieć, jak dokładnie tworzona jest każda konstrukcja języka. Ma charakter informacyjny, ale ma złożoność na zupełnie innym poziomie.
źródło
Jeśli znasz dobrze język, powinieneś mieć przynajmniej podstawową wiedzę na temat technologii o jeden poziom abstrakcji niższą.
Dlaczego? Gdy coś pójdzie nie tak, znajomość podstawowych mechanizmów znacznie ułatwia debugowanie dziwnych problemów i naturalnie pisanie bardziej wydajnego kodu
Używając Pythona (/ CPython) jako przykładu, jeśli zaczniesz mieć dziwne awarie lub niską wydajność, wiedza na temat debugowania kodu C może być bardzo przydatna, podobnie jak wiedza na temat jego metody zarządzania pamięcią. Pomoże to również wiedzieć, kiedy / czy napisać coś jako rozszerzenie C i tak dalej ...
Aby odpowiedzieć na twoje pytanie w tym przypadku, znajomość asemblera naprawdę nie pomogłaby doświadczonemu deweloperowi Pythona (to zbyt wiele kroków w dół od abstrakcji - cokolwiek zrobione w Pythonie skutkowałoby wieloma wieloma instrukcjami asemblacji)
.. ale jeśli masz doświadczenie z C, to znajomość „następnego poziomu w dół” (montaż) byłaby rzeczywiście przydatna.
Podobnie, jeśli używasz CoffeScript, to (bardzo) przydatna jest znajomość Javascript. Jeśli korzystasz z Clojure, przydatna jest znajomość Java / JVM.
Ten pomysł działa również poza językami programowania - jeśli używasz asemblera, dobrym pomysłem jest zapoznanie się z funkcjonowaniem podstawowego sprzętu. Jeśli jesteś projektantem stron internetowych, dobrze jest wiedzieć, jak jest wdrażana aplikacja internetowa. Jeśli jesteś mechanikiem samochodowym, dobrze jest mieć wiedzę na temat fizyki
źródło
Napisz mały program c i zdemontuj wyjście. To wszystko. Należy jednak być przygotowanym na większy lub mniejszy stopień kodu „sprzątania”, który zostanie dodany na korzyść systemu operacyjnego.
Montaż pomaga zrozumieć, co dzieje się pod maską, ponieważ dotyczy bezpośrednio pamięci, rejestrów procesorów i tym podobnych.
Jeśli naprawdę chcesz przejść od zera, bez komplikacji systemu operacyjnego komplikujących rzeczy, spróbuj zaprogramować Arduino w języku asemblera.
źródło
Nie ma ostatecznej odpowiedzi, ponieważ programiści nie są tego samego typu. Czy musisz wiedzieć, co czai się pod spodem? Jeśli tak, naucz się tego. chcesz po prostu nauczyć się tego z ciekawości? Jeśli tak, naucz się tego. Jeśli nie przyniesie ci to praktycznych korzyści, po co się tym przejmować? Czy do prowadzenia samochodu potrzebny jest poziom wiedzy mechanika? Czy mechanik potrzebuje wiedzy inżyniera, aby pracować tylko w samochodzie? To poważna analogia. Mechanik może być bardzo dobrym, produktywnym mechanikiem bez nurkowania, aby uzyskać głęboką wiedzę o pojazdach, które utrzymuje. To samo dotyczy muzyki. Czy naprawdę chcesz pogłębić złożoność melodii, harmonii i rytmu, aby być dobrym piosenkarzem lub graczem? Nie. Niektórzy wyjątkowo utalentowani muzycy nie potrafią czytać partytury, nie mówiąc już o różnicy między trybami Doriana i Lidiana. Jeśli chcesz, w porządku, ale nie, nie musisz. Jeśli jesteś programistą, montaż nie ma praktycznego zastosowania, o którym mogę myśleć. Jeśli jesteś w systemach wbudowanych lub czymś naprawdę specjalnym, może to być konieczne, ale gdyby tak było, wiedziałbyś o tym.
Oto, jak Joel przyjmuje wartość uczenia się języka wyższego poziomu: http://www.joelonsoftware.com/articles/ThePerilsofJavaSchools.html
źródło
Właściwie to, co prawdopodobnie byłoby dla ciebie najlepsze, byłaby klasa, która (o ile wiem) nigdzie nie istnieje: byłaby to klasa, która łączy krótki przegląd języka maszyn / asemblerów i koncepcji adresowania pamięci z przewodnikiem po budowie kompilatora , generowanie kodu i środowiska wykonawcze.
Problem polega na tym, że w języku wysokiego poziomu, z dala od sprzętu, takim jak C # lub Python, tak naprawdę nie doceniasz faktu, że każdy wykonywany ruch zamienia się w setki, jeśli nie tysiące instrukcji maszynowych, i nie mają tendencję do zrozumienia, w jaki sposób kilka wierszy języka wysokiego poziomu może powodować dostęp i modyfikację ogromnej ilości pamięci. Nie chodzi o to, że musisz dokładnie wiedzieć, co się dzieje „pod przykrywkami”, ale musisz docenić zakres tego, co się dzieje, i ogólną koncepcję rodzajów rzeczy, które się zdarzają.
źródło
Moja odpowiedź na to pytanie ewoluowała stosunkowo niedawno. Istniejące odpowiedzi obejmują to, co powiedziałbym w przeszłości. W rzeczywistości jest to nadal objęte najważniejszą odpowiedzią - punkt „doceniaj konstrukty w programowaniu wyższego poziomu”, ale myślę, że jest to szczególny przypadek, o którym warto wspomnieć ...
Według tego posta na blogu Jeffa Atwooda , który odnosi się do badania, zrozumienie przypisania jest kluczową kwestią w zrozumieniu programowania. Programiści uczący się albo rozumieją, że notacja po prostu reprezentuje kroki, które podąża komputer, i uzasadniają te kroki, albo stają się wiecznie zdezorientowani przez wprowadzające w błąd analogie do równań matematycznych itp.
Cóż, jeśli rozumiesz następujące elementy z asemblera 6502 ...
To naprawdę tylko kroki. Kiedy nauczysz się tłumaczyć to na instrukcję przypisania ...
Nie potrzebujesz wprowadzającej w błąd analogii do równania matematycznego - masz już prawidłowy model mentalny, aby go odwzorować.
EDYCJA - oczywiście jeśli wyjaśnienie, które otrzymujesz,
LDA variable
jest w gruncie rzeczyACCUMULATOR = variable
, dokładnie to, co otrzymujesz z niektórych samouczków i odniesień, kończysz tam, gdzie zacząłeś i wcale nie jest to pomocne.Nauczyłem się asemblera 6502 jako mojego drugiego języka, z których pierwszym był Commodore Basic, i tak naprawdę niewiele się wtedy nauczyłem - częściowo dlatego, że tak mało było do nauczenia, ale także dlatego, że asembler wydawał się wtedy o wiele bardziej interesujący . Częściowo razy, częściowo dlatego, że miałem 14 lat geek.
Nie polecam robić tego, co zrobiłem, ale zastanawiam się, czy przestudiowanie kilku bardzo prostych przykładów w bardzo prostym języku asemblera może być wartościowym wstępem do nauki języków wyższego poziomu.
źródło
O ile nie jesteś pisarzem kompilatora lub nie potrzebujesz czegoś wysoce zoptymalizowanego (takiego jak algorytm przetwarzania danych), nauka kodowania asemblera nie zapewni żadnych korzyści.
Pisanie i obsługa kodu napisanego w asemblerze jest bardzo trudna, dlatego nawet jeśli znasz język asemblera bardzo dobrze, nie powinieneś go używać, chyba że istnieją inne sposoby.
Artykuł „ Optymalizacja pod kątem SSE: studium przypadku ” pokazuje, co można zrobić, jeśli pójdziesz na montaż. Autorowi udało się zoptymalizować algorytm ze 100 cykli / wektor do 17 cykli / wektor.
źródło
Pisanie w asemblerze nie dałoby magicznego wzrostu prędkości, ponieważ z powodu ilości szczegółów (alokacja rejestru itp.) Prawdopodobnie napiszesz najbardziej trywialny algorytm, jaki kiedykolwiek powstał.
Dodatkowo dzięki nowoczesnym (czytanym - zaprojektowanym po 70-80) procesorom montaż nie zapewni wystarczającej liczby szczegółów, aby wiedzieć, co się dzieje (to znaczy - na większości procesorów). Nowoczesne PU (CPU i GPU) są dość złożone, jeśli chodzi o instrukcje planowania. Znajomość podstaw montażu (lub pseudo-montażu) pozwoli zrozumieć książki / kursy architektury komputerowej, które dostarczyłyby dalszej wiedzy (pamięci podręczne, wykonywanie poza kolejnością, MMU itp.). Zwykle nie trzeba znać złożonego ISA, aby je zrozumieć (MIPS 5 jest dość popularnym IIRC).
Po co rozumieć procesor? Może dać ci znacznie więcej zrozumienia, co się dzieje. Powiedzmy, że piszesz mnożenie macierzy w naiwny sposób:
Może być „wystarczająco dobry” dla twojego celu (jeśli jest to macierz 4x4, i tak może być skompilowana do instrukcji wektorowych). Istnieją jednak dość ważne programy podczas kompilacji ogromnych tablic - jak je zoptymalizować? Jeśli napiszesz kod w asemblerze, możesz mieć kilka procent ulepszeń (chyba że zrobiłbyś to tak, jak robi większość ludzi - także w naiwny sposób, wykorzystując niewykorzystane rejestry, stale ładując / przechowując w pamięci i w efekcie mając wolniejszy program niż w języku HL) .
Jednak możesz odwrócić linie i magicznie zyskać wydajność (dlaczego? Zostawiam to jako „pracę domową”) - IIRC w zależności od różnych czynników dla dużych matryc może być nawet 10x.
To powiedziawszy - pracują nad tym, aby kompilatory były w stanie to zrobić ( grafit dla gcc i Polly dla czegokolwiek używającego LLVM). Są nawet w stanie je przekształcić (przepraszam - piszę blokowanie z pamięci):
Podsumowując - znajomość podstaw złożenia pozwala na zagłębienie się w różne „szczegóły” z projektu procesora, które pozwoliłyby pisać szybsze programy. Warto znać różnice między architekturami RISC / CISC lub VLIW / vector Processor / SIMD / ... Nie chciałbym jednak zaczynać od x86, ponieważ są one dość skomplikowane (być może również ARM) - wiedza na temat rejestru itp. Jest wystarczająca do uruchomienia IMHO.
źródło
Zwykle jest to BARDZO ważne dla celów debugowania. Co robisz, gdy system pęka w środku instrukcji i błąd nie ma sensu? Z językami .NET nie ma większego problemu, o ile używasz tylko bezpiecznego kodu - system prawie zawsze ochroni cię przed tym, co dzieje się pod maską.
źródło
Krótko mówiąc, myślę, że odpowiedź brzmi, ponieważ możesz zrobić więcej, jeśli nauczysz się montażu. Nauka montażu zapewnia dostęp do dziedzin programowania urządzeń wbudowanych, penetracji i obchodzenia zabezpieczeń, inżynierii wstecznej i programowania systemu, w których bardzo trudno jest pracować, jeśli nie znasz asemblera.
Jeśli chodzi o naukę poprawiania wydajności programu, jest to wątpliwe w programowaniu aplikacji. Przez większość czasu jest tak wiele rzeczy, na których należy się skupić, zanim osiągniesz ten poziom optymalizacji, takich jak optymalizacja dostępu do we / wy zarówno na dysku, jak i w sieci, optymalizacja sposobu tworzenia GUI, wybór odpowiednich algorytmów, maksymalizacja wszystkich rdzeni , działając na najlepszym sprzęcie, jaki można kupić za pieniądze i przechodząc z tłumaczonych na skompilowane języki. O ile nie tworzysz oprogramowania dla innych użytkowników końcowych, sprzęt jest tani w porównaniu do stawki godzinowej programisty, szczególnie w przypadku dostępności w chmurze.
Ponadto musisz rozważyć zwiększenie szybkości wykonywania programu z czytelnością kodu po tym, jak zostaniesz potrącony przez magistralę, wyjdziesz lub wrócisz do bazy kodu, aby zmienić go rok po napisaniu ostatniej wersji.
źródło
Poleciłbym uczenie się algorytmów: sortowania, powiązanych list, drzew binarnych, mieszania itp.
Naucz się także lisp, patrz Struktura i interpretacja programów komputerowych. kilka prymitywnych poleceń, jedno prymitywne seplenienie i niektóre prowokujące asemblery).
Na koniec, jeśli musisz nauczyć się asemblera, naucz się łatwego, takiego jak ARM (również jest on używany w około 4 razy większej liczbie urządzeń niż x86).
źródło
Odpowiedź brzmi: po prostu dlatego, że używany język musi zostać zinterpretowany lub skompilowany na końcu w asemblerze. Bez względu na język lub maszynę.
Konstrukcja języków wywodzi się ze sposobu działania procesora. Więcej o programach niskiego poziomu, mniej o programach wysokiego poziomu.
Zakończę stwierdzeniem, że nie tylko musisz znać mały asembler, ale także architekturę procesora, której uczysz się poprzez naukę asemblera.
Kilka przykładów: Istnieje wielu programistów Java, którzy nie rozumieją, dlaczego to nie działa, a nawet mniej niż wiedzą, co się dzieje po uruchomieniu.
Gdybyś znał małego asemblera, zawsze wiedziałbyś, że nie jest to ta sama zawartość lokalizacji w pamięci, co liczba w zmiennej wskaźnika, która „wskazuje” na tę lokalizację.
Co gorsza, nawet w opublikowanych książkach przeczytasz coś takiego jak w prymitywach JAVA przekazywanych przez wartość, a obiekty przez odniesienie, co jest całkowicie niepoprawne. Wszystkie argumenty w Javie są przekazywane przez wartość, a Java NIE może przekazywać obiektów do funkcji, tylko wskaźniki, które są przekazywane przez wartość.
Jeśli teraz zgromadzisz, to oczywiste, co się dzieje, jeśli nie, wyjaśnienie tego jest tak skomplikowane, że większość autorów po prostu kłamie.
Oczywiście ich konsekwencje są subtelne, ale mogą później sprawić ci poważne kłopoty. Jeśli wiesz, że asembler to nie problem, jeśli nie, czeka cię długa noc debugowania.
źródło
String a = "X"; String b = "X"; if( a==b) return true;
co robi w rzeczywistości z== true
powodu czegoś, co nazywaString interning
się kompilatorem. Wszystkie pozostałe instrukcje Java są również błędne. Java nie ma wskaźników, ma odwołania, które nie są tym samym. I nic z tego nie ma nic wspólnego z asemblerem w żaden sposób. Java przekazuje prymitywy według wartości, a także referencje według wartości. Java nie ma wskaźników, więc nie może ich pominąć. Znowu wszystko nie ma znaczenia dla znajomości ASM.