Nauczyłem się z książki Kipa Irvine'a . Jeśli zignorujesz (uczciwą) krytykę jego (nieistotnych) bibliotek, mogę polecić go jako dobre wprowadzenie do samego języka - chociaż dla naprawdę interesujących rzeczy musisz polować na obsesje w sieci.
Myślę, że warto zrozumieć, co dzieje się na niższych poziomach. Podczas badania asemblera dowiesz się o tworzeniu potoków procesora, przewidywaniu gałęzi, wyrównaniu pamięci podręcznej, SIMD, zmianie kolejności instrukcji i tak dalej. Znajomość tych elementów pomoże Ci napisać lepszy kod wysokiego poziomu.
Ponadto, konwencjonalna opinia jest taka, aby przez większość czasu nie próbować ręcznie optymalizować asemblacji, ale pozwolić kompilatorowi się tym martwić. Kiedy zobaczysz przykłady pokręconych rzeczy, które generują kompilatory, lepiej zrozumiesz, dlaczego konwencjonalna mądrość się utrzymuje.
Przykład: LFSR działa szybko z instrukcją rotate-with-carry, w szczególnych przypadkach, takich jak ten, tak łatwo jest napisać wersję asemblera, jak odkryć, czy kompilator jest wystarczająco inteligentny, aby to rozgryźć. Czasami po prostu wiesz coś , czego nie ma kompilator.
Zwiększa również zrozumienie kwestii bezpieczeństwa - zapisu lub wykonania, przepełnienia stosu itp.
Niektóre problemy ze współbieżnością stają się widoczne tylko wtedy, gdy wiesz, co dzieje się na poziomie instrukcji.
Może to być przydatne czasami podczas debugowania, jeśli nie masz pełnego kodu źródłowego.
Jest wartość ciekawości. W jaki sposób realizowane są funkcje wirtualne? Czy kiedykolwiek próbowałeś pisać programy DirectX lub COM w asemblerze? W jaki sposób zwracane są duże struktury, czy funkcja wywołująca oferuje dla nich miejsce lub odwrotnie?
Są też specjalne języki asemblera dla sprzętu graficznego, chociaż języki shaderów osiągnęły wysoki poziom kilka lat temu, wszystko, co pozwala myśleć o problemie w inny sposób, jest dobre.