Dlaczego tajemnicze krótkie identyfikatory są nadal tak powszechne w programowaniu niskiego poziomu?


64

Kiedyś bardzo ważne były krótkie nazwy instrukcji / rejestru. Te powody już nie obowiązują, ale krótkie tajemnicze nazwy są nadal bardzo powszechne w programowaniu niskiego poziomu.

Dlaczego to? Czy tylko dlatego, że stare nawyki trudno przełamać, czy są lepsze powody?

Na przykład:

  • Atmel ATMEGA32U2 (2010): TIFR1(zamiast TimerCounter1InterruptFlag), ICR1H(zamiast InputCapture1High), DDRB(zamiast DataDirectionPortB), etc.
  • Zestaw instrukcji .NET CLR (2002): bge.s(zamiast branch-if-greater-or-equal.short) itp.

Czy dłuższe, nieszyfrowane nazwy nie są łatwiejsze w obsłudze?


Odpowiadając i głosując, weź pod uwagę następujące kwestie. Wiele sugerowanych tutaj możliwych wyjaśnień odnosi się w równym stopniu do programowania na wysokim poziomie, a jednak ogólnie rzecz biorąc konsensus polega na użyciu nieszyfrowych nazw składających się ze słowa lub dwóch (z wyłączeniem powszechnie rozumianych akronimów).

Ponadto, jeśli twój główny argument dotyczy fizycznej przestrzeni na papierowym diagramie , należy wziąć pod uwagę, że absolutnie nie dotyczy to asemblera lub CIL, a ponadto byłbym wdzięczny, jeśli pokażesz mi diagram, w którym krótkie nazwy pasują, ale czytelne, pogarszają diagram . Z osobistego doświadczenia w bezkonkurencyjnej firmie zajmującej się półprzewodnikami, czytelne nazwy pasują dobrze i dają czytelniejsze diagramy.

Jaka jest podstawowa rzecz, która różni się w programowaniu niskiego poziomu w porównaniu do języków wysokiego poziomu, co sprawia, że ​​zwięzłe, tajemnicze nazwy są pożądane w programowaniu niskiego poziomu, ale nie w programach wysokiego poziomu?


82
Odpowiedź: Aby mieć wrażenie, że programujesz w języku niskiego poziomu.
Thomas Eding,

5
Cryptic jest względny. JSRjest trzy razy dłuższy niż reprezentowany przez niego kod operacji ( $20w 6502) i znacznie łatwiejszy do zrozumienia na pierwszy rzut oka.
Blrfl

4
Jestem trochę rozczarowany, ponieważ jest tam poprawna odpowiedź, ale zdecydowanie nie jest to odpowiedź zaakceptowana. W przypadku schematów obwodów i takich przerwań są zwykle nazywane liniami, z którymi są skojarzone, a na schemacie obwodów nie chcesz pełnych informacji, nie jest to dobra praktyka ani praktyczne. Po drugie, ponieważ nie lubisz odpowiedzi, nie oznacza to, że są one nieprawidłowe.
Jeff Langemeier

4
@gnat: Spróbuj set Accumulator32 to BaseIndex32? Po prostu rozszerzenie tradycyjnych skrótów nie jest jedynym sposobem na uczynienie czegoś bardziej czytelnym.
Timwi

1
„jeśli twoim głównym argumentem jest fizyczna przestrzeń na papierowym schemacie”, nie chodzi o to, że dobre nazywanie bierze pod uwagę inne rzeczy niż tylko jasność nazwy (podałem kilka w mojej odpowiedzi, schematy - w tym te narysowane na tablica - to tylko jedna z tych innych rzeczy) i to wyjaśnienie jest względne (znajomość zazwyczaj pomaga w jasności niezależnie od wyboru).
AProgrammer

Odpowiedzi:


106

Oprogramowanie korzysta z tych nazw, ponieważ arkusze danych używają tych nazw. Ponieważ kod na tym poziomie jest bardzo trudny do zrozumienia bez arkusza danych, tworzenie nazw zmiennych, których nie można wyszukiwać, jest wyjątkowo nieprzydatne.

To rodzi pytanie, dlaczego arkusze danych używają krótkich nazw. Prawdopodobnie dlatego, że często musisz przedstawiać nazwy w tabelach takich jak ta, w których nie ma miejsca na identyfikatory o długości 25 znaków:

Tabela TIFR1 z arkusza danych

Ponadto, takie jak schematy, schematy pinów i sitodruki PCB często są bardzo ciasne dla przestrzeni.


7
Ponadto, ta odpowiedź tak naprawdę nie odnosi się do strony czysto programowej, np. CLR, JVM, x86 itp. :)
Timwi

12
@romkyns: Jest nieco bardziej oczywiste, dlaczego używali tych krótkich nazw, kiedy faktycznie czytali te arkusze danych. Arkusze danych dla mikrokontrolera, który mam pod ręką, to około 500 stron, nawet jeśli używam krótkich nazw w całym tekście . Szerokość tabel obejmowałaby kilka stron / ekranów, gdybyśmy użyli dłuższych nazw, co czyni je bardzo niewygodnymi w użyciu odniesienia.
In silico

27
@romkyns: Dłuższe nazwy można wyszukiwać w jednakowy sposób, ale są one „nienatywne”. Jeśli słuchasz inżynierów osadzonych, mówią oni „tiffer zero”, a nie „flaga przerwania timera zero”. Wątpię, czy programiści WWW rozszerzają HTTP, HTML lub JSON w nazwach metod.
TMN

6
@KarlBielefeldt er, co? :) Oczywiście nie znajdę go w bieżącym arkuszu danych, ponieważ zamiast tego wybrali krótką nazwę. To nie potwierdza twierdzenia, że ​​krótkich nazw można wyszukiwać w najmniejszym stopniu ...
Roman Starkov

5
Nie tylko arkusze danych są ograniczone przestrzenią, to schematy. Wszystkie te logiczne komponenty mają wyprowadzenia, które należy połączyć z innymi komponentami. „TimerCounter1InteruptFlag.clear” nie pasuje równie dobrze do niewielkiej reprezentacji drutu „TCIF.C”
AShelly

60

Prawo Zipfa

Patrząc na ten tekst, możesz sam zaobserwować, że długość słowa i częstotliwość użycia są na ogół odwrotnie powiązane. Słowa, które są używane bardzo często, jak it, a, but, you, i andsą bardzo krótkie, a słowa, które są rzadziej używane podoba observe, comprehensioni verbositysą dłuższe. Ten zaobserwowany związek między częstotliwością a długością nazywa się prawem Zipfa .

Liczba instrukcji w zestawie instrukcji dla danego mikroprocesora zwykle jest liczona w dziesiątkach lub setkach. Na przykład zestaw instrukcji Atmel AVR wydaje się zawierać około stu różnych instrukcji (nie liczyłem), ale wiele z nich jest odmianą wspólnego tematu i ma bardzo podobne mnemoniki. Na przykład instrukcje mnożenia obejmują MUL, MULS, MULSU, FMUL, FMULS i FMULSU. Nie musisz długo patrzeć na listę instrukcji, zanim zrozumiesz, że instrukcje rozpoczynające się od „BR” to rozgałęzienia, instrukcje rozpoczynające się od „LD” to obciążenia itp. To samo dotyczy zmiennych: nawet skomplikowane procesory zapewniają tylko ograniczoną liczbę miejsc do przechowywania wartości: rejestry stanu, rejestry ogólnego przeznaczenia itp.

Ponieważ instrukcji jest tak mało, a długie nazwy wymagają więcej czasu, warto nadać im krótkie nazwy. Z kolei języki wyższego poziomu pozwalają programistom tworzyć ogromną liczbę funkcji, metod, klas, zmiennych i tak dalej. Każda z nich będzie używana znacznie rzadziej niż większość instrukcji asemblacyjnych, a dłuższe, bardziej opisowe nazwy są coraz ważniejsze, aby dać czytelnikom (i pisarzom) wystarczającą ilość informacji, aby zrozumieć, czym są i co robią.

Ponadto zestawy instrukcji dla różnych procesorów często używają podobnych nazw dla podobnych operacji. Większość zestawów instrukcji obejmuje operacje na ADD, MUL, SUB, LD, ST, BR, NOP, a jeśli nie używają tych dokładnych nazw, zwykle używają nazw bardzo bliskich. Gdy nauczysz się mnemoniki dla jednego zestawu instrukcji, dostosowanie się do zestawów instrukcji dla innych urządzeń nie trwa długo. Więc może się wydawać, że nazwy „tajemnicze” do ciebie są tak znajome jak słowa takie jak and, ori notdla programistów, którzy są biegli w sztuce programowania niskiego poziomu. Myślę, że większość osób pracujących na poziomie asemblera powiedziałaby ci, że nauka czytania kodu nie jest jednym z większych wyzwań w programowaniu na niskim poziomie.


2
dzięki Caleb! Dla mnie ta doskonała odpowiedź uratowała pytanie, które w jakiś sposób udało się zebrać cztery oceny wartości w jednym tytule: „tajemniczy”, „krótki”, „wciąż”, „tak powszechny”
gnat

1
Dziękuję, @gnat, za komentarz i hojny bonus.
Caleb

37

Ogólnie

Jakość nazewnictwa to nie tylko posiadanie nazw opisowych, ale także inne aspekty, a to prowadzi do rekomendacji takich jak:

  • im bardziej globalny zakres, tym bardziej opisowa powinna być nazwa
  • im częściej jest używany, tym krótsza powinna być nazwa
  • ta sama nazwa powinna być używana we wszystkich kontekstach dla tej samej rzeczy
  • różne rzeczy powinny mieć różne nazwy, nawet jeśli kontekst jest inny
  • zmiany powinny być łatwo wykrywalne
  • ...

Pamiętaj, że te zalecenia są sprzeczne.

Instrukcja mnemoniki

Jako programista w asemblerze używanie short-branch-if-greater-or-equalfor bge.sdaje mi takie samo wrażenie, jak kiedy widzę, jako programista Algol SUBSTRACT THE-HORIZONTAL-COORDINATE-OF-THE-FIRST-POINT TO THE-HORIZONTAL-COORDINATE-OF-THE-SECOND-POINT GIVING THE-DIFFERENCES-OF-THE-COORDINATE-OF-THE-TWO-POINTSzamiast geometrii obliczeniowej dx := p2.x - p1.x. Po prostu nie mogę się zgodzić, że te pierwsze są bardziej czytelne w kontekście, na którym mi zależy.

Zarejestruj nazwy

Wybierz oficjalną nazwę z dokumentacji. Dokumentacja wybiera nazwę z projektu. Projekt wykorzystuje wiele formatów graficznych, w których długie nazwy nie są odpowiednie, a zespół projektowy będzie żył z tymi nazwami przez miesiące, jeśli nie lata. Z obu powodów nie będą używać „flagi Przerwania pierwszego licznika timera”, będą skracać ją w swoim schemacie, a także podczas mówienia. Wiedzą o tym i używają systematycznych skrótów, TIFR1aby zmniejszyć ryzyko pomyłki. Jednym z punktów jest to, że TIFR1nie jest to przypadkowy skrót, to wynik schematu nazewnictwa.


4
Czy TIFR1naprawdę jest lepszy schemat nazewnictwa niż ten InterruptFlag1, czy IptFlag1naprawdę musisz być krótki?
Timwi

4
@Timwi InterruptFlagi IptFlagsą lepsze niż IFw ten sam sposób EnumerableInterfacei ItfcEnumerablesą lepsze niż IEnumerable.
AProgrammer

@AProgrammer: Uważam twoją odpowiedź i twój komentarz za najlepszą i oznaczę ją jako zaakceptowaną, gdybym mógł. Ci, którzy uważają, że tylko ograniczenia fizyczne dyktują krótkie nazwy, są w błędzie. Ta dyskusja będzie dla Ciebie interesująca: 37signals.com/svn/posts/…
alpav

5
@alpav Czy zdajesz sobie sprawę, że twój link jest przeciwieństwem tego, co mówi ta odpowiedź? Jeśli w ogóle, to w pełni obsługuje InterruptFlag1ze względu na lepszą przejrzystość.
Roman Starkov

24

Oprócz powodów „starych nawyków”, starszy kod, który został napisany 30 lat temu i jest nadal w użyciu, jest bardzo powszechny. Pomimo tego, co myślą niektórzy mniej doświadczeni ludzie, refaktoryzacja tych systemów, aby wyglądały ładnie, wiąże się z bardzo wysokimi kosztami przy niewielkim zysku i nie jest opłacalna ekonomicznie.

Systemy osadzone, które są blisko sprzętu - i uzyskują dostęp do rejestrów, zwykle używają takich samych lub podobnych etykiet jak te używane w arkuszach danych sprzętu, z bardzo dobrych powodów. Jeśli rejestr nazywa się XYZZY1 w arkuszach danych sprzętu, sensowna jest, że zmienna reprezentująca go to XYZZY1, lub jeśli programista miał dobry dzień, RegXYZZY1.

Jeśli chodzi o to bge.s, jest podobny do asemblera - dla niewielu osób, które muszą to wiedzieć, dłuższe nazwy są mniej czytelne. Jeśli nie możesz się oderwać od siebie bge.si myślisz branch-if-greater-or-equal.short, że coś zmieni - grasz tylko CLR i nie wiesz o tym.

Innym powodem, dla którego zobaczysz krótkie nazwy zmiennych, jest szerokie rozpowszechnienie skrótów w domenie, na którą program jest kierowany.

Podsumowując - spodziewane są krótkie skrócone nazwy zmiennych odzwierciedlające wpływ zewnętrzny, takie jak normy branżowe i karty danych sprzętu. Krótkie skrócone nazwy zmiennych, które są wewnętrzne dla oprogramowania, są zwykle mniej pożądane.


Jeśli zrozumiałem argument, którego używasz do obrony „bge.s”, czy TIFR1jest bardziej czytelny dla tych, którzy go potrzebują TimerCounter1InterruptFlag, prawda?
Roman Starkov

2
@romkyns: Oczywiście - w tym przypadku mniej znaczy więcej .... W przeciwieństwie do CNTR, co może oznaczać „Licznik”, „Sterowanie”, „Nie można śledzić trasy” itp., T1FR1 Dokładnie zdefiniowane znaczenie.
mattnz

„Jeśli nie możesz zmusić się do obejrzenia bge.s i pomyślisz, że odgałęzienie, jeśli większy lub równy. Skrót zrobi różnicę - grasz tylko CLR i nie wiesz o tym.” Nie wiem o tym Rozumiem asembler x86 całkiem dobrze, ale za każdym razem, gdy piszę pętlę, muszę sprawdzić, co oznaczają wszystkie j?instrukcje . Posiadanie bardziej oczywistej nazwy instrukcji zdecydowanie by mi pomogło. Ale może jestem raczej wyjątkiem niż regułą. Mam problem z zapamiętaniem trywialnych szczegółów.
Cody Gray

11

Jest tutaj tak wiele różnych pomysłów. Nie mogę przyjąć żadnej z istniejących odpowiedzi jak na odpowiedź: po pierwsze, istnieje prawdopodobnie wiele czynników, które przyczyniają się do tego, a po drugie, nie może wiedzieć, który z nich jest najbardziej istotna.

Oto podsumowanie odpowiedzi zamieszczonych przez innych tutaj. Zamieszczam to jako CW i moim zamiarem jest ostatecznie oznaczenie go jako zaakceptowanego. Edytuj, jeśli coś przeoczyłem. Próbowałem przeformułować każdy pomysł, aby wyrazić go zwięźle, ale wyraźnie.

Dlaczego więc tajemnicze krótkie identyfikatory są tak powszechne w programowaniu niskiego poziomu?

  • Ponieważ wiele z nich jest wystarczająco powszechnych w danej domenie, aby uzasadnić bardzo krótką nazwę. Pogarsza to krzywą uczenia się, ale jest opłacalnym kompromisem, biorąc pod uwagę częstotliwość używania.
  • Ponieważ zwykle istnieje mały zestaw możliwości, które są naprawione (programista nie może dodać do zestawu).
  • Ponieważ czytelność jest kwestią nawyku i praktyki. branch-if-greater-than-or-equal.shortjest początkowo bardziej czytelny niż bge.s, ale z pewną praktyką sytuacja się odwraca.
  • Ponieważ często trzeba je pisać w całości ręcznie, ponieważ języki niskiego poziomu często nie są wyposażone w zaawansowane środowiska IDE, które mają dobre autouzupełnianie, lub klimatyzacja nie jest niezawodna.
  • Ponieważ czasem pożądane jest spakowanie dużej ilości informacji do identyfikatora, a czytelna nazwa byłaby nie do przyjęcia, nawet przy wysokich standardach.
  • Ponieważ tak historycznie wyglądały środowiska niskiego poziomu. Zerwanie z nałogiem wymaga świadomego wysiłku, grozi zirytowaniem tych, którzy lubili stare sposoby i muszą być uzasadnione jako wartościowe. Trzymanie się ustalonego sposobu jest „domyślne”.
  • Ponieważ wiele z nich pochodzi z innych źródeł, takich jak schematy i karty danych. Te z kolei podlegają ograniczeniom przestrzeni.
  • Ponieważ ludzie odpowiedzialni za nadawanie nazw rzeczom nigdy nawet nie brali pod uwagę czytelności, nie zdawali sobie sprawy, że stwarzają problem lub są leniwi.
  • Ponieważ w niektórych przypadkach nazwy stały się częścią protokołu wymiany danych, takiego jak użycie języka asemblera jako pośredniej reprezentacji niektórych kompilatorów.
  • Ponieważ ten styl jest natychmiast rozpoznawany jako niski poziom, a zatem wygląda fajnie dla maniaków.

Osobiście uważam, że niektóre z nich w rzeczywistości nie przyczyniają się do powodów, dla których nowo opracowany system wybrałby ten styl nazewnictwa, ale uważam, że błędem byłoby odfiltrowywanie niektórych pomysłów w odpowiedzi tego typu.


10

Wrzucę kapelusz w ten bałagan.

Konwencje i standardy kodowania wysokiego poziomu to nie to samo, co standardy i praktyki kodowania niskiego poziomu. Niestety większość z nich to pozostałości po starym kodzie i starych procesach myślowych.

Niektóre jednak służą celowi. Na pewno BranchGreaterThan byłby znacznie bardziej czytelny niż BGT , ale teraz istnieje konwencja, jest to instrukcja i jako taka zyskała trochę przyczepności w ciągu ostatnich 30 lat użytkowania jako standard. Dlaczego zaczęli od tego, prawdopodobnie jakiś limit szerokości znaków dla instrukcji, zmiennych i tym podobnych; dlaczego go trzymają, to standard. Ten standard jest taki sam, jak użycie int jako identyfikatora, użycie liczb całkowitych byłoby bardziej czytelne we wszystkich przypadkach, ale jest konieczne dla każdego, kto programuje dłużej niż kilka tygodni ... nie. Dlaczego? Ponieważ to standardowa praktyka.

Po drugie, jak powiedziałem w moim komentarzu, wiele przerwań nosi nazwę INTG1 i inne tajemnicze nazwy, które również służą celowi. Na schematach obwodów NIE jest dobrą konwencją nazywanie twoich linii, a tak obszernie zaśmieca schemat i szkodzi czytelności. Wszelka gadatliwość jest opisana w dokumentacji. A ponieważ wszystkie schematy połączeń / obwodów mają te krótkie nazwy linii przerwań, same przerwania również mają taką samą nazwę, aby zachować spójność dla projektanta osadzonego ze schematu obwodu aż do kodu, aby go zaprogramować.

Projektant ma nad tym pewną kontrolę, ale podobnie jak każdy inny język / nowy język, istnieją konwencje, które następują od sprzętu do sprzętu i jako takie powinny pozostać podobne w każdym języku asemblera. Mogę spojrzeć na fragment asemblera i być w stanie uzyskać treść kodu bez użycia tego zestawu instrukcji, ponieważ trzymają się konwencji, LDA lub jakiegoś związku z nią prawdopodobnie ładuje rejestr MV prawdopodobnie coś przenosi gdzieś gdzie indziej nie chodzi o to, co uważasz za przyjemne lub o praktykę na wysokim poziomie, jest to język sam w sobie i jako taki ma swoje własne standardy i oznacza, że ​​jako projektant powinien podążać, często nie są one tak arbitralne jak wydają się.

Zostawię cię z tym: Poproszenie społeczności osadzonej o stosowanie pełnych praktyk wysokiego poziomu jest jak proszenie chemików, aby zawsze zapisywali związki chemiczne. Chemik pisze je dla siebie i każdy w tej dziedzinie to zrozumie, ale dostosowanie się może zająć nowemu przybyszowi trochę czasu.


1
Wydaje mi się, że „użyjemy tajemniczych nazw, ponieważ to sprawia, że ​​programowanie na niskim poziomie wydaje się takie” i „użyjemy tajemniczych nazw, ponieważ taka jest konwencja dla programowania na niskim poziomie” są prawie takie same, więc +1 ode mnie i pomyślę o zaakceptowaniu tego jako mniej zapalnego wariantu tego, który zaakceptowałem na początku .
Roman Starkov

6
+1 dla chemików, ponieważ generuje dobrą analogię do różnych dziedzin programowania.

4
+1 Nigdy też nie rozumiałem, dlaczego ludzie używają krótkich, tajemniczych nazw, takich jak „woda”, jeśli istnieje o wiele bardziej czytelny „DiHydrogenOxyde”
Ingo

6

Jednym z powodów, dla których używają tajemniczych krótkich identyfikatorów, jest to, że nie są one tajemnicze dla programistów. Musisz zdać sobie sprawę, że pracują z tym na co dzień, a te nazwy są naprawdę nazwami domen. Więc wiedzą na pamięć, co dokładnie oznacza TIFR1.

Jeśli nowy zespół przyjdzie do zespołu, będzie musiał przeczytać arkusze danych (jak wyjaśniono w @KarlBielefeldt), aby mogli się z nimi swobodnie zapoznać.

Sądzę, że twoje pytanie posłużyło za zły przykład, ponieważ rzeczywiście na tego rodzaju kodach źródłowych zwykle widzisz wiele niepotrzebnych identyfikatorów krypt dla rzeczy spoza domeny.

Powiedziałbym, że robią to głównie z powodu złych nawyków, które istniały, gdy kompilatory nie uzupełniały automatycznie wszystkiego, co piszesz.


5

Podsumowanie

Inicjalizm jest zjawiskiem wszechobecnym w wielu kręgach technicznych i nietechnicznych. Jako taki nie ogranicza się do programowania niskiego poziomu. Ogólną dyskusję można znaleźć w artykule na temat akronimu w Wikipedii . Moja odpowiedź dotyczy programowania niskopoziomowego.

Przyczyny tajemniczych nazw:

  1. Instrukcje niskiego poziomu są mocno wpisane
  2. Musisz spakować wiele informacji o typie w nazwie instrukcji niskiego poziomu
  3. W przeszłości kody jednoznakowe były uprzywilejowane do pakowania informacji o typie.

Rozwiązania i ich wady:

  1. Istnieją nowoczesne schematy nazewnictwa niskiego poziomu, które są bardziej spójne niż te historyczne.
    • LLVM
  2. Jednak nadal istnieje potrzeba spakowania dużej ilości informacji o typie.
    • Tak więc tajemnicze skróty wciąż można znaleźć wszędzie.
  3. Ulepszona czytelność między wierszami pomoże początkującemu programistowi niskiego poziomu szybciej wybrać język, ale nie pomoże w zrozumieniu dużych fragmentów kodu niskiego poziomu.

Pełna odpowiedź

(A) Możliwe są dłuższe nazwy. Na przykład nazwy wewnętrzne C ++ SSE2 mają średnio 12 znaków w porównaniu do 7 znaków w mnemoniku zestawu. http://msdn.microsoft.com/en-us/library/c8c5hx3b(v=vs.80).aspx

(B) Następnie pojawia się pytanie: jak długo / nieszyfrowane trzeba uzyskać z instrukcji niskiego poziomu?

(C) Teraz analizujemy skład takich schematów nazewnictwa. Oto dwa schematy nazewnictwa dla tej samej instrukcji niskiego poziomu:

  • Schemat nazewnictwa nr 1: CVTSI2SD
  • Schemat nazewnictwa nr 2: __m128d _mm_cvtsi32_sd (__m128d a, int b);

(C.1) Instrukcje niskiego poziomu są zawsze silnie napisane. Nie może być dwuznaczności, wnioskowania o typie, automatycznej konwersji typu ani przeciążenia (ponowne użycie nazwy instrukcji w celu oznaczenia podobnych, ale nie równoważnych operacji).

(C.2) Każda instrukcja niskiego poziomu musi zawierać w swojej nazwie wiele informacji typu. Przykłady informacji:

  • Architektura rodziny
  • Operacja
  • Argumenty (wejścia) i dane wyjściowe
  • Typy (liczba całkowita ze znakiem, liczba całkowita bez znaku, liczba zmiennoprzecinkowa)
  • Precyzja (szerokość bitów)

(C.3) Jeśli każda informacja zostanie przeliterowana, program będzie bardziej szczegółowy.

(C.4) Schematy kodowania typów stosowane przez różnych dostawców mają długie historyczne korzenie. Na przykład w zestawie instrukcji x86:

  • B oznacza bajt (8 bitów)
  • W oznacza słowo (16-bit)
  • D oznacza „podwójne słowo” dworda (32-bit)
  • Q oznacza qword „quad-word” (64-bit)
  • DQ oznacza dqword „podwójne-poczwórne słowo” (128-bit)

Te odniesienia historyczne nie miały żadnego współczesnego znaczenia, ale wciąż się utrzymują. Bardziej spójny schemat umieściłby w nazwie wartość szerokości bitu (8, 16, 32, 64, 128).

Przeciwnie, LLVM jest właściwym krokiem w kierunku spójności instrukcji niskiego poziomu: http://llvm.org/docs/LangRef.html#functions

(D) Niezależnie od schematu nazewnictwa instrukcji, programy niskiego poziomu są już pełne i trudne do zrozumienia, ponieważ koncentrują się na najdrobniejszych szczegółach wykonania. Zmiana schematu nazewnictwa instrukcji poprawi czytelność na poziomie linia-linia, ale nie usunie trudności w zrozumieniu operacji dużego fragmentu kodu.


1
Poprawiona czytelność między wierszami będzie musiała mieć pewien wpływ na zrozumienie całości, ale samo nazywanie nie może oczywiście uczynić go trywialnym.
Roman Starkov

3
Również rodzaj off-topic, ale CVTSI2SDnie wykonuje żadnych więcej informacji niż ConvertDword2Doublealbo ConvInt32ToFloat64, ale te ostatnie, podczas gdy dłużej, są natychmiast rozpoznawalne, podczas gdy pierwsza musi być rozszyfrowane ...
Roman Starkov

2

Ludzie od czasu do czasu czytają i piszą asemblery, a przez większość czasu jest to tylko protokół komunikacyjny. Tj. Jest najczęściej używany jako pośrednia serializowana reprezentacja tekstowa między kompilatorem a asemblerem. Im bardziej szczegółowa jest ta reprezentacja, tym bardziej niepotrzebny jest narzut w tym protokole.

W przypadku kodów opc i nazw rejestrów długie nazwy w rzeczywistości szkodzą czytelności. Krótkie mnemoniki są lepsze dla protokołu komunikacyjnego (między kompilatorem a asemberem), a język asemblera jest przez większość czasu protokołem komunikacyjnym. Krótkie mnemoniki są lepsze dla programistów, ponieważ kod kompilatora jest łatwiejszy do odczytania.


Jeśli chcesz zaoszczędzić miejsce, po prostu zgzipuj! ... Jeśli nie potrzebujesz narzutu, użyj formatu binarnego! Jeśli używasz tekstu, dążysz do jego czytelności - dlaczego więc nie pójść na całość i zapewnić jego odpowiednią czytelność?
Roman Starkov

2
@romkyns, kompresowanie tekstowego protokołu komunikacyjnego między dwoma procesami lokalnymi? To jest coś nowego. Protokoły binarne są znacznie mniej niezawodne. Jest to sposób uniksowy - protokoły tekstowe zapewniają sporadyczną czytelność. Są wystarczająco czytelne.
SK-logic

Dobrze. Twoim założeniem jest to, że czytam i piszę nazwy tych rejestrów lub instrukcji CIL wystarczająco mało, aby narzut miał znaczenie. Ale pomyśl o tym; są one używane tak często, jak każda nieparzysta nazwa metody lub zmiennej w innym języku programowania podczas programowania . Czy to tak rzadkie, że dodatkowe kilka bajtów ma znaczenie?
Roman Starkov

1
Szanuję twoje prawo do innego gustu co do długości nazwisk, ale czy tak naprawdę nazywasz metody i miejscowi w swoich kompilatorach zagadkowymi rzeczami TIFR, czy też zawierają one pełne słowa?
Roman Starkov

1
Nie widzę żadnej różnicy, która byłaby istotna dla czytelnego i krótkiego kompromisu. Widzę je jako różne, oczywiście, podobnie jak zmienne różnią się od funkcji, które różnią się od typów. Po prostu nie rozumiem, dlaczego opcodes i nazwy rejestrów korzystają z tego, że są bardzo krótkie, do tego stopnia, że ​​muszę zapoznać się z dokumentacją każdego nowo napotkanego, zanim będziesz miał jakąkolwiek wskazówkę, co robi. Twój jedyny dotychczasowy argument to wydajne przechowywanie, jeśli się nie mylę. Czy naprawdę myśli? ... A może masz inne powody?
Roman Starkov

1

Przeważnie jest to idiomatyczne. Jak napisano w innym miejscu @TMN, tak jak nie piszesz import JavaScriptObjectNotationani import HypertextTransferProtocolLibraryw Pythonie, nie piszesz Timer1LowerHalf = 0xFFFFw C. Wygląda równie śmiesznie w kontekście. Każdy, kto musi wiedzieć, już wie.

Odporność na zmiany może wynikać częściowo z faktu, że niektórzy dostawcy kompilatorów C dla systemów wbudowanych odbiegają od standardu językowego i składni w celu implementacji funkcji bardziej przydatnych dla programowania wbudowanego. Oznacza to, że nie zawsze możesz używać funkcji autouzupełniania swojego ulubionego IDE lub edytora tekstowego podczas pisania kodu niskiego poziomu, ponieważ dostosowania te osłabiają ich zdolność do analizowania kodu. Stąd użyteczność krótkich nazw rejestrów, makr i stałych.

Na przykład kompilator C HiTech zawiera specjalną składnię dla zmiennych, które musiały mieć w pamięci określoną przez użytkownika pozycję. Możesz zadeklarować:

volatile char MAGIC_REGISTER @ 0x7FFFABCD;

Teraz jedynym istniejącym IDE, które będzie analizowało to IDE HiTech ( HiTide ). W każdym innym edytorze musisz za każdym razem wpisywać go ręcznie z pamięci. Starzeje się bardzo szybko.

Jest też fakt, że kiedy używasz narzędzi programistycznych do sprawdzania rejestrów, często wyświetlasz tabelę z kilkoma kolumnami (nazwa rejestru, wartość szesnastkowa, wartość dwójkowa, ostatnia wartość szesnastkowa itp.). Długie nazwy oznaczają, że musisz rozwinąć kolumnę nazwy do 13 znaków, aby zobaczyć różnicę między dwoma rejestrami, i grać „zauważ różnicę” w dziesiątkach wierszy powtarzanych słów.

Może to zabrzmieć jak głupie drobiazgi, ale czy nie każda konwencja kodowania ma na celu zmniejszenie zmęczenia oczu, zmniejszenie zbędnego pisania lub rozwiązanie jednej z milionów innych drobnych skarg?


2
Wszystkie twoje argumenty mają sens. W pełni rozumiem wszystkie te punkty. Nie sądzisz jednak, że dokładnie to samo dotyczy kodu wysokiego poziomu? Musisz także zobaczyć tabelę miejscowych w funkcji C #. Kontekst jest subiektywny i File.ReadAllBytesmoże też wyglądać absurdalnie długo dla kogoś, kto był do tego przyzwyczajony fread. Więc ... po co inaczej traktować kod wysokiego i niskiego poziomu ?
Roman Starkov

@romkyns - Rozumiem, o co chodzi, ale nie sądzę, że tak naprawdę traktujemy kod wysokiego poziomu bardzo inaczej. Skróty są odpowiednie w wielu kontekstach wysokiego poziomu, po prostu nie zdajemy sobie z tego sprawy, ponieważ jesteśmy bardziej przyzwyczajeni do skrótu lub jakiegokolwiek innego schematu z nim związanego. Kiedy faktycznie piszę funkcje lub tworzę zmienne w kodzie niskiego poziomu, używam ładnych opisowych nazw. Ale kiedy odnoszę się do rejestru, cieszę się, że mogę rzucić okiem na zbieraninę liter i cyfr i szybko pomyśleć: „T = timer, IF = flaga przerwania, 1 = pierwszy rejestr”. Pod tym względem jest to prawie jak chemia organiczna: P
detly

@romkyns - Również w czysto praktycznym sensie myślę, że różnica między tabeli rejestrów w IDE i aplikacji rozwoju jakiegoś mikroprocesora w C # to: tabela rejestrów UP może wyglądać tak: Timer1InterruptFlag, Timer2InterruptFlag, ..., Timer9InterruptFlag, IOPortAToggleMask, IOPortBToggleMask, etc x100. W języku wyższego poziomu użyłbyś zmiennych, które różnią się znacznie bardziej ... lub użyłbyś większej struktury. Timer1InterruptFlagto 75% nieistotnego hałasu w porównaniu do T1IF. Nie sądzę, żebyś stworzył ogromną listę zmiennych w C #, które ledwo się tak różnią.
detly

1
@romkyns - Co może nie być świadomy, jest fakt, że nie ma już zwrot w kierunku tego, co można opisać. Najnowsze kompilatory Microchip są wyposażone w biblioteki, które są bardziej szczegółowe i opisowe niż tylko rejestry, np. UARTEnable(UART1, BITS_8, PARITY_N, STOP_1, BAUD_115200). Ale wciąż są niesamowicie niezgrabne i wymagają dużo pośredniej i nieefektywnej pracy. Staram się ich używać tam, gdzie to możliwe, ale w większości przypadków manipuluję rejestrem we własnych funkcjach i wywołuję go z logiki wyższego poziomu.
detly

@detly: Kompilator CCS ma takie metody, a niektóre inne procesory to robią. Generalnie ich nie lubię. Specyfikacja rejestru jest wystarczająca do napisania kodu, który korzysta z rejestrów i wystarczy, aby ktoś czytający kod korzystający z rejestrów zobaczył, co robią te rejestry. Jeśli akt zapisu wartości N na sprzętowym preskalarnym ustawia kropkę na N + 1 (dość powszechne), właściwym znaczeniem set_prescalar(TMR4,13);jest IMHO o wiele mniej jasne niż byłoby TMR4->PSREG=12;. Nawet jeśli spojrzysz na instrukcję kompilatora, aby dowiedzieć się, co robi pierwszy kod, prawdopodobnie nadal będziesz musiał ...
supercat

1

Dziwi mnie, że nikt nie wspominał o lenistwie i że inne nauki nie są omawiane. Moja codzienna praca jako programista pokazuje mi, że na konwencje nazewnictwa dla dowolnej zmiennej w programie mają wpływ trzy różne aspekty:

  1. Podstawy naukowe programisty.
  2. Umiejętności programistyczne programisty.
  3. Środowisko programisty.

Myślę, że nie ma sensu dyskutować o programowaniu na niskim lub wysokim poziomie. Na samym końcu zawsze można go przypisać do trzech poprzednich aspektów.


Wyjaśnienie pierwszego aspektu: Wielu „programistów” nie jest programistami. Są matematykami, fizykami, biologami, a nawet psychologami lub ekonomistami, ale wielu z nich nie jest informatykami. Większość z nich ma własne słowa kluczowe i skróty, które można zobaczyć w ich „konwencjach” nazewnictwa. Często są uwięzieni w swojej dziedzinie i używają znanych skrótów, nie myśląc o instrukcjach dotyczących czytelności ani kodowania.

Wyjaśnienie drugiego aspektu: ponieważ większość programistów nie jest informatykami, ich umiejętności programowania są ograniczone. Dlatego często nie dbają o konwencje kodowania, ale bardziej o konwencje specyficzne dla domeny, jak podano jako pierwszy aspekt. Również jeśli nie masz umiejętności programisty, nie rozumiesz konwencji kodowania. Myślę, że większość z nich nie widzi pilnej potrzeby napisania zrozumiałego kodu. To jak ogień i zapomnieć.

Wyjaśnienie trzeciego aspektu: jest mało prawdopodobne, aby hamować konwencje twojego środowiska, które mogą być starym kodem, który musisz obsługiwać, standardami kodowania twojej firmy (prowadzonymi przez ekonomistów, którzy nie dbają o kodowanie) lub domeną, do której należysz. Jeśli ktoś zaczął używać tajemniczych nazw, a ty musisz wesprzeć go lub jego kod, jest mało prawdopodobne, aby zmienić tajemnicze nazwy. Jeśli w twojej firmie nie ma standardów kodowania, założę się, że prawie każdy programista napisze własny standard. I na koniec, jeśli jesteś otoczony przez użytkowników domeny, nie zaczniesz pisać innego języka niż oni używają.


nikt nie wspominał o lenistwie - może dlatego, że nie ma to tutaj znaczenia. I że inne nauki nie są omawiane, och, to proste: ta strona nie jest do dyskusji . To jest na pytania i odpowiedzi
komara

Lenistwo jest uzasadnionym powodem. Prawie wszyscy programiści to leniwi ludzie (inaczej robilibyśmy wszystko ręcznie ooo!).
Thomas Eding,
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.