Czy powinienem próbować ćwiczyć problemy w montażu? [Zamknięte]


9

Patrzyłem na Project Euler Problem 48 :

Seria, 1 1 + 2 2 + 3 3 + ... + 10 10 = 10405071317.

Znajdź ostatnie dziesięć cyfr serii, 1 1 + 2 2 + 3 3 + ... + 1000 1000 .

W Pythonie mogę to zrobić za pomocą jednej linii:

sum((x**x for x in xrange(1,1001))

Ale odpowiednikiem tego montażu byłoby 100 linii i prawdziwe wyzwanie.

Czy powinienem robić niektóre z tych łamigłówek w asemblerze, aby uzyskać wgląd w programowanie na niskim poziomie i zrozumieć, jak naprawdę działa komputer?


2
Jeśli nie wiesz, jak działa pamięć, jak możesz oczekiwać, że poradzisz sobie z takimi tematami, jak wskaźniki? Jeśli nie rozumiesz, jak działa komputer i system operacyjny, jak możesz zaprogramować aplikację?
Ramhound

Potrafię zrobić wiele abstrakcji Ramhound, dlatego o to prosiłem. Może nie uda mi się uzyskać pełnego zawieszenia wskaźników, które nadal są w stanie zrobić coś we wskaźnikach, takich jak zamiana, co ma logiczny sens, gdy przyjmiesz, że wskaźniki przechowują pamięć w innym typie danych. Znowu Ramhound, ponieważ zasugerowałeś, że powinienem zrozumieć te rzeczy, możesz zasugerować tematy, które powinienem przeczytać? Język asemblera i trochę COA byłyby dobre?
Nishant,

Jeśli nie zrozumiesz wszystkich wskaźników, okaże się, że w niektórych miejscach będzie to poważna wada.
David Thornley,

3
Albo twoja linia Pythona oblicza x ^ 2 dla x w 1..1000 (zamiast x ^ x dla x w 1..1000) lub python jest jeszcze bardziej magiczny niż myślałem. :)
Ingo

Czy funkcja „podniesienia potęgi” *w Pythonie?

Odpowiedzi:


1

Poza nauką asemblerową uważam, że nauka o kompilacji języka niskiego poziomu, takiego jak C, jest bardzo cenna. Więc moja odpowiedź brzmi tak, ale z drugiej strony jestem prawdopodobnie stronniczy, ponieważ lubię programować na niskim poziomie.

Na przykład po prostu zrozumienie, jak kompilowane są proste instrukcje. Następująca funkcja

int func(int val)
{
  int num = val * 5;
  return num;
}

... staje się (co najmniej interesujące):

movl    %edi, -20(%rbp)
movl    -20(%rbp), %edx
movl    %edx, %eax
sall    $2, %eax
addl    %edx, %eax

Ten kod pobiera argument ze stosu (val, parametr do func), przesuwa go w lewo o 2 miejsca (pomnóż przez 2 ^ 2 lub 4), a następnie dodaje oryginalną wartość do wyniku. Końcowym wynikiem jest pomnożenie przez 5. Przykład taki ilustruje wiele rzeczy, o których należy pamiętać, takich jak optymalizacje kompilatora. Zamiast wywoływać instrukcję do bezpośredniego pomnożenia przez 5, przesuwa dwa miejsca do pomnożenia przez 4, a następnie dodaje oryginalną wartość. Znalazłem takie przykłady, aby znacznie poprawić moje rozumienie rzeczy na niższym poziomie.

Wygeneruj wyjście asemblera z gcc z -Sopcją. Należy jednak pamiętać, że wyniki będą się różnić w zależności od kompilatora i poziomu optymalizacji.

W każdym razie nie sądzę , że bycie programistą w asemblerze jest tym samym, co rozumienie asemblera . Ponownie czuję, że programowanie w języku takim jak C i wiedza o tym, jak można go wprowadzić do kodu maszynowego, jest cenną praktyką.


11

Prawdopodobnie nie jest to konieczne, aby móc napisać asembler (z których większość zawiera szczegóły dotyczące inicjalizacji i konwencji wywoływania dla twojego systemu).

Warto to zrozumieć, na wypadek, gdybyś próbował debugować coś bez źródła.

ALE zdecydowanie warto zrozumieć maszynę przynajmniej na poziomie „C” i wskaźników (zasadniczo asemblera wysokiego poziomu), abyś wiedział, dlaczego sumowanie miliona razy w pętli jest złe.


W rzeczywistości niektóre względnie sprytne implementacje mogą sprawić, że for i in range(1000000): s = s + '.'nie będzie (t dużo) gorsze niż „zoptymalizowane” wersje, których ponownie użyję s. Podobnie, kilka innych zmian unieważnia to, co jest rozsądnym założeniem ze znajomością języka C i założeniem naiwnej implementacji. Ale ogólnie jest to bardziej przydatne niż szkodliwe. Pamiętaj tylko, że implementacje językowe są czasem mądrzejsze od ciebie;)

2
@ delnan-Potrzebowałem tylko krótkiego przykładu, w którym coś, co wygląda nieszkodliwie w Javie / C #, może być bardzo drogie na krzemie. W szczególności spotkałem wiele osób, które uważają, że przydzielanie dużej ilości pamięci i kopiowanie jest natychmiastowe.
Martin Beckett

Nienawidzę wierzyć, że delnan :-)
Nishant,

5

Dobre pytanie. Nauka montażu jest zdecydowanie dobra i warta wysiłku.

  1. Takie zrozumienie na niskim poziomie będzie przydatne w tworzeniu oprogramowania wbudowanego
  2. Refaktoryzacja na niskim poziomie
  3. Pomoże ci to w efektywnym wykorzystaniu debuggera
  4. Poznasz rozłożony kod, aby pomóc w takich sprawach, jak jaskinie kodowe

2
Musiałem poszukać kodeków. Często ich używam, ale teraz nazywamy je „Objazdami”. research.microsoft.com/en-us/projects/detours
ProdigySim

1

Tak i nie.

To prawda, że ​​pozwoli ci lepiej zrozumieć, co robi Twój kod i dlaczego niektóre rzeczy są po prostu złym pomysłem, musisz pomyśleć o tym wysiłku.

Nauka asemblera nie jest weekendowym projektem, zajmie ci dużo czasu i musisz pomyśleć, czy ten czas można lepiej spędzić.

Jeśli nie jesteś w zoptymalizowanym kodzie, prawdopodobnie nigdy nie zobaczysz korzyści równych włożonemu wysiłkowi.


1

Zrobiłem dużo asemblera, kiedy byłem młodszy i nie sądzę, żeby pomogło to zrozumieć cokolwiek poza asemblerem. Jeśli spojrzysz na nowoczesny asembler, to i tak wszystko jest w języku makro. Zwykle nie znoszę analogii, ale i tak tu jest: czy wiedza o tym, jak działa silnik samochodu, czyni cię lepszym kierowcą?


Czy wiedza o tym, jak działa silnik samochodu, czyni cię lepszym kierowcą? Nie, ale czyni cię lepszym właścicielem samochodu, ponieważ jeśli silnik się zepsuje, możesz to naprawić.
Cameron Martin

Zgadzam się, ale to nie czyni cię lepszym sterownikiem, co jest analogią, której używałem. Naprawiając silnik samodzielnie, nie wspierasz szeroko pojętej gospodarki, stosując mechanikę ... Analogie są ograniczone. Zasadniczo nigdy nie zniechęcam kogoś do szukania czegoś, jeśli jest zainteresowany, ale myślę, że musisz zejść głęboko w dół króliczej nory, aby móc zastosować to z powodzeniem w językach wyższego poziomu. Na początek musisz zrozumieć optymalizacje kompilacji używane przez konkretny język, jeśli jest on skompilowany, interpreter lub jitter. To ogromny obszar.
Ian

1

Sposób, w jaki pracowałem nad zrozumieniem asemblera, polega na pisaniu programów w językach wyższego poziomu, a następnie zastępowaniu części (przynajmniej mam nadzieję) funkcjonalnie równoważnymi fragmentami złożonego kodu. Oznacza to, że mogę używać HLL do tego, co są dobre do organizowania i rozwiązywania problemów na wysokim poziomie - i używam asm do walenia metalu.

(Kiedy mówię o tym, że program hosta jest napisany w HLL, mam na myśli C lub ObjC, gdy próbuję nauczyć się asm x86_64, i BASIC, gdy pracuję na asm Z80, 6502 i 6809).

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.