Perché gli identificatori brevi criptici sono ancora così comuni nella programmazione di basso livello?

62

C'erano già molto buoni motivi per mantenere i nomi delle istruzioni / registro in breve. Queste ragioni non si applicano più, ma i nomi criptici brevi sono ancora molto comuni nella programmazione di basso livello.

Perché è questo? È solo perché le vecchie abitudini sono difficili da rompere, o ci sono ragioni migliori?

Ad esempio:

  • Atmel ATMEGA32U2 (2010?): TIFR1 (anziché TimerCounter1InterruptFlag ), ICR1H (anziché InputCapture1High ), DDRB (invece di DataDirectionPortB ), ecc.
  • Set di istruzioni CLR .NET (2002): bge.s (invece di branch-if-greater-or-equal.short ), ecc.

I nomi più lunghi e non criptici non sono più facili da usare?

Quando rispondi e vota, tieni presente quanto segue. Molte delle possibili spiegazioni suggerite qui applicano ugualmente alla programmazione di alto livello, eppure il consenso, in generale, è quello di usare nomi non criptici composti da una parola o due (acronimi comunemente compresi esclusi) .

Inoltre, se il tuo argomento principale riguarda lo spazio fisico su un diagramma cartaceo , tieni presente che questo non si applica assolutamente al linguaggio assembly o CIL, inoltre mi farebbe piacere se mi mostri un diagramma dove nomi stridenti in forma ma leggibili rendono lo schema peggiore. Dall'esperienza personale in un'azienda produttrice di semiconduttori, i nomi leggibili si adattano perfettamente e generano diagrammi più leggibili.

Qual è la cosa principale che è diversa rispetto alla programmazione di basso livello rispetto a quella di linguaggi di alto livello che rende desiderabili i nomi criptici tersi nella programmazione di basso livello ma non di alto livello ?

    
posta Roman Starkov 28.08.2012 - 23:35
fonte

11 risposte

11

Ci sono così tante idee diverse qui. Non posso accettare nessuna delle risposte esistenti come la risposta: in primo luogo, ci sono probabilmente molti fattori che contribuiscono a questo, e in secondo luogo, non posso sapere quale sia la più significativa.

Ecco qui un riassunto delle risposte pubblicato da altri qui. Sto postando questo come CW e la mia intenzione è di contrassegnarlo come accettato. Si prega di modificare se ho perso qualcosa. Ho cercato di riformulare ogni idea per esprimerla in modo conciso ma chiaro.

Quindi perché gli identificatori brevi criptici sono così comuni nella programmazione di basso livello?

  • Perché molti di loro sono abbastanza comuni nel rispettivo dominio per garantire un nome molto breve. Ciò peggiora la curva di apprendimento, ma è un compromesso utile data la frequenza di utilizzo.
  • Perché di solito c'è un piccolo insieme di possibilità che è fissato (il programmatore non può aggiungere al set).
  • Perché la leggibilità è una questione di abitudine e pratica. branch-if-greater-than-or-equal.short è inizialmente più leggibile di bge.s , ma con un po 'di pratica la situazione si inverte.
  • Perché spesso devono essere digitati per intero, a mano, perché i linguaggi di basso livello spesso non sono dotati di IDE potenti con buon completamento automatico o a / c non affidabili.
  • Perché a volte è desiderabile inserire un sacco di informazioni nell'identificatore e un nome leggibile sarebbe inaccettabilmente lungo anche per gli standard di alto livello.
  • Perché è quello che gli ambienti di basso livello hanno assomigliato storicamente. Rompere l'abitudine richiede uno sforzo cosciente, rischia di infastidire coloro che amavano i vecchi modi e deve essere giustificato come utile. Attaccare con il modo stabilito è il "default".
  • Perché molti di loro hanno origine altrove, come schemi e schede tecniche. Quelli, a loro volta, sono influenzati dai vincoli di spazio.
  • Perché le persone incaricate di nominare le cose non hanno mai nemmeno considerato la leggibilità, o non si rendono conto che stanno creando un problema o sono pigre.
  • Perché in alcuni casi i nomi sono diventati parte di un protocollo per lo scambio di dati, come l'uso del linguaggio assembly come rappresentazione intermedia da parte di alcuni compilatori.
  • Perché questo stile è immediatamente riconoscibile come di basso livello e quindi sembra interessante per i geek.

Personalmente ritengo che alcuni di questi non contribuiscano effettivamente alle ragioni per cui un sistema di nuova concezione avrebbe scelto questo stile di denominazione, ma ho ritenuto che sarebbe sbagliato filtrare alcune idee in questo tipo di risposta.

    
risposta data 27.11.2018 - 11:46
fonte
105

Il motivo per cui il software usa quei nomi è perché i fogli dati usano quei nomi. Dal momento che il codice a quel livello è molto difficile da capire senza la scheda tecnica comunque, la creazione di nomi di variabili che non è possibile cercare è estremamente inutile.

Questo fa sorgere la domanda sul perché i fogli dati usano nomi brevi. Probabilmente è perché spesso hai bisogno di presentare i nomi in tabelle come questa in cui non hai spazio per identificatori di 25 caratteri:

Inoltre, cose come schemi, diagrammi di pin e serigrafie PCB spesso sono molto angusti per lo spazio.

    
risposta data 28.08.2012 - 23:57
fonte
59

Legge di Zipf

Tu stesso puoi osservare guardando questo stesso testo che la lunghezza della parola e la frequenza di utilizzo sono, in generale, inversamente correlate. Le parole che vengono utilizzate molto frequentemente, come it , a , but , you e and sono molto brevi, mentre le parole che vengono utilizzate meno spesso come observe , comprehension e verbosity sono più lunghi. Questa relazione osservata tra frequenza e lunghezza è chiamata Legge di Zipf .

Il numero di istruzioni nel set di istruzioni per un dato microprocessore di solito è numerato in dozzine o centinaia. Ad esempio, il set di istruzioni Atmel AVR sembra contenere un centinaio di istruzioni distinte (non ho contato), ma molti di questi sono variazioni su un tema comune e hanno mnemonici molto simili. Ad esempio, le istruzioni di moltiplicazione includono MUL, MULS, MULSU, FMUL, FMULS e FMULSU. Non è necessario consultare l'elenco delle istruzioni per molto tempo prima di avere l'idea generale che le istruzioni che iniziano con "BR" siano rami, le istruzioni che iniziano con "LD" siano caricate, ecc. Lo stesso vale per le variabili: anche i processori complessi forniscono solo un numero limitato di posizioni per memorizzare i valori: registri di condizione, registri di uso generale, ecc.

Dato che ci sono così poche istruzioni e perché i nomi lunghi richiedono più tempo per essere letti, è opportuno dare loro nomi brevi. Al contrario, i linguaggi di livello superiore consentono ai programmatori di creare un numero enorme di funzioni, metodi, classi, variabili e così via. Ognuno di questi verrà utilizzato molto meno frequentemente rispetto alla maggior parte delle istruzioni di assemblaggio e nomi più lunghi e più descrittivi sono sempre più importanti per fornire ai lettori (e agli autori) informazioni sufficienti per capire cosa sono e cosa fanno.

Inoltre, i set di istruzioni per diversi processori usano spesso nomi simili per operazioni simili. La maggior parte delle serie di istruzioni include operazioni per ADD, MUL, SUB, LD, ST, BR, NOP e, se non usano questi nomi esatti, usano solitamente nomi molto vicini. Una volta imparati i mnemonici per un set di istruzioni, non ci vuole molto per adattarsi ai set di istruzioni per altri dispositivi. Quindi nomi che potrebbero sembrare "criptici" per te sono familiari come parole come and , or e not per i programmatori esperti nella programmazione di basso livello. Penso che la maggior parte delle persone che lavorano a livello di assemblaggio ti diranno che imparare a leggere il codice non è una delle sfide maggiori nella programmazione di basso livello.

    
risposta data 14.01.2013 - 17:19
fonte
37

In generale

La qualità della denominazione non consiste solo nell'avere nomi descrittivi, ma deve anche considerare altri aspetti e ciò porta a raccomandazioni come:

  • più globale è l'ambito, più descrittivo dovrebbe essere il nome
  • più spesso viene utilizzato, più breve deve essere il nome
  • lo stesso nome dovrebbe essere usato in tutti i contesti per la stessa cosa
  • cose diverse dovrebbero avere nomi diversi anche se il contesto è diverso
  • le variazioni dovrebbero essere facilmente rilevate
  • ...

Nota che queste raccomandazioni sono in conflitto.

Istruzione mnemonica

Come programmatore di linguaggio assembly, l'utilizzo di short-branch-if-greater-or-equal per bge.s mi dà la stessa impressione di quando vedo, come un programmatore di Algol che esegue la geometria computazionale, 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-POINTS invece di dx := p2.x - p1.x . Non posso proprio essere d'accordo sul fatto che i primi siano più leggibili nei contesti a cui tengo.

Registra nomi

Scegli il nome ufficiale dalla documentazione. La documentazione sceglie il nome dal design. Il design utilizza molti formati grafici in cui i nomi lunghi non sono adeguati e il team di progettazione vivrà con quei nomi per mesi, se non per anni. Per entrambi i motivi, non useranno "Interrupt flag of the first timer counter", lo abbreveranno nel loro schema così come quando parleranno. Lo sanno e usano abbreviazioni sistematiche come TIFR1 in modo che ci siano meno possibilità di confusione. Un punto qui è che TIFR1 non è un'abbreviazione casuale, è il risultato di uno schema di denominazione.

    
risposta data 29.08.2012 - 09:56
fonte
24

Oltre alle "vecchie abitudini", il codice Legacy che è stato scritto 30 anni fa ed è ancora in uso è molto comune. Nonostante ciò che pensano alcune persone meno esperte, il refactoring di questi sistemi in modo che sembrino belli ha un costo molto alto per un piccolo guadagno e non è commercialmente fattibile.

I sistemi integrati vicini all'hardware e l'accesso ai registri tendono a utilizzare etichette identiche o simili a quelle utilizzate nei fogli dati dell'hardware, per ottime ragioni. Se il registro si chiama XYZZY1 nei fogli dati hardware, ha senso che la variabile che rappresenta è probabilmente XYZZY1, o se il programmatore ha avuto una buona giornata, RegXYZZY1.

Per quanto riguarda il bge.s , è simile all'assemblatore - alle poche persone che hanno bisogno di sapere che i nomi più lunghi sono meno leggibili. Se non riesci a farti perdere circa bge.s e pensa che branch-if-greater-or-equal.short faccia la differenza - stai semplicemente giocando con il CLR e non lo sai.

L'altra ragione per cui vedrai nomi di variabili brevi è dovuta all'ampia diffusione delle abbreviazioni all'interno del dominio che il software sta prendendo di mira.

In sintesi - sono previsti nomi abbreviati di variabili brevi che riflettono un'influenza esterna come le norme del settore e le schede tecniche dell'hardware. Normalmente i nomi di variabili abbreviate brevi interne al software sono meno desiderabili.

    
risposta data 29.08.2012 - 00:09
fonte
10

Ho intenzione di gettare il mio cappello in questo casino.

Le convenzioni e gli standard di codifica di alto livello non sono gli stessi standard e pratiche di codifica di basso livello. Sfortunatamente, la maggior parte di questi sono intralci da codice legacy e vecchi processi di pensiero.

Alcuni, tuttavia, hanno uno scopo. Sicuramente BranchGreaterThan sarebbe molto più leggibile di BGT , ma ora c'è una convenzione, è un'istruzione e come tale ha guadagnato un po 'di trazione negli ultimi 30 anni di utilizzo come standard. Perché hanno iniziato con esso, probabilmente con qualche limite di larghezza di caratteri arbitrario per istruzioni, variabili e simili; perché lo mantengono, è uno standard. Questo standard è lo stesso che usare int come identificatore, sarebbe più leggibile usare Intero in tutti i casi, ma è necessario per chiunque abbia programmato più di un poche settimane ... no Perché? Perché è una pratica standard.

In secondo luogo, come ho detto nel mio commento, molti degli interrupt sono denominati INTG1 e altri nomi criptici, anche questi hanno uno scopo. Nei diagrammi circuitali è NOT una buona convenzione per nominare le tue linee e in modo così verbale ingombra il diagramma e danneggia la leggibilità. Tutta la verbalità è gestita nella documentazione. E poiché tutti gli schemi di cablaggio / circuito hanno questi nomi brevi per le linee di interrupt, gli stessi interrupt hanno lo stesso nome di mantenere la coerenza per il progettista embedded dallo schema circuitale fino al codice per programmarlo.

Un designer ha un certo controllo su questo, ma come ogni campo / nuova lingua ci sono convenzioni che seguono dall'hardware all'hardware, e come tale dovrebbe rimanere simile in ogni linguaggio di assemblaggio. Posso guardare un frammento di assembly ed essere in grado di ottenere il succo del codice senza mai usare quel set di istruzioni perché si attengono a una convenzione, LDA o qualche relazione ad esso sta probabilmente caricando un registro < strong> MV probabilmente sta spostando qualcosa da qualche parte a un'altra parte, non si tratta di ciò che pensi sia bello o è una pratica di alto livello, è un linguaggio a sé stante e come tale ha i suoi standard e significa che tu come dovrebbe seguire il designer, spesso non sono così arbitrari come sembrano.

Vi lascerò con questo: chiedere alla comunità incorporata di usare verbose pratiche di alto livello è come chiedere ai chimici di scrivere sempre composti chimici. Il chimico li scrive per conto loro e chiunque altro nel campo lo capirà, ma potrebbe volerci un po 'di tempo per adattarsi.

    
risposta data 14.01.2013 - 15:50
fonte
6

Un motivo per cui usano identificatori brevi criptici è perché non sono criptici per gli sviluppatori. Devi rendertene conto che ci lavorano tutti i giorni e quei nomi sono in realtà dei nomi di dominio. Quindi sanno a memoria cosa significa esattamente TIFR1.

Se un nuovo sviluppatore arriva nel team, dovrà leggere i fogli dati (come spiegato da @KarlBielefeldt) in modo che si sentano a proprio agio con quelli.

Credo che la tua domanda abbia usato un cattivo esempio perché in effetti su quei tipi di codice sorgente di solito vedi molti identificatori di crypt non necessari per cose non di dominio.

Direi che lo fanno per lo più a causa delle cattive abitudini che esistevano quando i compilatori non completavano automaticamente tutto ciò che scrivevi.

    
risposta data 29.08.2012 - 15:47
fonte
5

Sommario

L'inizialismo è un fenomeno pervasivo in molti ambienti tecnici e non tecnici. In quanto tale, non è limitato alla programmazione di basso livello. Per la discussione generale, consultare l'articolo di Wikipedia su Acronimo . La mia risposta è specifica per la programmazione di basso livello.

Cause dei nomi criptici:

  1. Le istruzioni di basso livello sono strongmente scritte
  2. È necessario comprimere un sacco di informazioni sul tipo nel nome di un'istruzione di basso livello
  3. Storicamente, i codici a carattere singolo sono preferiti per l'imballaggio delle informazioni sul tipo.

Soluzioni e i loro svantaggi:

  1. Esistono moderni schemi di denominazione di basso livello che sono più coerenti di quelli storici.
    • LLVM
  2. Tuttavia, esiste ancora la necessità di comprimere un sacco di informazioni sul tipo.
    • Pertanto, le abbreviazioni criptiche possono ancora essere trovate ovunque.
  3. Una migliore leggibilità line-to-line aiuterà un programmatore principiante di basso livello a riprendere il linguaggio più velocemente, ma non aiuterà a comprendere grandi pezzi di codice di basso livello.

Risposta completa

(A) I nomi più lunghi sono possibili. Ad esempio, i nomi di C ++ SSE2     intrinseca media di 12 caratteri rispetto ai 7 caratteri     nell'assemblea mnemonica.      link

(B) La domanda passa quindi a: Quanto tempo / non-criptico si ha bisogno     per ottenere istruzioni di basso livello?

(C) Ora analizziamo la composizione di tali schemi di denominazione. Di seguito sono riportati due schemi di denominazione per lo stesso istruzione di basso livello:

  • Schema di denominazione n. 1: CVTSI2SD
  • Schema di denominazione n. 2: __m128d _mm_cvtsi32_sd (__m128d a, int b);

(C.1) Le istruzioni di basso livello sono sempre strongmente digitate. Non ci può essere        ambiguità, tipo di inferenza, conversione automatica del tipo, o        sovraccarico (riutilizzo del nome dell'istruzione per indicare operazioni simili ma non equivalenti).

(C.2) Ogni istruzione di basso livello deve codificare molte informazioni di tipo        nel suo nome. Esempi di informazioni:

  • Architettura famiglia
  • Operazione
  • Argomenti (input) e output
  • Tipi (intero con segno, numero intero senza segno, float)
  • Precisione (larghezza bit)

(C.3) Se ogni informazione è scritta, il programma sarà        più prolisso.

(C.4) Gli schemi di codifica del tipo usati da vari venditori avevano radici storiche lunghe. Ad esempio, nel set di istruzioni x86:

  • B significa byte (8 bit)
  • W indica word (16 bit)
  • D significa dword "double-word" (32-bit)
  • Q significa qword "quad-word" (64-bit)
  • DQ significa dqword "double-quad-word" (128-bit)

Questi riferimenti storici non avevano alcun significato moderno, ma si aggrappano ancora. Uno schema più coerente avrebbe inserito il valore della larghezza di bit (8, 16, 32, 64, 128) nel nome.

Al contrario, LLVM è un passo giusto verso la coerenza delle istruzioni di basso livello: link

(D) Indipendentemente dallo schema di denominazione delle istruzioni, i programmi di basso livello lo sono      già prolisso e difficile da capire perché si concentrano sul      dettagli minuti di esecuzione. Modifica dello schema di denominazione delle istruzioni      migliorerà la leggibilità a livello di line-to-line, ma non rimuoverà      la difficoltà di comprendere le operazioni di un grande pezzo di      codice.

    
risposta data 14.01.2013 - 03:16
fonte
2

Gli umani leggono e scrivono assemblaggi solo occasionalmente, e il più delle volte è solo un protocollo di comunicazione. Ad esempio, è più spesso usato come una rappresentazione basata su testo in serie intermedia tra compilatore e assemblatore. Più questa rappresentazione è prolissa, maggiore è il sovraccarico non necessario in questo protocollo.

Nel caso degli opcode e dei nomi dei registri, i nomi lunghi in realtà danneggiano la leggibilità. I mnemonici brevi sono migliori per un protocollo di comunicazione (tra compilatore e assember) e il linguaggio assembly è un protocollo di comunicazione per la maggior parte del tempo. I mnemonici brevi sono migliori per i programmatori, dal momento che il codice del compilatore è più facile da leggere.

    
risposta data 13.01.2013 - 12:31
fonte
1

Per lo più è idiomatico. Come dice @TMN altrove, proprio come non scrivi import JavaScriptObjectNotation o import HypertextTransferProtocolLibrary in Python, non scrivi Timer1LowerHalf = 0xFFFF in C. Sembra altrettanto ridicolo nel contesto. Chiunque abbia bisogno di sapere lo sa già.

La resistenza al cambiamento potrebbe derivare, in parte, dal fatto che alcuni produttori di compilatori C per sistemi embedded si discostano dallo standard e dalla sintassi del linguaggio per implementare funzionalità più utili per la programmazione incorporata. Ciò significa che non puoi sempre utilizzare la funzione di completamento automatico del tuo IDE o editor di testo preferito quando scrivi un codice di basso livello, perché queste personalizzazioni annullano la loro capacità di analizzare il codice. Da qui l'utilità dei nomi dei registri brevi, delle macro e delle costanti.

Ad esempio, il compilatore C di HiTech includeva una sintassi speciale per le variabili che necessitavano di avere una posizione specificata dall'utente in memoria. Potresti dichiarare:

volatile char MAGIC_REGISTER @ 0x7FFFABCD;

Ora l'unico IDE esistente che analizzerà questo è l'IDE di HiTech ( HiTide ). In qualsiasi altro editor, dovrai scriverlo manualmente, dalla memoria, ogni volta. Questo diventa vecchio molto rapidamente.

Poi c'è anche il fatto che quando usi gli strumenti di sviluppo per ispezionare i registri, avrai spesso una tabella visualizzata con diverse colonne (nome del registro, valore in esadecimale, valore in binario, ultimo valore in esadecimale, ecc.) . I nomi lunghi significano che devi espandere la colonna del nome a 13 caratteri per vedere la differenza tra due registri e giocare "trova la differenza" su dozzine di righe di parole ripetute.

Potrebbero sembrare piccoli stupidi cavilli, ma non tutte le convenzioni di codifica sono state progettate per ridurre l'affaticamento della vista, ridurre la digitazione superflua o indirizzare qualsiasi altro milione di lamentele?

    
risposta data 14.01.2013 - 02:44
fonte
1

Sono sorpreso che nessuno abbia menzionato la pigrizia e che altre scienze non siano discusse. Il mio lavoro quotidiano come programmatore mi mostra che le convenzioni di denominazione per qualsiasi tipo di variabile in un programma sono influenzate da tre diversi aspetti:

  1. Lo sfondo scientifico del programmatore.
  2. Le capacità di programmazione del programmatore.
  3. L'ambiente del programmatore.

Penso che non sia utile discutere di programmazione di basso livello o di alto livello. Alla fine può essere sempre bloccato ai precedenti tre aspetti.

Una spiegazione del primo aspetto: Molti "programmatori" non sono programmatori in primo luogo. Sono matematici, fisici, biologi o persino psicologi o economisti, ma molti di loro non sono scienziati informatici. La maggior parte di loro ha le proprie parole chiave e abbreviazioni specifiche del dominio che è possibile vedere nelle loro "convenzioni" di denominazione. Sono spesso intrappolati nel loro dominio e usano quelle abbreviazioni conosciute senza pensare a leggibilità o guide di codifica.

Una spiegazione del secondo aspetto: Dato che la maggior parte dei programmatori non sono scienziati informatici, le loro capacità di programmazione sono limitate. Questo è il motivo per cui spesso non si preoccupano delle convenzioni sulla codifica, ma di più sulle convenzioni specifiche del dominio come indicato come primo aspetto. Inoltre, se non hai le capacità di un programmatore non hai la comprensione delle convenzioni di codifica. Penso che molti di loro non vedano l'urgente necessità di scrivere codice comprensibile. È come il fuoco e dimentica.

Una spiegazione del terzo aspetto: È improbabile che si freni con le convenzioni del proprio ambiente che possono essere codice vecchio che si deve supportare, standard di codifica della propria azienda (gestiti da economisti che non si preoccupano della codifica) o del dominio a cui si appartiene. Se qualcuno ha iniziato a usare nomi criptici e devi supportare lui o il suo codice, è improbabile che cambi i nomi criptici. Se non ci sono standard di codifica nella tua azienda, scommetto che quasi ogni programmatore scriverà il proprio standard. Infine, se sei circondato da utenti del dominio, non inizierai a scrivere un altro linguaggio diverso da quello che usano.

    
risposta data 15.01.2013 - 08:42
fonte

Leggi altre domande sui tag