Por que os identificadores abreviados ocultos ainda são tão comuns na programação de baixo nível?

62

Costumava haver muito boas razões para manter nomes de instruções / registros curtos. Essas razões não se aplicam mais, mas nomes crípticos curtos ainda são muito comuns em programação de baixo nível.

Por que isso? É só porque os velhos hábitos são difíceis de quebrar ou há melhores razões?

Por exemplo:

  • Atmel ATMEGA32U2 (2010?): TIFR1 (em vez de TimerCounter1InterruptFlag ), ICR1H (em vez de InputCapture1High ), DDRB (em vez de DataDirectionPortB ), etc.
  • Conjunto de instruções do .NET CLR (2002): bge.s (em vez de branch-if-greater-or-equal.short ), etc.

Os nomes mais longos e não enigmáticos são mais fáceis de trabalhar?

Ao responder e votar, considere o seguinte. Muitas das possíveis explicações sugeridas aqui se aplicam igualmente à programação de alto nível, e ainda o consenso, em geral, é usar nomes não-crípticos consistindo de uma palavra ou duas (siglas comumente entendidas excluídas) .

Além disso, se seu argumento principal for sobre espaço físico em um diagrama de papel , considere que isso absolutamente não se aplica à linguagem assembly ou CIL, além disso, eu agradeceria se você me mostrar um diagrama Os nomes concisos, mas legíveis, tornam o diagrama pior. A partir da experiência pessoal em uma empresa de semicondutores fabless, os nomes legíveis se encaixam perfeitamente e resultam em diagramas mais legíveis.

Qual é a questão principal que é diferente sobre a programação de baixo nível em oposição às linguagens de alto nível que tornam desejáveis os nomes crípticos na programação de baixo nível mas não de alto nível ?

    
por Roman Starkov 28.08.2012 / 23:35
fonte

11 respostas

11

Existem muitas ideias diferentes aqui. Não posso aceitar nenhuma das respostas existentes como a resposta: em primeiro lugar, há provavelmente muitos fatores que contribuem para isso, e em segundo lugar, eu não posso saber qual é o mais significativo. / p>

Então aqui está um resumo das respostas postadas por outras pessoas aqui. Estou postando isso como CW e minha intenção é eventualmente marcá-lo como aceito. Por favor, edite se eu perdi alguma coisa. Tentei reformular cada ideia para expressá-la de forma concisa, mas clara.

Então, por que os identificadores abreviados ocultos são tão comuns em programação de baixo nível?

  • Porque muitos deles são comuns o suficiente no respectivo domínio para garantir um nome muito curto. Isso piora a curva de aprendizado, mas é uma troca válida, dada a frequência de uso.
  • Porque normalmente existe um pequeno conjunto de possibilidades que é fixo (o programador não pode adicionar ao conjunto).
  • Porque a legibilidade é uma questão de hábito e prática. branch-if-greater-than-or-equal.short é inicialmente mais legível que bge.s , mas com alguma prática a situação se torna inversa.
  • Porque eles geralmente têm que ser digitados na íntegra, à mão, porque as linguagens de baixo nível geralmente não vêm com IDEs poderosos que têm um bom preenchimento automático, ou a / c não é confiável.
  • Por que às vezes é recomendável incluir muitas informações no identificador, e um nome legível seria inaceitavelmente longo até mesmo pelos padrões de alto nível.
  • Porque é isso que os ambientes de baixo nível parecem historicamente. Quebrar o hábito requer esforço consciente, corre o risco de aborrecer aqueles que gostavam dos velhos hábitos e deve ser justificado como valioso. Furar com o caminho estabelecido é o "padrão".
  • Porque muitos deles se originam em outros lugares, como esquemas e planilhas de dados. Aqueles, por sua vez, são afetados por restrições de espaço.
  • Porque as pessoas encarregadas de nomear as coisas nunca consideraram a legibilidade, ou não percebem que estão criando um problema ou são preguiçosas.
  • Porque, em alguns casos, os nomes se tornaram parte de um protocolo para o intercâmbio de dados, como o uso da linguagem assembly como uma representação intermediária por alguns compiladores.
  • Porque esse estilo é instantaneamente reconhecível como de baixo nível e, portanto, parece legal para os geeks.
Pessoalmente, sinto que algumas delas não contribuem realmente para as razões pelas quais um sistema recém-desenvolvido escolheria esse estilo de nomeação, mas senti que seria errado filtrar algumas ideias nesse tipo de resposta.

    
por 27.11.2018 / 11:46
fonte
105

A razão pela qual o software usa esses nomes é porque os registros de dados usam esses nomes. Como o código nesse nível é muito difícil de entender sem a folha de dados, fazer nomes de variáveis que você não pode pesquisar é extremamente inútil.

Isso traz a questão de por que os datasheets usam nomes curtos. Isso é provavelmente porque você precisa apresentar os nomes em tabelas como essa, onde você não tem espaço para identificadores de 25 caracteres:

Além disso, coisas como diagramas esquemáticos, diagramas de pinos e serigrafias de PCBs são muito apertados para o espaço.

    
por 28.08.2012 / 23:57
fonte
59

Lei de Zipf

Você mesmo pode observar, olhando este mesmo texto, que a extensão de palavras e a frequência de uso são, em geral, inversamente relacionadas. Palavras que são usadas com muita frequência, como it , a , but , you e and são muito curtas, enquanto palavras usadas com menos frequência como observe , comprehension e verbosity são mais longos. Essa relação observada entre freqüência e duração é chamada Lei de Zipf .

O número de instruções no conjunto de instruções para um determinado microprocessador geralmente é numerado em dezenas ou centenas. Por exemplo, o conjunto de instruções Atmel AVR parece conter cerca de cem instruções distintas (não contei), mas muitos desses são variações de um tema comum e têm mnemônicos muito semelhantes. Por exemplo, as instruções de multiplicação incluem MUL, MULS, MULSU, FMUL, FMULS e FMULSU. Você não precisa olhar para a lista de instruções por muito tempo antes de obter a ideia geral de que instruções que começam com "BR" são ramificações, instruções que começam com "LD" são cargas etc. O mesmo se aplica às variáveis: mesmo processadores complexos fornecem apenas um número limitado de locais para armazenar valores: registros de condição, registros de propósito geral, etc.

Como há tão poucas instruções e porque os nomes longos demoram mais para serem lidos, faz sentido fornecer nomes abreviados. Por outro lado, linguagens de nível mais alto permitem que os programadores criem um grande número de funções, métodos, classes, variáveis e assim por diante. Cada um deles será usado com muito menos freqüência do que a maioria das instruções de montagem, e nomes mais longos e mais descritivos são cada vez mais importantes para fornecer aos leitores (e escritores) informações suficientes para entender o que são e o que fazem.

Além disso, os conjuntos de instruções para diferentes processadores geralmente usam nomes semelhantes para operações semelhantes. A maioria dos conjuntos de instruções inclui operações para ADD, MUL, SUB, LD, ST, BR, NOP e, se eles não usam esses nomes exatos, geralmente usam nomes muito próximos. Uma vez que você aprendeu os mnemônicos para um conjunto de instruções, não demora muito para se adaptar aos conjuntos de instruções para outros dispositivos. Portanto, nomes que podem parecer "enigmáticos" para você são tão familiares quanto palavras como and , or e not para programadores que são hábeis na arte da programação de baixo nível. Eu acho que a maioria das pessoas que trabalham no nível da montagem lhe diriam que aprender a ler o código não é um dos maiores desafios da programação de baixo nível.

    
por 14.01.2013 / 17:19
fonte
37

Em geral

A qualidade da nomenclatura não é apenas sobre nomes descritivos, mas também para outros aspectos, e isso leva a recomendações como:

  • quanto mais global for o escopo, mais descritivo o nome deve ser
  • quanto mais usado for usado, menor será o nome
  • o mesmo nome deve ser usado em todos os contextos para a mesma coisa
  • coisas diferentes devem ter nomes diferentes, mesmo que o contexto seja diferente
  • as variações devem ser facilmente detectadas
  • ...

Observe que essas recomendações são conflitantes.

mnemônica de instruções

Como um programador de linguagem assembly, usar short-branch-if-greater-or-equal para bge.s me dá a mesma impressão do que quando vejo, como um programador Algol fazendo geometria computacional, 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 em vez de dx := p2.x - p1.x . Eu simplesmente não posso concordar que os primeiros são mais legíveis nos contextos de que me preocupo.

Registre nomes

Você escolhe o nome oficial da documentação. A documentação escolhe o nome do design. O design usa muitos formatos gráficos nos quais os nomes longos não são adequados e a equipe de design terá a vida com esses nomes por meses, se não anos. Por ambos os motivos, eles não usarão o "Interruptor de interrupção do contador do primeiro temporizador", eles serão abreviados em seu esquema e também quando falarem. Eles sabem disso e usam abreviaturas sistemáticas como TIFR1 para que haja menos chance de confusão. Um ponto aqui é que TIFR1 não é uma abreviação aleatória, é o resultado de um esquema de nomenclatura.

    
por 29.08.2012 / 09:56
fonte
24

Além dos motivos dos "velhos hábitos", o código Legacy que foi escrito há 30 anos e ainda está em uso é muito comum. Apesar do que algumas pessoas menos experientes pensam, refatorar esses sistemas para que pareçam bonitos tem um custo muito alto para um pequeno ganho e não é comercialmente viável.

Sistemas incorporados que estão próximos do hardware - e acessam registradores, tendem a usar as mesmas etiquetas ou similares àquelas usadas nas folhas de dados de Hardware, por boas razões. Se o registrador é chamado XYZZY1 nas folhas de dados de hardware, faz sentido que a Variável representando seja provável XYZZY1, ou se o programador estava tendo um bom dia, RegXYZZY1.

No que diz respeito ao bge.s , é semelhante ao assembler - para as poucas pessoas que precisam saber, nomes mais longos são menos legíveis. Se você não consegue fazer a cabeça em torno de bge.s e acha que branch-if-greater-or-equal.short fará diferença - você está apenas jogando com o CLR e não o conhece.

A outra razão pela qual você verá nomes curtos de variáveis se deve à ampla difusão de abreviações dentro do domínio que o software está segmentando.

Em resumo - são esperados nomes de variáveis abreviadas curtas que refletem uma influência Externa, como normas do setor e folhas de dados de hardware. Os nomes curtos de variáveis abreviadas que são internos ao software são normalmente menos desejáveis.

    
por 29.08.2012 / 00:09
fonte
10

Vou jogar meu chapéu nessa bagunça.

Convenções e padrões de codificação de alto nível não são os mesmos padrões e práticas de codificação de baixo nível. Infelizmente, a maioria deles são remanescentes de código legado e processos antigos de pensamento.

Alguns, no entanto, servem a um propósito. Claro que o BranchGreaterThan seria muito mais legível do que BGT , mas há uma convenção lá agora, é uma instrução e como tal ganhou um pouco de tração nos últimos 30 anos de uso como padrão. Por que eles começaram com isso, provavelmente algum limite de largura de caracteres arbitrários para instruções, variáveis e outros; por que eles guardam, é um padrão. Este padrão é o mesmo que usar int como um identificador, seria mais legível usar Integer em todos os casos, mas é necessário para qualquer um que esteja programando mais do que um poucas semanas ... não. Por quê? Porque é uma prática padrão.

Segundo, como eu disse no meu comentário, muitas das interrupções são chamadas de INTG1 e outros nomes crípticos, que também servem a um propósito. Nos diagramas de circuitos não é NÃO uma boa convenção nomear suas linhas e, de forma tão detalhada, desordenar o diagrama e prejudicar a legibilidade. Toda verbosidade é tratada na documentação. E como todos os diagramas de fiação / circuito têm esses nomes curtos para linhas de interrupção, as próprias interrupções também recebem o mesmo nome para manter a consistência do designer incorporado do diagrama de circuito até o código para programá-lo.

Um designer tem algum controle sobre isso, mas, como em qualquer campo / nova linguagem, existem convenções que seguem do hardware ao hardware e, como tal, devem permanecer semelhantes em cada linguagem de montagem. Eu posso olhar para um trecho de montagem e ser capaz de obter a essência do código sem nunca usar esse conjunto de instruções, porque eles se ater a uma convenção, LDA ou alguma relação com ele provavelmente está carregando um registro < strong> MV provavelmente está mudando algo de algum lugar para outro lugar, não é sobre o que você acha que é bom ou é uma prática de alto nível, é uma linguagem em si e como tal tem seus próprios padrões e significa que você como o designer deve seguir, elas nem sempre são tão arbitrárias quanto parecem.

Eu vou deixar você com isto: Pedir à comunidade embarcada para usar práticas verbais de alto nível é como pedir aos químicos que sempre escrevam compostos químicos. O químico as escreve para si e qualquer outra pessoa no campo entenderá, mas pode demorar um pouco para que o recém-chegado se ajuste.

    
por 14.01.2013 / 15:50
fonte
6

Uma razão pela qual eles usam identificadores curtos crípticos é porque eles não são enigmáticos para os desenvolvedores. Você tem que perceber que eles trabalham com isso todos os dias e esses nomes são realmente nomes de domínio. Então eles sabem de cor o que exatamente TIFR1 significa.

Se um novo desenvolvedor vier para a equipe, ele terá que ler as folhas de dados (como explicado por @ KarlBielefeldt) para que elas se sintam confortáveis com elas.

Acredito que a sua pergunta tenha usado um mau exemplo, porque, de fato, nesses códigos-fonte, você geralmente vê muitos identificadores desnecessários de criptografia para coisas que não são de domínio.

Eu diria que eles fazem isso devido a maus hábitos que existiam quando os compiladores não completavam automaticamente tudo que você digita.

    
por 29.08.2012 / 15:47
fonte
5

Resumo

O inicialismo é um fenômeno generalizado em muitos círculos técnicos e não técnicos. Como tal, não se limita à programação de baixo nível. Para a discussão geral, consulte o artigo da Wikipedia sobre o Sigla . Minha resposta é específica para programação de baixo nível.

Causas de nomes crípticos:

  1. Instruções de baixo nível são strongmente tipadas
  2. Precisa reunir muitas informações de tipo no nome de uma instrução de baixo nível
  3. Historicamente, códigos de caracteres únicos são favorecidos para empacotar as informações de tipo.

Soluções e seus inconvenientes:

  1. Existem esquemas modernos de nomenclatura de baixo nível que são mais consistentes do que os históricos.
    • LLVM
  2. No entanto, a necessidade de compactar muitas informações de tipo ainda existe.
    • Assim, abreviações ocultas ainda podem ser encontradas em todos os lugares.
  3. A legibilidade de linha a linha aprimorada ajudará um programador novato de nível inferior a captar a linguagem mais rapidamente, mas não ajudará na compreensão de grandes partes de código de baixo nível.

Resposta completa

(A) Nomes mais longos são possíveis. Por exemplo, os nomes de C ++ SSE2     intrínsecos em média 12 caracteres em comparação com os 7 caracteres     na assembléia mnemônica.      link

(B) A questão então passa para: Quanto tempo / não-enigmático é necessário?     obter instruções de baixo nível?

(C) Agora analisamos a composição de tais esquemas de nomenclatura. A seguir estão dois esquemas de nomenclatura para a mesma instrução de baixo nível:

  • Esquema de nomenclatura # 1: CVTSI2SD
  • Esquema de nomeação # 2: __m128d _mm_cvtsi32_sd (__m128d a, int b);

(C.1) Instruções de baixo nível são sempre strongmente tipadas. Não pode haver        ambigüidade, inferência de tipos, conversão de tipo automática ou        sobrecarga (reutilização do nome da instrução para significar operações semelhantes mas não equivalentes).

(C.2) Cada instrução de baixo nível deve codificar muitas informações de tipo        em seu nome. Exemplos de informação:

  • Família de arquitetura
  • Operação
  • Argumentos (Entradas) e Saídas
  • Tipos (Inteiro Inteiro, Inteiro Não Assinado, Flutuante)
  • Precisão (largura de bit)

(C.3) Se cada informação for explicitada, o programa será        mais detalhado.

(C.4) Os esquemas de codificação de tipos usados por vários fornecedores tinham raízes históricas longas. Como exemplo, no conjunto de instruções x86:

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

Essas referências históricas não tinham significados modernos, mas ainda permanecem por aí. Um esquema mais consistente teria colocado o valor da largura de bits (8, 16, 32, 64, 128) no nome.

Pelo contrário, o LLVM é um passo certo na direção da consistência em instruções de baixo nível: link

(D) Independentemente do esquema de nomes de instruções, programas de baixo nível são      já verboso e difícil de entender, porque eles se concentram no      detalhes minuciosos de execução. Alterando o esquema de nomenclatura de instruções      melhorará a legibilidade em um nível linha a linha, mas não removerá      a dificuldade de compreender as operações de um grande pedaço de      código.

    
por 14.01.2013 / 03:16
fonte
2

Os humanos lêem e escrevem assembly apenas ocasionalmente, e na maioria das vezes é apenas um protocolo de comunicação. Ou seja, é mais frequentemente usado como uma representação baseada em texto serializada intermediária entre o compilador e o montador. Quanto mais detalhada for essa representação, mais sobrecarga desnecessária estará neste protocolo.

No caso de opcodes e nomes de registradores, nomes longos na verdade prejudicam a legibilidade. Mnemônicos curtos são melhores para um protocolo de comunicação (entre compilador e assember), e a linguagem assembly é um protocolo de comunicação na maioria das vezes. Mnemônicos curtos são melhores para programadores, já que o código do compilador é mais fácil de ler.

    
por 13.01.2013 / 12:31
fonte
1

Principalmente é idiomático. Como diz @TMN em outro lugar, assim como você não escreve import JavaScriptObjectNotation ou import HypertextTransferProtocolLibrary no Python, você não escreve Timer1LowerHalf = 0xFFFF em C. Ele parece igualmente ridículo no contexto. Todos que precisam saber já sabem.

A resistência à mudança pode surgir, em parte, do fato de que alguns fornecedores de compiladores C para sistemas embarcados se desviam do padrão e da sintaxe da linguagem para implementar recursos mais úteis à programação incorporada. Isso significa que nem sempre é possível usar o recurso de preenchimento automático do seu IDE ou editor de texto favorito ao escrever código de baixo nível, porque essas personalizações anulam sua capacidade de analisar o código. Daí a utilidade de nomes de registros curtos, macros e constantes.

Por exemplo, o compilador C da HiTech incluiu uma sintaxe especial para variáveis que precisavam ter uma posição especificada pelo usuário na memória. Você pode declarar:

volatile char MAGIC_REGISTER @ 0x7FFFABCD;

Agora, o único IDE existente que analisará isso é o próprio IDE da HiTech ( HiTide ). Em qualquer outro editor, você terá que digitá-lo manualmente, a partir da memória, todas as vezes. Isso envelhece muito rapidamente.

Depois, há também o fato de que, quando você usa ferramentas de desenvolvimento para inspecionar registros, geralmente tem uma tabela exibida com várias colunas (nome do registro, valor em hexadecimal, valor em binário, último valor em hexadecimal etc.) . Nomes longos significam que você precisa expandir a coluna de nome para 13 caracteres para ver a diferença entre dois registradores, e jogar "localize a diferença" em dezenas de linhas de palavras repetidas.

Isso pode parecer bobagem, mas nem todas as convenções de codificação são projetadas para reduzir o cansaço visual, diminuir a digitação supérflua ou abordar qualquer um de milhões de outras queixas menores?

    
por 14.01.2013 / 02:44
fonte
1

Estou surpreso que ninguém tenha mencionado a preguiça e que outras ciências não sejam discutidas. Meu trabalho diário como programador mostra-me que as convenções de nomenclatura para qualquer tipo de variável em um programa são influenciadas por três aspectos diferentes:

  1. A formação científica do programador.
  2. As habilidades de programação do programador.
  3. O ambiente do programador.

Acho que não adianta discutir sobre programação de baixo nível ou alto nível. No final, sempre pode ser atribuído aos três primeiros aspectos.

Uma explicação do primeiro aspecto: Muitos "programadores" não são programadores em primeiro lugar. Eles são matemáticos, físicos, biólogos ou até mesmo psicólogos ou economistas, mas muitos deles não são cientistas da computação. A maioria deles tem suas próprias palavras-chave e abreviações específicas de domínio que você pode ver em suas "convenções" de nomenclatura. Eles são frequentemente presos em seus domínios e usam essas abreviações conhecidas sem pensar em guias de legibilidade ou de leitura.

Uma explicação do segundo aspecto: Como a maioria dos programadores não são cientistas da computação, suas habilidades de programação são limitadas. É por isso que eles geralmente não se importam com convenções de codificação, mas mais com convenções específicas de domínio, conforme declarado como primeiro aspecto. Além disso, se você não tiver as habilidades de um programador, não terá o conhecimento das convenções de codificação. Eu acho que a maioria deles não vê a necessidade urgente de escrever código compreensível. É como fogo e esqueça.

Uma explicação do terceiro aspecto: É improvável que ele trava com as convenções do seu ambiente, que podem ser códigos antigos que você precisa suportar, padrões de codificação de sua empresa (geridos por economistas que não se importam com codificação) ou com o domínio ao qual você pertence. Se alguém começou a usar nomes enigmáticos e você tem que dar suporte a ele ou a seu código, é improvável que você mude os nomes enigmáticos. Se não houver padrões de codificação na sua empresa, aposto que quase todos os programadores escreverão seu próprio padrão. E por último, se você estiver cercado por usuários de domínio, você não começará a escrever outra linguagem que eles usam.

    
por 15.01.2013 / 08:42
fonte