Dlaczego programy nie są pisane w asemblerze częściej? [Zamknięte]

216

Wydaje się, że powszechne jest zdanie, że programowanie asemblacyjne trwa dłużej i jest trudniejsze do programowania w języku wyższego poziomu, takim jak C. Dlatego wydaje się zalecane lub zakładane, że z tych powodów lepiej jest pisać w języku wyższego poziomu. oraz ze względu na lepszą przenośność.

Ostatnio pisałem w asemblerze x86 i przyszło mi do głowy, że być może te przyczyny nie są tak naprawdę prawdą, z wyjątkiem przenośności. Być może chodzi raczej o znajomość i umiejętność dobrego pisania asemblera. Zauważyłem również, że programowanie w asemblerze jest zupełnie inne niż programowanie w HLL. Być może dobry i doświadczony programista asemblacyjny mógłby pisać programy równie łatwo i tak szybko, jak doświadczony programista C piszący w C.

Być może dzieje się tak, ponieważ programowanie asemblerowe jest zupełnie inne niż HLL, a zatem wymaga odmiennego myślenia, metod i sposobów, co sprawia, że ​​programowanie nieznanych osób wydaje się bardzo niewygodne, a zatem nadaje mu złą nazwę do pisania programów.

Jeśli przenośność nie stanowi problemu, to co C miałby w porównaniu z dobrym asemblerem, takim jak NASM?

Edycja: aby wskazać. Kiedy piszesz w asemblerze, nie musisz pisać tylko w kodach instrukcji. Możesz używać makr i procedur oraz własnych konwencji, aby tworzyć różne abstrakty, aby programy były bardziej modułowe, łatwiejsze w utrzymaniu i łatwiejsze do odczytania. Tutaj pojawia się umiejętność pisania dobrego zestawu.

błota
źródło
71
Pisać ? Co z czytaniem kodu? ty (i inni) będziecie czytać kod dużo więcej niż go piszecie
nos
81
Dlaczego muszę uczyć się nowego języka tylko dlatego, że mój program powinien działać na nowej platformie? Dlaczego powinienem konstruować moje programy, aby pasowały do ​​idei procesorów dotyczących liczby rejestrów i co można z tym zrobić? Staram się rozwiązywać problemy, a nie licytować komputery.
Joachim Sauer
8
Podsumowanie edycji: Można użyć kompilatora C.
Meinersbur
4
@ Simon Może mam wtedy złe lata, ale jestem zaskoczony, że debatujemy nad ASM kontra „językiem wysokiego poziomu, takim jak C” w 2010 r. W szczególności część, w której C jest przykładem języka wysokiego poziomu
matt b
11
@changelog: Nie tak piszesz programowanie.reddit.com.
BoltClock

Odpowiedzi:

331

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.

Co jeśli następny procesor ma dwa razy więcej rejestrów?

Pytanie to brzmi następująco: jaką funkcjonalność zapewniają kompilatory?

Wątpię, czy możesz / chcesz / powinieneś zoptymalizować swój ASM lepiej niż gcc -O3można.

Benoit
źródło
10
gcc nie jest tak dobry w optymalizacji, znacznie lepszy niż przeciętny człowiek, ale jest wiele miejsc, w których optymalizatory nie wykonują dobrej roboty. Zgadzam się z tobą, choć inaczej.
old_timer
4
@dwelch W bardzo rzadkich przypadkach gcc (lub wiele innych kompilatorów) nie optymalizuje poprawnie skompilowanej C. W takich przypadkach zawsze można jednak napisać ograniczoną liczbę procedur w ASM i połączyć tylko te metody podczas kompilacji.
Czwartek
@Ben S: Początkowo edytowałem „wiele”, a nie „dużo”, ponieważ „dużo” jest używane tylko dla pojedynczych obiektów. Ponieważ obiekt „dużo” jest w liczbie mnogiej (programiści), „wiele” jest właściwą opcją. Ale nie będę ponownie edytować twojej odpowiedzi, jeśli „dużo” jest tym, czego chcesz.
Billy ONeal
1
W wielu przypadkach kompilator nie może dobrze zoptymalizować, ale dość często programista, który jest świadomy ograniczeń optymalizatora, może zoptymalizować swój kod C bez uciekania się do asemblera.
Qwertie,
1
FWIW w mojej codziennej pracy kompiluję nasz produkt za pomocą gcc -g -O0, ponieważ możliwość dołączenia do niego gdb w systemie na żywo i nie wariowania z powodu zmiennych zoptymalizowanych nieistniejących, jest o wiele bardziej wart firma niż pozostawia kolejne 4 miliardy cykli procesora bezczynnie każdego dnia (z 3 bilionów). Chrupanie liczb całkowitych nie jest zbyt często wąskim gardłem.
Bernd Jendrissek
1930

Cześć, jestem kompilatorem.

Właśnie zeskanowałem tysiące wierszy kodu podczas czytania tego zdania. Przeglądałem miliony możliwości optymalizacji jednej linii przy użyciu setek różnych technik optymalizacji opartych na ogromnej ilości badań akademickich, do których spędziłbyś lata. Nie będę odczuwał zakłopotania, nawet najmniejszego szarpnięcia, kiedy przekonwertuję pętlę trzywierszową na tysiące instrukcji, aby przyspieszyć. Nie mam wstydu, gdy staram się optymalizować i robić najbrudniejsze sztuczki. A jeśli nie chcesz, żebym to zrobił, może na dzień lub dwa, zachowam się i zrobię to tak, jak lubisz. Mogę przekształcić metody, których używam, kiedy chcesz, nawet bez zmiany jednej linii twojego kodu. Mogę nawet pokazać, jak Twój kod wyglądałby w asemblerze, na różnych architekturach procesorów i różnych systemach operacyjnych oraz w różnych konwencjach montażowych, jeśli chcesz. Tak, wszystko w kilka sekund. Ponieważ wiesz, że mogę; i wiesz, nie możesz.

PS A tak przy okazji, nie używałeś połowy kodu, który napisałeś. Wyświadczyłem ci przysługę i wyrzuciłem ją.

ssg
źródło
99

Napisałem rzuty asemblera dla układów 6502, Z80, 6809 i 8086. Przestałem to robić, gdy tylko kompilatory C stały się dostępne dla platform, na które zwracałem uwagę, i natychmiast stałem się co najmniej 10-krotnie bardziej produktywny. Większość dobrych programistów korzysta z narzędzi, których używają z racjonalnych powodów.

zaraz
źródło
72

Uwielbiam programować w asemblerze, ale potrzeba więcej kodu, aby zrobić to samo, co w języku wysokiego poziomu, i istnieje bezpośrednia korelacja między wierszami kodu a błędami. (Wyjaśniono to kilkadziesiąt lat temu w The Mythical Man-Month .)

Można myśleć o C jako o „zespole wysokiego poziomu”, ale przejdź kilka kroków wyżej, a znajdziesz się w innym świecie. W C # nie myślisz dwa razy o napisaniu tego:

foreach (string s in listOfStrings) { /* do stuff */ }

Byłyby to dziesiątki, może setki linii kodu w asemblerze, każdy programista, który go wdrożył, przyjąłby inne podejście, a następna osoba, która się pojawi, musiałaby to rozgryźć. Więc jeśli uważasz (jak wielu), że programy są napisane przede wszystkim dla innych osób do czytania, asembler jest mniej czytelny niż typowy HLL.

Edycja: zgromadziłem osobistą bibliotekę kodu używanego do typowych zadań oraz makra do implementacji struktur kontrolnych podobnych do C. Ale uderzyłem w ścianę w latach 90., kiedy GUI stały się normą. Zbyt wiele czasu poświęcano na rzeczy rutynowe.

Ostatnim zadaniem, w którym ASM był niezbędny, było kilka lat temu, napisanie kodu do zwalczania złośliwego oprogramowania. Brak interfejsu użytkownika, więc były to wszystkie zabawne części bez wzdęcia.

egrunin
źródło
Czy jesteś tego pewien? Wydaje mi się, że pamiętam czytanie w Code Complete, że tak nie było ...
jcolebrand
1
Jestem pewien, że jest punkt, w którym przewagę „mniejszej liczby linii” pokonuje wada „przedwczesnej optymalizacji”. Ale nie widziałem Code Complete od wieków ...
egrunin
6
Trochę ironiczne jest użycie „przedwczesnej optymalizacji” jako argumentu do złożenia ... (Prawdopodobnie jednak źle cię interpretuję. Nadal uważam, że to zabawne.)
Bernd Jendrissek
Nadal możesz wywoływać funkcję w asemblerze, więc wątpię, że pętla foreach zajmuje dziesiątki do setek linii. Lub czego mi brakuje?
Sebastian Mach
@ phresnel: foreachdziała znacznie więcej niż for- tworzy instancję i używa iteratora specyficznego dla typu.
egrunin
15

Oprócz odpowiedzi innych osób na czytelność, łatwość konserwacji, krótszy kod, a tym samym mniej błędów i będąc znacznie łatwiejszym, dodam dodatkowy powód:

prędkość programu.

Tak, w asemblerze możesz ręcznie dostroić kod, aby wykorzystać każdy ostatni cykl i uczynić go tak szybkim, jak to fizycznie możliwe. Kto jednak ma czas? Jeśli napiszesz niezupełnie głupi program w C, kompilator wykona dla ciebie naprawdę dobrą robotę optymalizacji. Prawdopodobnie dokonanie co najmniej 95% optymalizacji, które zrobiłbyś ręcznie, bez konieczności martwienia się o śledzenie któregoś z nich. Jest tu zdecydowanie reguła 90/10, w której ostatnie 5% optymalizacji zajmie 95% twojego czasu. Więc po co zawracać sobie głowę?

Brian Postow
źródło
4
+1. Pisanie kodu asemblera i pisanie szybkiego kodu asemblera to dwie różne rzeczy. Jeśli korzystasz z dobrego kompilatora, otrzymasz szybki kod asemblera za darmo.
Niki,
otrzymujesz kod szybkiego asemblera za darmo tylko wtedy, gdy wiesz, jak korzystać z kompilatora, większość nie korzysta z optymalizacji, większość ludzi kompiluje się z opcjami debugowania, w wyniku czego kończy się to źle wykonanym wolnym asemblerem. tak, w ponad 99% przypadków nie należy go dotykać, wystarczy dotknąć pokręteł kompilatora i nie modyfikować bezpośrednio wyjścia.
old_timer
jeśli zależy Ci na optymalizacjach, powinieneś to zrobić z kompilatora ... JEŻELI nie zależy ci na optymalizacjach, ale nadal używasz asemblera, to po prostu jesteś głupi.
Brian Postow
@dwelch: Wydaje mi się, że mogą istnieć dzieciaki ze skryptów, które nie zadają sobie trudu, aby dowiedzieć się, w jaki sposób są używane narzędzia. Ale wątpię, aby ludzie tacy jak oni mogli kiedykolwiek napisać kod szybkiego asemblera.
Niki
13

Jeśli przeciętny program produkcyjny ma na myśli 100 000 wierszy kodu, a każdy wiersz zawiera około 8-12 instrukcji asemblera, będzie to 1 milion instrukcji asemblera.

Nawet jeśli potrafisz napisać to wszystko ręcznie z przyzwoitą szybkością (pamiętaj, że musisz napisać 8 razy więcej kodu), co się stanie, jeśli chcesz zmienić niektóre funkcje? Zrozumienie czegoś, co napisałeś kilka tygodni temu z tych 1 miliona instrukcji, to koszmar! Nie ma modułów, klas, nie ma projektowania obiektowego, żadnych ram, nic. A ilość podobnie wyglądającego kodu, który musisz napisać dla nawet najprostszych rzeczy, jest co najmniej zniechęcająca.

Poza tym nie można zoptymalizować kodu prawie tak dobrze, jak języka wysokiego poziomu. Tam, gdzie na przykład C wykonuje szaloną liczbę optymalizacji, ponieważ opisujesz swoje zamiary, a nie tylko kod, w asemblerze piszesz tylko kod, asembler nie jest w stanie dokonać żadnych godnych uwagi optymalizacji w kodzie. To, co piszesz, dostajesz i wierz mi, nie możesz niezawodnie zoptymalizować 1 miliona instrukcji, które łatasz i łatasz podczas pisania.

Blindy
źródło
8

Cóż, pisałem dużo asemblera „w dawnych czasach” i mogę was zapewnić, że jestem o wiele bardziej produktywny, pisząc programy w języku wysokiego poziomu.

Maurice Perry
źródło
8
„Zgromadzenie jest po łacinie”.
Adriano Varoli Piazza
4
@Adriano: z wyjątkiem tego, że istnieje wiele, wiele różnych dialektów i żaden z nich nie wygląda tak samo.
Joachim Sauer
1
Jasne, ale miałem na myśli, że nauka programowania w dowolnym z nich daje wgląd w architekturę maszyny, która pomaga na wyższych poziomach. Jeśli nie poradzisz sobie z pamięcią stronicowaną, w takim przypadku skończysz blizną. Jak czytanie Carmen 16 z Catullus.
Adriano Varoli Piazza
5
@Adriano „Zgromadzenie jest po łacinie”, żaden asm nie chrząka jaskiniowiec. Jeden pomruk dla skał 2 stopnie dla jelenia, 3 stopnie dla ognia - dobre dla prostych rzeczy, ale trudne do prowadzenia imperium.
Martin Beckett
1
@Martin: Czy kiedykolwiek próbowałeś wykonywać złożoną arytmetykę z cyframi rzymskimi?
Adriano Varoli Piazza
6

Rozsądny poziom kompetencji asemblera to przydatna umiejętność, szczególnie jeśli pracujesz na dowolnym poziomie systemu lub programowania wbudowanego, nie tyle dlatego, że musisz napisać tyle asemblera, ale dlatego, że czasami ważne jest, aby zrozumieć, co naprawdę robi pudełko . Jeśli nie masz niskiego poziomu zrozumienia pojęć i problemów asemblera, może to być bardzo trudne.

Jednak, jeśli chodzi o pisanie dużej ilości kodu w asemblerze, istnieje kilka powodów, dla których niewiele się to robi.

  • Po prostu nie ma (prawie) potrzeby. Z wyjątkiem czegoś takiego jak bardzo wczesna inicjalizacja systemu i być może kilka fragmentów asemblera ukrytych w funkcjach C lub makrach, wszystkie kody niskiego poziomu, które kiedyś mogły zostać napisane w asemblerze, można bez trudu napisać w C lub C ++.

  • Kod w językach wyższego poziomu (nawet C i C ++) ogranicza funkcjonalność do znacznie mniejszej liczby wierszy, a wiele badań wykazało, że liczba błędów koreluje z liczbą wierszy kodu źródłowego. Tj. Ten sam problem, rozwiązany w asemblerze i C, będzie miał więcej błędów w asemblerze, ponieważ jest dłuższy. Ten sam argument motywuje przejście do języków wyższego poziomu, takich jak Perl, Python itp.

  • Pisząc w asemblerze, musisz poradzić sobie z każdym aspektem problemu, od szczegółowego układu pamięci, wyboru instrukcji, wyboru algorytmu, zarządzania stosami itp. Języki wyższego poziomu zabierają ci to wszystko, dlatego są tak gęstsze w warunki LOC.

Zasadniczo wszystkie powyższe są związane z poziomem abstrakcji dostępnym w asemblerze w porównaniu do C lub innego języka. Asembler zmusza cię do robienia wszystkich własnych abstrakcji i utrzymywania ich poprzez własną samodyscyplinę, w której każdy język średniego poziomu, taki jak C, a zwłaszcza języki wyższego poziomu, dostarczają abstrakcji od razu po wyjęciu z pudełka, a także możliwość stosunkowo łatwego tworzenia nowych.

Dale Hagglund
źródło
6

Jako programista, który spędza większość swojego czasu we wbudowanym świecie programowania, twierdzę, że asembler jest daleki od martwego / przestarzałego języka. Istnieje pewien zbliżony do metalicznego poziom kodowania (na przykład w sterownikach), który czasami nie może być wyrażony tak dokładnie lub wydajnie w języku wyższego poziomu. Piszemy prawie wszystkie nasze procedury interfejsu sprzętowego w asemblerze.

To powiedziawszy, ten kod asemblera jest opakowany tak, że można go wywołać z kodu C i jest traktowany jak biblioteka. Z wielu powodów nie piszemy całego programu w asemblerze. Przede wszystkim przenośność; nasza baza kodu jest używana w kilku produktach, które używają różnych architektur i chcemy zmaksymalizować ilość kodu, który można udostępnić między nimi. Drugi to znajomość programisty. Mówiąc wprost, szkoły nie uczą asemblera tak, jak kiedyś, a nasi programiści są znacznie bardziej produktywni w C niż w asemblerze. Ponadto mamy wiele różnych „dodatków” (takich jak biblioteki, debuggery, narzędzia analizy statycznej itp.) Dostępnych dla naszego kodu C, które nie są dostępne dla kodu języka asemblera. Nawet jeśli chcielibyśmy napisać program do samodzielnego montażu, nie bylibyśmy w stanie tego zrobić, ponieważ kilka krytycznych bibliotek sprzętowych jest dostępnych tylko jako biblioteki C. W pewnym sensie jest to problem z kurczakiem / jajkiem. Ludzie są odciągani od asemblera, ponieważ nie ma tylu bibliotek i narzędzi programistycznych / debugujących, ale biblioteki / narzędzia nie istnieją, ponieważ zbyt mało ludzi używa asemblera, aby uzasadnić wysiłek ich tworzenia.

W końcu jest czas i miejsce na każdy język. Ludzie używają tego, co są im najbardziej znane i produktywne. Prawdopodobnie zawsze znajdzie się miejsce w repertuarze programisty do montażu, ale większość programistów odkryje, że mogą pisać kod w języku wyższego poziomu, który jest prawie tak samo wydajny w znacznie krótszym czasie.

bta
źródło
6

Kiedy piszesz w asemblerze, nie musisz pisać tylko w kodach instrukcji. Możesz używać makr i procedur oraz własnych konwencji, aby tworzyć różne abstrakty, aby programy były bardziej modułowe, łatwiejsze w utrzymaniu i łatwiejsze do odczytania.

Więc w zasadzie mówisz, że dzięki umiejętnemu użyciu wyrafinowanego asemblera możesz uczynić swój kod ASM coraz bliższym C (lub w każdym razie innym językiem niskiego poziomu własnego wynalazku), aż w końcu będziesz po prostu tak produktywny jak programista C.

Czy to jest odpowiedź na Twoje pytanie? ;-)

Nie mówię tego bezczynnie: programowałem używając dokładnie takiego asemblera i systemu. Co więcej, asembler mógłby celować w procesor wirtualny, a osobny tłumacz skompilował dane wyjściowe asemblera dla platformy docelowej. Podobnie dzieje się z IF LLVM, ale w jego wczesnych formach sprzed około 10 lat. Była więc przenośność, a także możliwość pisania procedur dla określonego docelowego asemblera tam, gdzie jest to wymagane ze względu na wydajność.

Pisanie przy użyciu tego asemblera było tak samo produktywne jak C, a w porównaniu z GCC-3 (który był mniej więcej w tym czasie, kiedy byłem w to zaangażowany) asembler / translator tworzył kod, który był mniej więcej tak szybki i zwykle mniejszy. Wielkość była naprawdę ważna, a firma miała niewielu programistów i była gotowa uczyć nowych pracowników nowego języka, zanim będą mogli zrobić coś pożytecznego. I mieliśmy kopię zapasową, że ludzie, którzy nie znali asemblera (np. Klienci), mogliby napisać C i skompilować go dla tego samego wirtualnego procesora, stosując tę ​​samą konwencję wywoływania i tak dalej, tak aby interfejs był zgrany. Czułem się więc jak marginalna wygrana.

Tak było w przypadku wielu lat pracy w torbie przy opracowywaniu technologii asemblera, bibliotek itp. Trzeba przyznać, że większość z nich stała się przenośna, gdyby celowała tylko w jedną architekturę, wówczas śpiewający wszystko asembler byłby znacznie łatwiejszy.

Podsumowując: możesz nie lubić C, ale to nie znaczy, że wysiłek związany z użyciem C jest większy niż wysiłek wymyślenia czegoś lepszego.

Steve Jessop
źródło
5

Montaż nie jest przenośny między różnymi mikroprocesorami.

semaj
źródło
Nie jest to do końca prawdą w przypadku współczesnych procesorów i programów asemblerowych, możesz kierować reklamy na różne procesory tak jak w C. Czy na pewno nie będziesz w stanie użyć pełnego zestawu instrukcji w tym przypadku, ale nie zrobisz tego, jeśli go napiszesz w C. Przenośność nie jest głównym problemem.
Blindy,
6
Może masz na myśli architekturę .
Ben S
2
@Blindy - możesz atakować różne procesory z rodziny x86, ale zdecydowanie nie ma podobieństwa w instrukcjach montażu między wariantem x86 a procesorem ARM lub Z80 lub 8051.
semaj
To prawda, ale wtedy nie można również zaprogramować Z80 w c. Myślę, że wszyscy mówimy tutaj o normalnych procesorach x86 / x64.
Blindy,
1
Cały świat to nie x86. Nic o „różnych mikroprocesorach” nie sugeruje, że wszystkie wykonują ten sam zestaw instrukcji.
Bernd Jendrissek
5

Z tego samego powodu, dla którego nie chodzimy już do łazienki na zewnątrz lub dlaczego nie mówimy po łacinie ani aramejsku.

Pojawia się technologia, dzięki której wszystko staje się łatwiejsze i bardziej dostępne.

EDYCJA - aby przestać obrażać ludzi, usunąłem pewne słowa.

Jack Marchetti
źródło
4
Nadal Technology
obrażasz Luddytów
1
„My” nie mówimy po łacinie?
wilgotny
Ani łacina, ani aramejski nie zniknęły, ponieważ zostały zastąpione przez lepszą technologię (tj. Łatwiejszą do nauczenia się / podnoszenia języka). W rzeczywistości łacina jest nadal z nami wszędzie w Europie. Wszystkie języki rzymskie oparte są na łacinie. Współczesny (neo) aramejski jest używany przez prawie pół miliona ludzi. Powody, dla których języki te nie są już powszechne, są historyczne (geopolityczne, a dokładniej), a nie technologiczne. Ten sam powód, dla którego angielski jest lingua franca nauki i klas rządzących w naszym wieku - mówią nim ludzie z ostatniego imperium, Brytyjczycy (a teraz Amerykanie).
Ritz
4

Czemu? Prosty.

Porównaj to:

        for (var i = 1; i <= 100; i++)
        {
            if (i % 3 == 0)
                Console.Write("Fizz");
            if (i % 5 == 0)
                Console.Write("Buzz");
            if (i % 3 != 0 && i % 5 != 0)
                Console.Write(i);
            Console.WriteLine();
        }

z

.locals init (
    [0] int32 i)
L_0000: ldc.i4.1 
L_0001: stloc.0 
L_0002: br.s L_003b
L_0004: ldloc.0 
L_0005: ldc.i4.3 
L_0006: rem 
L_0007: brtrue.s L_0013
L_0009: ldstr "Fizz"
L_000e: call void [mscorlib]System.Console::Write(string)
L_0013: ldloc.0 
L_0014: ldc.i4.5 
L_0015: rem 
L_0016: brtrue.s L_0022
L_0018: ldstr "Buzz"
L_001d: call void [mscorlib]System.Console::Write(string)
L_0022: ldloc.0 
L_0023: ldc.i4.3 
L_0024: rem 
L_0025: brfalse.s L_0032
L_0027: ldloc.0 
L_0028: ldc.i4.5 
L_0029: rem 
L_002a: brfalse.s L_0032
L_002c: ldloc.0 
L_002d: call void [mscorlib]System.Console::Write(int32)
L_0032: call void [mscorlib]System.Console::WriteLine()
L_0037: ldloc.0 
L_0038: ldc.i4.1 
L_0039: add 
L_003a: stloc.0 
L_003b: ldloc.0 
L_003c: ldc.i4.s 100
L_003e: ble.s L_0004
L_0040: ret 

Są identyczne pod względem funkcji. Drugi nie jest nawet asemblerem, ale .NET IL (język pośredni, podobny do kodu bajtowego Javy). Druga kompilacja przekształca IL w kod natywny (tj. Prawie asembler), czyniąc go jeszcze bardziej tajemniczym.

Andrei Rînea
źródło
3

Domyślam się, że ASM nawet na x86 (_64) ma sens w przypadkach, w których dużo zyskujesz, korzystając z instrukcji trudnych do zoptymalizowania przez kompilator. Na przykład x264 używa dużo asma do kodowania, a przyrosty prędkości są ogromne.

Maister
źródło
2

Jestem pewien, że jest wiele powodów, ale są dwa szybkie powody, o których mogę myśleć

  1. Kod asemblera jest zdecydowanie trudniejszy do odczytania (jestem pewien, że jego pisanie zajmuje więcej czasu)
  2. Gdy masz duży zespół programistów pracujących nad produktem, pomocne jest podzielenie kodu na logiczne bloki i ochrona interfejsów.
Martin Konecny
źródło
1
Pamiętaj, że możesz również podzielić zespół na logiczne bloki.
Paul Williams
2

Jednym z pierwszych odkryć (znajdziesz go w Mitycznym Miesiącu Człowieka Brooksa , który pochodzi z doświadczenia w latach 60. XX wieku) było to, że ludzie byli mniej więcej tak wydajni w jednym języku, jak w innym, w debugowanych liniach kodu dziennie. To oczywiście nie jest powszechnie prawdą i może ulec zepsuciu, gdy jest się zbyt daleko, ale ogólnie było tak w przypadku języków wysokiego poziomu z czasów Brooksa.

Dlatego najszybszym sposobem na zwiększenie wydajności byłoby użycie języków, w których jedna pojedyncza linia kodu zrobiła więcej, i faktycznie działa to, przynajmniej w przypadku języków o złożoności, takich jak FORTRAN i COBOL, lub dać bardziej nowoczesny przykład C.

David Thornley
źródło
2

Przenośność zawsze stanowi problem - jeśli nie teraz, przynajmniej w końcu. Branża programistyczna każdego roku wydaje miliardy na przenoszenie starego oprogramowania, które w momencie jego napisania nie miało „oczywiście” żadnego problemu z przenośnością.

Thomas Pornin
źródło
2
„Nie będzie musiał przenosić się na inną architekturę” brzmi dla mnie bardzo podobnie: „Nie będzie potrzebował więcej niż dwóch cyfr na rok”.
David Thornley,
Czy nie możemy użyć C #, ponieważ Windows może nie być w przyszłym roku?
Martin Beckett
Np. Komputery Apple MacIntosh oparte na procesorach Motorola MC68000, PowerPC (IBM i in.), A teraz procesory Intel x86 (IA-32 (e)). Więc tak, przenośność jest problemem dla każdego używanego systemu wystarczająco długo, a każdy programista, który nie ugryzł się w swój kod trwający dłużej niż oczekiwano, nie jest jeszcze doświadczony.
mctylr
@Martin: Za dwadzieścia lat będzie wiele programów w języku C #, które ludzie chcą uruchamiać, więc będzie sposób na kompilowanie i uruchamianie programów w języku C #. Nic nie jest z natury ustalone w C #, chociaż za dwadzieścia lat byłbym zaskoczony, gdyby był on tak popularny jak obecnie. Jednak za dwadzieścia lat nasze procesory będą się znacznie różnić. Program asemblera napisany w 1990 roku może dziś dobrze działać, ale na pewno nie będzie optymalny i będzie działał wolniej niż skompilowany C.
David Thornley
Właśnie to miałem na myśli - mam o wiele więcej problemów z przenoszeniem, ponieważ struktura wysokiego poziomu zmieniła się od 6 miesięcy temu niż ja, ponieważ zmieniły się instrukcje w x86 - zwłaszcza, że ​​ręcznie kodowany asm zwykle trzyma się najprostszych metod.
Martin Beckett
2

Nastąpił błędny cykl, gdy asembler stał się mniej powszechny: w miarę dojrzewania języków wyższego poziomu zestawy instrukcji asemblera budowano mniej dla wygody programisty, a bardziej dla wygody kompilatorów.

Więc teraz, realistycznie, może być bardzo trudno podjąć właściwe decyzje, powiedzmy, które rejestry powinieneś użyć lub które instrukcje są nieco bardziej wydajne. Kompilatory mogą korzystać z heurystyki, aby dowiedzieć się, które kompromisy mogą przynieść najlepsze korzyści. Prawdopodobnie możemy przemyśleć mniejsze problemy i znaleźć lokalne optymalizacje, które mogłyby pokonać nasze dość wyrafinowane kompilatory, ale są szanse, że w przeciętnym przypadku dobry kompilator wykona lepszą robotę przy pierwszej próbie, niż prawdopodobnie dobry programista. W końcu, podobnie jak John Henry, możemy pokonać maszynę, ale możemy poważnie wypalić się, gdy tam dotrzemy.

Nasze problemy są teraz zupełnie inne. W 1986 roku próbowałem wymyślić, jak uzyskać nieco większą prędkość w małych programach, które wymagały umieszczenia kilkuset pikseli na ekranie; Chciałem, aby animacja była mniej gwałtowna. Sprawiedliwa sprawa dla języka asemblera. Teraz próbuję wymyślić, jak reprezentować abstrakcje wokół języka kontraktów i polityki obsługi hipotek, i wolałbym przeczytać coś, co przypomina język, którym mówią biznesmeni. W przeciwieństwie do makr LISP, makra asemblera nie egzekwują zbyt wiele reguł, więc nawet jeśli możesz uzyskać coś dość zbliżonego do DSL w dobrym asemblerze, będzie on podatny na wszelkiego rodzaju dziwactwa, które wygrały ” powodują problemy, jeśli napisałem ten sam kod w Ruby, Boo, Lisp, C # lub nawet F #.

Jeśli twoje problemy są łatwe do wyrażenia za pomocą wydajnego języka asemblera, masz więcej mocy.

JasonTrue
źródło
2

To samo dotyczy większości tego, co powiedzieli inni.

W dawnych dobrych czasach przed wynalezieniem C, gdy jedynymi językami wysokiego poziomu były takie rzeczy jak COBOL i FORTRAN, było wiele rzeczy, których po prostu nie można było zrobić bez uciekania się do asemblera. To był jedyny sposób na uzyskanie pełnej elastyczności, dostęp do wszystkich urządzeń itp. Ale wtedy wynaleziono C, a prawie wszystko, co było możliwe w montażu, było możliwe w C. Napisałem bardzo niewiele zestawień od czasu następnie.

To powiedziawszy, myślę, że jest to bardzo przydatne ćwiczenie dla nowych programistów, aby nauczyć się pisać w asemblerze. Nie dlatego, że w rzeczywistości dużo by to wykorzystali, ale dlatego, że wtedy rozumiesz, co naprawdę dzieje się w komputerze. Widziałem wiele błędów programistycznych i nieefektywnego kodu od programistów, którzy wyraźnie nie mają pojęcia, co tak naprawdę dzieje się z bitami, bajtami i rejestrami.

Sójka
źródło
Tak, natychmiast. Fortran Disk and Tape I / O na komputerach mainframe IBM wiele lat temu był prawie bezużyteczny, więc napisaliśmy własne procedury we / wy w 370 / Assembler i nazwaliśmy je kodem Fortan IV. A pisanie kodu asemblera pozwoliło mi naprawdę zrozumieć podstawową architekturę. Nie napisałem żadnego kodu asemblera od kilku lat i wszyscy młodsi ludzie, z którymi pracuję, nigdy go nie napisali - ale szkoda, że ​​nie, jest to bardzo pouczające.
Simon Knights
2

Od około miesiąca programuję w asemblerze. Często piszę fragment kodu w C, a następnie kompiluję go w asemblerze, aby mi pomóc. Być może nie wykorzystuję pełnej mocy optymalizacyjnej kompilatora C, ale wygląda na to, że moje źródło C asm zawiera niepotrzebne operacje. Zaczynam więc rozumieć, że mówienie o dobrym kompilatorze C przewyższającym dobrego kodera asemblera nie zawsze jest prawdziwe.

W każdym razie moje programy asemblacyjne są tak szybkie. Im częściej używam asemblera, tym mniej czasu zajmuje mi napisanie kodu, ponieważ tak naprawdę nie jest to takie trudne. Również komentarz dotyczący złej czytelności zestawu nie jest prawdziwy. Jeśli odpowiednio oznaczysz swoje programy i skomentujesz, gdy zajdzie potrzeba dodatkowego opracowania, wszystko powinno być gotowe. W rzeczywistości sposób montażu jest dla programisty bardziej przejrzysty, ponieważ widzą, co dzieje się na poziomie procesora. Nie wiem o innych programistach, ale dla mnie wolę wiedzieć, co się dzieje, niż rzeczy w rodzaju czarnej skrzynki.

Biorąc to pod uwagę, prawdziwą zaletą kompilatorów jest to, że kompilator może zrozumieć wzorce i relacje, a następnie automatycznie kodować je w odpowiednich lokalizacjach w źródle. Jednym z popularnych przykładów są funkcje wirtualne w C ++, które wymagają kompilatora do optymalnego mapowania wskaźników funkcji. Jednak kompilator ogranicza się do robienia tego, na co pozwala twórca kompilatora. Prowadzi to do tego, że programiści czasami muszą uciekać się do robienia dziwnych rzeczy ze swoim kodem, co wydłuża czas kodowania, kiedy można było to zrobić trywialnie przy montażu.

Osobiście uważam, że rynek mocno obsługuje języki wysokiego poziomu. Gdyby język asemblera był jedynym językiem, jaki istnieje obecnie, to byłoby o 70% mniej ludzi programujących i kto wie, gdzie byłby nasz świat, prawdopodobnie w latach 90-tych. Języki wyższego poziomu przemawiają do szerszego grona osób. Umożliwia to większą podaż programistów do budowy potrzebnej infrastruktury naszego świata. Kraje rozwijające się, takie jak Chiny i Indie, w dużym stopniu korzystają z języków takich jak Java. Kraje te szybko rozwiną infrastrukturę IT, a ludzie staną się bardziej połączeni. Chodzi mi o to, że języki wysokiego poziomu są popularne nie dlatego, że produkują doskonały kod, ale dlatego, że pomagają zaspokoić popyt na rynkach światowych.

użytkownik922475
źródło
+1 za czarną skrzynkę. Tak, używamy czarnych skrzynek i nie ma sposobu, aby zajrzeć do nich (zbyt łatwe). Jak naprawdę działa foreach C # ? Kto wie. Microsoft powiedział, że jest idealny. To musi być.
ern0
Nie zapominaj też, że wraz z „językiem wysokiego poziomu” pojawia się wiele innych rzeczy, które mają znaczenie w prawdziwym świecie. C jest dostarczany ze standardowymi bibliotekami (matematyka, przetwarzanie ciągów, operacje we / wy itp.), A następnie duże wagi, takie jak Java, są dostarczane z mnóstwem innych pakietów i bibliotek do połączeń, przetwarzania obrazów, przetwarzania danych, tworzenia stron internetowych itp. To pytanie wykorzystania czasu na skupienie się na uzyskaniu 1 szczegółowego zadania o wysokiej wydajności na jednej platformie (a tym samym na montażu) w porównaniu do spędzania tego samego czasu na uzyskiwaniu znacznie większego zadania na wielu platformach przy minimalnej liczbie błędów.
jbx
1

W tej chwili uczę się asemblerowego w comp org i chociaż jest to interesujące, jest również bardzo nieefektywne, aby pisać. Musisz mieć dużo więcej szczegółów w głowie, aby wszystko działało, a także wolniej pisać te same rzeczy . Na przykład prosta 6-wierszowa pętla w C ++ może równać się 18 wierszom lub więcej asemblacji.

Osobiście bardzo fajnie jest uczyć się, jak rzeczy działają na poziomie sprzętowym, i daje mi większe uznanie dla działania komputera.

Jason
źródło
1

To, co C ma nad dobrym asemblerem makr, to język C. Sprawdzanie typu. Konstrukcje pętli. Automatyczne zarządzanie stosami. (Prawie) automatyczne zarządzanie zmiennymi. Dynamiczne techniki pamięci w asemblerze są ogromnym bólem w tyłek. Prawidłowe wykonanie listy połączonej jest przerażające w porównaniu do C lub jeszcze lepiej listy foo.insert (). I debugowanie - cóż, nie ma konkurencji o to, co jest łatwiejsze do debugowania. HLL wygrywają tam rozdania.

Zakodowałem prawie połowę swojej kariery w asemblerze, co bardzo ułatwia mi myślenie w assmebler. pomaga mi zobaczyć, co robi kompilator C, co ponownie pomaga mi pisać kod, który kompilator C może skutecznie obsługiwać. Dobrze przemyślana procedura napisana w C może zostać napisana w celu uzyskania dokładnie tego, czego chcesz w asemblerze przy odrobinie pracy - i jest przenośna! Musiałem już przepisać kilka starszych procedur asm z powrotem do C z powodów wieloplatformowych i to nie jest zabawne.

Nie, pozostanę przy C i poradzę sobie ze sporadycznym niewielkim spowolnieniem wydajności w stosunku do czasu produktywności, który zyskuję dzięki HLL.

Michael Dorgan
źródło
1

Mogę tylko odpowiedzieć na pytanie, dlaczego osobiście nie piszę programów w asemblerze, a głównym powodem jest to, że jest to bardziej nużące . Uważam też, że łatwiej jest subtelnie coś popsuć bez natychmiastowego zauważenia. Na przykład możesz zmienić sposób korzystania z rejestru w jednej procedurze, ale zapomnij zmienić go w jednym miejscu. Złoży się dobrze i możesz zauważyć dopiero później.

To powiedziawszy, myślę, że nadal istnieją prawidłowe zastosowania do montażu. Na przykład mam wiele całkiem zoptymalizowanych procedur montażu do przetwarzania dużych ilości danych, korzystania z SIMD i podążania za paranoicznym podejściem „każdy bit jest święty” [cytuj V.Stob]. (Należy jednak pamiętać, że naiwne implementacje asemblacji są często znacznie gorsze niż to, co wygenerowałby dla ciebie kompilator).

PhiS
źródło
1

C to asembler makr! I to jest najlepsze!

Może zrobić prawie wszystko, co potrafi montaż, może być przenośny, aw większości rzadkich przypadków, w których nie może zrobić czegoś, co można nadal użyć wbudowanego kodu asemblera. Pozostawia to tylko niewielką część programów, które absolutnie musisz napisać w asemblerze, i tylko w asemblerze.

A abstrakcje na wyższym poziomie i przenośność sprawiają, że dla większości ludzi pisanie oprogramowania systemowego w C. jest bardziej opłacalne. I chociaż przenośność może nie być potrzebna teraz, jeśli zainwestujesz dużo czasu i pieniędzy w pisanie jakiegoś programu, możesz nie chcieć się ograniczać do czego będziesz mógł go używać w przyszłości.

ahe
źródło
1

Wydaje się, że ludzie zapominają, że jest też inny kierunek.

Dlaczego przede wszystkim piszesz w asemblerze? Dlaczego nie napisać programu w naprawdę niskim języku?

Zamiast

mov eax, 0x123
add eax, 0x456
push eax
call printInt

równie dobrze możesz pisać

B823010000
0556040000
50 
FF15.....

Ma to tak wiele zalet, że znasz dokładny rozmiar swojego programu, możesz ponownie użyć wartości instrukcji jako danych wejściowych dla innych instrukcji i nie potrzebujesz nawet asemblera do napisania, możesz użyć dowolnego edytora tekstu ...

Powodem, dla którego nadal wolisz Asembler, jest powód, dla którego inni ludzie wolą C ...

BeniBela
źródło
0

Ponieważ zawsze tak jest: czas mija i dobre rzeczy też przemijają :(

Ale kiedy piszesz kod asm, to jest zupełnie inne uczucie niż kiedy piszesz języki wysokiego poziomu, chociaż wiesz, że jest to o wiele mniej produktywne. To tak, jakbyś był malarzem: możesz narysować wszystko, co ci się podoba, tak jak lubisz, bez żadnych ograniczeń (cóż, tylko dzięki funkcjom procesora) ... Dlatego to uwielbiam. Szkoda, że ​​ten język odchodzi. Ale dopóki ktoś go pamięta i koduje, nigdy nie umrze!

edk
źródło
Prawdziwe. Z drugiej strony odczuwa się upokorzenie, gdy kasjer i supermarket odmawiają wypłaty czeku, pogardliwie mówiąc: „Och, programujesz w języku NISKIEGO POZIOMU”.
Jay
0

$$$

Firma zatrudnia programistę, który pomaga przekształcić kod w $$$. Im szybciej można wytworzyć użyteczny kod, tym szybciej firma może przekształcić ten kod w $$$.

Języki wyższego poziomu są na ogół lepsze w generowaniu większych ilości przydatnego kodu. Nie oznacza to, że zgromadzenie nie ma swojego miejsca, ponieważ są czasy i miejsca, w których nic więcej nie będzie robić.

iskrzący
źródło
0

Zaleta HLL jest jeszcze większa, gdy porównasz asembler z językiem wyższego poziomu niż C, np. Java, Python lub Ruby. Na przykład te języki mają funkcję wyrzucania elementów bezużytecznych: nie trzeba się martwić, kiedy zwolnić część pamięci, ani nie ma wycieków pamięci ani błędów z powodu zbyt wczesnego zwolnienia.

użytkownik4660402
źródło
0

Jak wspomniano wcześniej, powodem istnienia każdego narzędzia jest skuteczność jego działania. Ponieważ HLL mogą wykonywać te same zadania, co wiele wierszy kodu asm, wydaje się naturalne, że asemblowanie jest zastępowane przez inne języki. A dla bliskiego sprzętowi majstrowania - jest wbudowany montaż w C i innych wariantach według języka. Dr Paul Carter in mówi w PC Assembly Language

„... lepsze zrozumienie tego, jak komputery naprawdę działają na niższym poziomie niż w językach programowania, takich jak Pascal. Poprzez lepsze zrozumienie działania komputerów, czytelnik może często być znacznie bardziej produktywny, opracowując oprogramowanie w językach wyższego poziomu, takich jak C i C ++. Nauka programowania w asemblerze jest doskonałym sposobem na osiągnięcie tego celu. ”

Mamy wstęp do montażu na moich kursach uniwersyteckich. Pomoże to wyczyścić koncepcje. Jednak wątpię, czy ktokolwiek z nas napisałby 90% kodu w asemblerze. Jak ważna jest dzisiaj dogłębna wiedza na temat montażu?

AruniRC
źródło
-2

Przeglądając te odpowiedzi, założę się, że 9/10 respondentów nigdy nie pracowało przy montażu.

Jest to odwieczne pytanie, które pojawia się tak często i dostajesz te same, w większości błędne odpowiedzi. Gdyby nie przenośność, sam bym wszystko zrobił. Nawet wtedy koduję w C prawie tak samo jak w asemblerze.

Obrabować
źródło
1
+1 za wzmiankę o ludziach bez doświadczenia w asm, a kolejne +1 za „kodowanie w C jak asm”. Kiedy piszę aplikacje C ++ (tak, CPP, nie C) dla osadzonych, koduję tak, jakby to było asm, np. W ogóle nie używam nowego / malloc ().
ern0
Używasz więc wielu rzeczy, takich jak char buf [MAX_PATH], które następnie przewracają się, gdy ktoś ma dane o rozmiarze MAX_PATH + n? ;)
paulm
1
@paulm - Masz na myśli tak jak C?
Rob
1
Mam nadzieję, że autorzy asemblera nie unikną użycia malloc (). Tak, po osadzeniu masz ograniczoną pamięć. Ale zrób to na Unixie lub innym komputerze (lub nawet większości mobilnych systemów operacyjnych), a niepotrzebnie ograniczasz siebie i swoich użytkowników. Ponadto: im mniej LOC piszesz, tym mniejsza szansa na pomyłkę, co oznacza, że ​​kod wyższego poziomu może zawierać mniej błędów niż mniej.
uliwitness
1
Właśnie spojrzałem, ponieważ byłem podejrzliwy i tak, z pewnością mogę powiedzieć, że redditors i HNers są tutaj.
Rob