Eu tenho programado em linguagens de nível superior (Python, C #, VBA, VB.NET) há cerca de 10 anos e não entendo completamente o que está acontecendo, "sob o capô".
Gostaria de saber quais são os benefícios de aprender montagem, e como isso me ajudará como programador? Você pode me fornecer um recurso que me mostre exatamente a conexão entre o que eu escrevo no código de nível superior e o que acontece na montagem?
for
loop declarando variáveis fora dele. exemploRespostas:
Porque você entenderá como realmente funciona.
O que se resume é que todas as coisas que escrevemos em C # ou Python precisam ser traduzidas em uma sequência de ações básicas que um computador pode executar. É fácil pensar em um computador em termos de classes, genéricos e compreensão de lista, mas eles só existem em nossas linguagens de programação de alto nível.
Podemos pensar em construções de linguagem que parecem realmente boas, mas que não se traduzem muito bem em uma maneira de fazer coisas de baixo nível. Ao saber como realmente funciona, você entenderá melhor por que as coisas funcionam da maneira que funcionam.
fonte
Isso lhe dará uma melhor compreensão do que está acontecendo "oculto" e como os ponteiros funcionam e o significado das variáveis e da arquitetura do registro (alocação e gerenciamento de memória, passagem de parâmetros (por valor / por referência), etc) em geral.
Para uma rápida olhada em C, como é isso?
compile
gcc -S so.c
e dê uma olhada na saída do assembly emso.s
:fonte
so.c
arquivo padrão para perguntas sobre o stackoverflow (como eu tenhoso.py
,so.awk
etc.) para testar as coisas rapidamente. So.S .. :)gcc -O -c -g -Wa,-ahl=so.s so.c
poderá ver a saída do assembly para cada linha do código C. Isso facilita um pouco a compreensão do que está acontecendo.5:so.c
encontrar o código da linha 5 deso.c
.Acho que a resposta que você procura está aqui: http://www.codeproject.com/Articles/89460/Why-Learn-Assembly-Language
Uma citação do artigo:
Além disso, eu recomendaria este livro porque ele tem uma versão simplificada da arquitetura de computadores: Introdução aos sistemas de computação: de bits e portas a C e além, 2 / e Yale N. Patt, Universidade do Texas em Austin Sanjay J. Patel, Universidade de Illinois em Urbana-Champaign
fonte
Na minha humilde opinião, isso não ajuda muito.
Eu conhecia muito bem a montagem x86. Ajudou um pouco quando a montagem surgiu nos meus cursos, surgiu uma vez durante uma entrevista e me ajudou a provar que um compilador (Metrowerks) estava gerando código incorreto. É fascinante como o computador realmente funciona, e me sinto intelectualmente mais rico por tê-lo aprendido. Também foi muito divertido de brincar na época.
No entanto, os compiladores de hoje são melhores na geração de assembly do que quase qualquer um em praticamente qualquer parte do código. A menos que você esteja escrevendo um compilador ou verificando se está fazendo a coisa certa, provavelmente está perdendo seu tempo aprendendo.
Admito que muitas perguntas que os programadores de C ++ ainda façam com utilidade são informadas pelo conhecimento da montagem. Por exemplo: devo usar variáveis de pilha ou pilha? devo passar por valor ou por referência const? Em quase todos os casos, no entanto, acho que essas escolhas devem ser feitas com base na legibilidade do código e não na economia de tempo computacional. (Por exemplo, use variáveis de pilha sempre que quiser limitar uma variável a um escopo.)
Minha humilde sugestão é focar em habilidades que realmente importam: design de software, análise de algoritmos e solução de problemas. Com a experiência no desenvolvimento de grandes projetos, sua intuição irá melhorar, o que aumenta seu valor muito mais do que conhecer montagem (na minha opinião).
fonte
Você deve estar familiarizado com um nível 'mais profundo' no sistema em que está trabalhando. Pular muito longe de uma só vez não é ruim, mas pode não ser tão útil quanto se poderia desejar.
Um programador em um idioma de alto nível deve aprender um idioma de nível inferior (C é uma excelente opção). Você não precisa ir até a montagem para apreciar o que acontece embaixo das cobertas quando diz ao computador para instanciar um objeto ou criar uma tabela de hash ou um conjunto - mas deve poder codificar eles.
Para um programador java, aprender um pouco de C ajudaria você no gerenciamento de memória, passando argumentos. Escrever algumas das extensas bibliotecas java em C ajudaria a entender quando usar qual implementação do Set (você quer um hash? Ou árvore?). Lidar com char * em um ambiente encadeado ajudará a entender por que String é imutável.
Levado para o próximo nível ... O programador de CA deve ter alguma familiaridade com a montagem, e os tipos de montagem (geralmente encontrados em lojas de sistemas embarcados) provavelmente farão bem em entender as coisas no nível das portas. Quem trabalha com portões deve conhecer um pouco de física quântica. E esses físicos quânticos, bem, eles ainda estão tentando descobrir qual é a próxima abstração.
fonte
Como você não mencionou C ou C ++ nos idiomas que você conhece. Eu recomendaria enfaticamente aprendê-los bem antes mesmo de pensar em montagem. C ou C ++ fornecerá todos os conceitos básicos que são totalmente transparentes nas linguagens gerenciadas e você entenderá a maioria dos conceitos mencionados nesta página com uma das linguagens mais importantes que você pode usar em projetos do mundo real. É um verdadeiro valor agregado para suas habilidades de programação. Por favor, esteja ciente de que a montagem é usada em áreas muito específicas e não é tão útil quanto C ou C ++.
Eu diria ainda mais que você não deve mergulhar na montagem antes de entender como as linguagens não gerenciadas funcionam. É quase uma leitura obrigatória.
Você deve aprender montagem se quiser ir ainda mais longe. Você quer saber exatamente como cada construção da linguagem é criada. É informativo, mas é uma complexidade de nível totalmente diferente.
fonte
Se você conhece bem um idioma, deve ter pelo menos conhecimento básico da tecnologia em um nível de abstração menor.
Por quê? Quando as coisas dão errado, o conhecimento da mecânica subjacente facilita muito a depuração de problemas estranhos e, naturalmente, a criação de códigos mais eficientes.
Usando o Python (/ CPython) como exemplo, se você começar a ter falhas estranhas ou baixo desempenho, o conhecimento de como depurar o código C pode ser muito útil, assim como o conhecimento do método de gerenciamento de memória de ref-counting. Isso também ajudaria você a saber quando / se escrever algo como uma extensão C e assim por diante ...
Para responder à sua pergunta nesse caso, o conhecimento de montagem realmente não ajudaria um desenvolvedor Python experiente (há muitas etapas na abstração - tudo o que é feito no Python resultaria em muitas instruções de montagem)
..mas, se você tem experiência com C, conhecer o "próximo nível abaixo" (montagem) seria realmente útil.
Da mesma forma, se você estiver usando o CoffeScript, é (muito) útil conhecer o Javascript. Se você estiver usando o Clojure, o conhecimento de Java / JVM é útil.
Essa ideia também funciona fora das linguagens de programação - se você estiver usando o Assembly, é uma boa idéia estar familiarizado com o funcionamento do hardware subjacente. Se você é um web designer, é uma boa ideia saber como o aplicativo da web é implementado. Se você é mecânico de automóveis, é uma boa ideia ter algum conhecimento de física
fonte
Escreva um programa c pequeno e desmonte a saída. Isso é tudo. No entanto, esteja preparado para um maior ou menor grau de código de "limpeza" que é adicionado para o benefício do sistema operacional.
O Assembly ajuda a entender o que está acontecendo sob o capô, porque lida diretamente com memória, registros do processador e similares.
Se você realmente deseja usar o metal sem toda a complexidade de um sistema operacional, dificultando as coisas, tente programar um Arduino na linguagem assembly.
fonte
Não há resposta definitiva, pois os programadores não são de um tipo. Você precisa saber o que se esconde por baixo? Se sim, aprenda. você apenas quer aprender por curiosidade? Se sim, aprenda. Se não terá nenhum benefício prático para você, por que se preocupar? É necessário o nível de conhecimento de um mecânico apenas para dirigir um carro? Um mecânico precisa do nível de conhecimento de um engenheiro, apenas para trabalhar em um carro? Esta é uma analogia séria. Um mecânico pode ser um mecânico muito bom e produtivo sem mergulhar para entender profundamente os veículos que ele mantém. O mesmo para a música. Você realmente entende as complexidades da melodia, harmonia e ritmo para ser um bom cantor ou jogador? Não. Alguns músicos excepcionalmente talentosos não conseguem ler uma partitura, muito menos dizer a diferença entre os modos Dorian e Lydian. Se você quiser, tudo bem, mas não, você não precisa. Se você é um desenvolvedor web, a montagem não tem uso prático que eu possa pensar. Se você estiver em sistemas embarcados ou algo realmente especial, pode ser necessário, mas se fosse, você saberia.
Aqui está a opinião de Joel sobre o valor de se apoiar uma linguagem de nível não alto: http://www.joelonsoftware.com/articles/ThePerilsofJavaSchools.html
fonte
Na verdade, o que provavelmente seria melhor para você seria uma classe que (ao meu conhecimento) não existe em nenhum lugar: seria uma classe que combina uma breve visão geral da linguagem de máquina / montador e conceitos de endereçamento de armazenamento com um tour pela construção do compilador , geração de código e ambientes de tempo de execução.
O problema é que, com uma linguagem de alto nível e longe do hardware, como C # ou Python, você realmente não aprecia o fato de que cada movimento que você faz se transforma em centenas, senão milhares de instruções de máquina, e você não tendem a compreender como algumas linhas de uma linguagem de alto nível podem fazer com que grandes quantidades de armazenamento sejam acessadas e modificadas. Não é tanto que você precise saber exatamente o que está acontecendo "debaixo das cobertas", mas você precisa apreciar o escopo do que está acontecendo e uma concepção geral dos tipos de coisas que ocorrem.
fonte
Minha resposta a essa pergunta evoluiu relativamente recentemente. As respostas existentes cobrem o que eu teria dito no passado. Na verdade, isso ainda está coberto pela resposta principal - o ponto "aprecio as construções na programação de nível superior", mas é um caso especial que acho que vale a pena mencionar ...
De acordo com esta postagem no blog de Jeff Atwood , que faz referência a um estudo, entender a atribuição é uma questão fundamental para entender a programação. Os programadores aprendizes entendem que a notação representa apenas as etapas que o computador segue e justifica as etapas, ou então ficam perpetuamente confusos por analogias enganosas às equações matemáticas etc.
Bem, se você entende o seguinte do 6502 assembler ...
Isso é realmente apenas os passos. Então, quando você aprender a traduzir isso para uma declaração de atribuição ...
Você não precisa de uma analogia enganosa para uma equação matemática - você já tem um modelo mental correto para o qual mapear.
EDIT - é claro que se a explicação
LDA variable
é basicamenteACCUMULATOR = variable
, e é exatamente o que você obtém de alguns tutoriais e referências, você volta ao ponto em que começou e não ajuda em nada.Eu aprendi 6502 assembler como minha segunda língua, o primeiro sendo o Commodore Basic, e eu realmente não tinha aprendido muito disso na época - em parte porque havia muito pouco a aprender, mas também porque assembler parecia muito mais interessante naquela época . Em parte as vezes, em parte porque eu era um nerd de 14 anos.
Não recomendo fazer o que fiz, mas me pergunto se o estudo de alguns exemplos muito simples em uma linguagem assembler muito simples pode ser uma preliminar interessante para aprender idiomas de nível superior.
fonte
A menos que você seja um escritor de compilador ou precise de algo altamente otimizado (como algoritmo de processamento de dados), aprender a codificar assembly não fornecerá nenhum benefício.
Escrever e manter o código escrito no assembly é muito difícil, portanto, mesmo se você conhece muito bem a linguagem assembler, não deve usá-lo, a menos que não haja outras maneiras.
O artigo " Otimizando para SSE: um estudo de caso " mostra o que é possível fazer se você for à montagem. O autor conseguiu otimizar o algoritmo de 100 ciclos / vetor para 17 ciclos / vetor.
fonte
Escrever em montagem não daria a você um aumento mágico de velocidade, devido à quantidade de detalhes (alocação de registro etc.), você provavelmente escreverá o algoritmo mais trivial de todos os tempos.
Além disso, com a montagem de processadores modernos (lida - projetada após os anos 70-80) não fornecerá um número suficiente de detalhes para saber o que está acontecendo (isto é - na maioria dos processadores). As PU modernas (CPUs e GPUs) são bastante complexas no que diz respeito às instruções de programação. Conhecer os conceitos básicos de montagem (ou pseudo-montagem) permitirá entender os livros / cursos de arquitetura de computadores que forneceriam conhecimento adicional (caches, execução fora de ordem, MMU etc.). Normalmente você não precisa conhecer o ISA complexo para entendê-los (o MIPS 5 é bastante popular no IIRC).
Por que entender processador? Isso pode lhe dar muito mais entendimento do que está acontecendo. Digamos que você escreva multiplicação de matrizes de maneira ingênua:
Pode ser 'bom o suficiente' para o seu objetivo (se for uma matriz 4x4, pode ser compilado para instruções vetoriais de qualquer maneira). No entanto, existem programas muito importantes quando você compila matrizes maciças - como otimizá-las? Se você escrever o código no assembly, poderá obter alguns% de melhoria (a menos que faça o que a maioria das pessoas faz - também de maneira ingênua, subutilizando registros, carregando / armazenando na memória constantemente e, com efeito, tendo um programa mais lento do que na linguagem HL) .
No entanto, você pode reverter duas linhas e obter desempenho magicamente (por que? Deixo como 'lição de casa') - o IIRC, dependendo de vários fatores para matrizes grandes, pode ser até 10x.
Dito isto - há trabalhos em compiladores capazes de fazê-lo ( grafite para gcc e Polly para qualquer coisa usando LLVM). Eles são capazes de transformá-lo em (desculpe - estou escrevendo bloqueando a memória):
Para resumir, o conhecimento básico de uma montagem permite que você explore vários 'detalhes' do design do processador, o que permitiria escrever programas mais rápidos. Talvez seja bom conhecer as diferenças entre as arquiteturas RISC / CISC ou VLIW / processador de vetor / SIMD / .... No entanto, eu não começaria com x86, pois eles tendem a ser bastante complicados (possivelmente ARM também) - saber o que é um registro etc. é IMHO suficiente para iniciar.
fonte
Normalmente, é MUITO importante para fins de depuração. O que você faz quando o sistema quebra no meio de uma instrução e o erro não faz sentido? É muito menos um problema com as linguagens .NET, desde que você esteja usando apenas código seguro - o sistema quase sempre o protege do que está acontecendo sob o capô.
fonte
Em suma, acho que a resposta é porque você pode fazer mais se aprender montagem. Aprender montagem concede acesso às áreas de programação de dispositivos incorporados, penetração e evasão de segurança, engenharia reversa e programação de sistemas que são muito difíceis de trabalhar se você não conhece o montador.
Quanto a aprender a melhorar o desempenho do programa, isso é duvidoso na programação de aplicativos. Na maioria das vezes, há muitas coisas para focar antes de atingir esse nível de otimização, como otimizar seu acesso de E / S no disco e na rede, otimizar como você cria a GUI, escolher os algoritmos certos e maximizar todos os seus núcleos , rodando com o melhor hardware que o dinheiro pode comprar e mudar de idiomas interpretados para compilados. A menos que você esteja criando software para outros usuários finais, o hardware é barato comparado ao salário por hora de um programador, especialmente com a disponibilidade da nuvem.
Além disso, você deve ponderar o aumento da velocidade de execução do programa com a legibilidade do seu código depois de ser atropelado por um ônibus, sair ou voltar à base de códigos para alterá-lo um ano depois de escrever a última versão.
fonte
Eu recomendaria aprender algoritmos: classificação, listas vinculadas, árvores binárias, hash, etc.
Aprenda também lisp, ver Estrutura e interpretação de programas de computador groups.csail.mit.edu/mac/classes/6.001/abelson-sussman-lectures. Este curso em vídeo ensinará tudo o que você precisa saber, incluindo algoritmos (como fazer tudo com base em alguns comandos primitivos, um cego primitivo e alguns provocadores montadores).
Finalmente, se você precisa aprender o assembler, aprenda um fácil como o ARM (também é usado em cerca de 4 vezes mais dispositivos que o x86).
fonte
Bem, a resposta é que simplesmente porque o idioma que você está usando deve ser interpretado ou compilado no assembler no final. Não importa o idioma ou a máquina.
O design das linguagens deriva da maneira como a CPU funciona. Mais sobre programas de baixo nível, menos sobre programas de alto nível.
Terminarei dizendo que não é apenas necessário conhecer pouco assembler, mas também a arquitetura da CPU, que você aprende aprendendo assembler.
Alguns exemplos: existem muitos programadores java que não entendem por que isso não funciona e muito menos que sabem o que acontece quando você o executa.
Se você conhecesse um pequeno assembler, sempre saberia que não é o mesmo que o conteúdo de um local de memória versus o número na variável de ponteiro que "aponta" para esse local.
Pior ainda, mesmo em livros publicados, você lerá algo como nas primitivas JAVA que são passadas por valor e objetos por referência, o que é completamente incorreto. Todos os argumentos em Java são passados por valor, e Java NÃO pode passar objetos para funções, apenas ponteiros, que são passados por valor.
Se você agora monta seu óbvio o que está acontecendo, se não, é tão complicado explicar que a maioria dos autores apenas lhe dá uma mentira piedosa.
Obviamente, as implicações disso são sutis, mas podem causar problemas reais mais tarde. Se você sabe que o assembler é um problema, se não, você terá uma longa e longa noite de depuração.
fonte
String a = "X"; String b = "X"; if( a==b) return true;
que realmente acontece por== true
causa de algo chamadoString interning
que o compilador faz. Todas as outras instruções Java também estão erradas. Java não possui ponteiros, possui referências que não são a mesma coisa. E nada disso tem a ver com montador de qualquer maneira. Java transmite primitivas por valor, bem como referências por valor. Java não tem ponteiros, portanto não pode passar por nada. Novamente todos irrelevantes para conhecer o ASM.