É possível uma linguagem assembly universal para todos os computadores?

23

Gostaria de fazer algumas perguntas sobre a linguagem Assembly. Meu entendimento é que é muito próximo da linguagem de máquina, tornando-a mais rápida e eficiente.

Como temos arquiteturas de computador diferentes, isso significa que tenho que escrever um código diferente no Assembly para arquiteturas diferentes? Em caso afirmativo, por que o Assembly não é, escreva uma vez - execute todo tipo de idioma? Não seria mais fácil simplesmente torná-lo universal, para que você o escreva apenas uma vez e possa executá-lo em praticamente qualquer máquina com configurações diferentes? (Acho que seria impossível, mas gostaria de ter respostas concretas e aprofundadas)

Algumas pessoas podem dizer que C é o idioma que estou procurando. Eu não usei C antes, mas acho que ainda é uma linguagem de alto nível, embora provavelmente seja mais rápida que Java, por exemplo. Eu posso estar errado aqui.

nTuply
fonte
10
Que pesquisa você fez? Esperamos que você faça uma pesquisa antes de perguntar, para ajudá-lo a fazer uma pergunta melhor. Há muitos escritos em linguagem assembly.
DW
4
Esperamos que você faça uma quantidade significativa de pesquisa / auto-estudo antes de perguntar e nos diga na pergunta que pesquisa você fez. Nesse caso, a pesquisa pode incluir a leitura de artigos relevantes da Wikipedia (por exemplo, na linguagem assembly e arquitetura de computadores) e a leitura de um livro didático de arquitetura de computadores. Para tornar essa uma pergunta melhor: faça essa pesquisa, se você ainda não o fez, e edite a pergunta para explicar a pesquisa que você fez. Muitas vezes, esse tipo de pesquisa ajuda a formular uma pergunta melhor; e, de qualquer forma, ajuda os atendentes a evitar repetir o que você já sabe.
DW
15
Comece entendendo que / por que não existe um idioma chamado Assembly.
Raphael
2
Um problema "clássico" da portabilidade C é o tamanho diferente de primitivas (por exemplo, número inteiro) em diferentes hardwares e há outras citadas.
vzn
3
Isso é mais um problema social do que técnico - você precisa convencer todos os fabricantes de CPUs a fazer com que suas CPUs aceitem a mesma linguagem de máquina. (Na verdade, x86 foi quase vai ser isso, por acaso - então smartphones decolou)
user253751

Respostas:

45

A linguagem Assembly é uma maneira de escrever instruções para o conjunto de instruções do computador , de uma maneira um pouco mais compreensível para os programadores humanos.

Arquiteturas diferentes têm conjuntos de instruções diferentes: o conjunto de instruções permitidas é diferente em cada arquitetura. Portanto, você não pode esperar ter um programa de montagem de gravar uma vez, executar em qualquer lugar. Por exemplo, o conjunto de instruções suportadas pelos processadores x86 parece muito diferente do conjunto de instruções suportadas pelos processadores ARM. Se você escrevesse um programa de montagem para um processador x86, ele teria muitas instruções que não são suportadas no processador ARM e vice-versa.

O principal motivo para usar a linguagem assembly é que ela permite um controle de nível muito baixo sobre o seu programa e tira proveito de todas as instruções do processador: personalizando o programa para tirar proveito dos recursos exclusivos do processador em particular. vai funcionar, às vezes você pode acelerar o programa. A filosofia de escrever uma vez, executar em qualquer lugar está fundamentalmente em desacordo com isso.

DW
fonte
1
Eu acho que essa pergunta já foi respondida pelo terceiro parágrafo da minha resposta. Como você disse, esse esquema não seria eficiente; portanto, seria fundamentalmente contrário ao principal motivo para usar a linguagem assembly.
DW
26
@nTuply Assim que você modifica sua linguagem assembly para atender a diferentes máquinas, ela se torna uma linguagem de alto nível com uma sintaxe horrivelmente no estilo assembly. Depois de decidir usar uma linguagem de alto nível, você também pode usar uma com sintaxe mais amigável e deixar o compilador fazer o trabalho duro.
David Richerby
15
Não é uma idéia completamente estúpida ter uma "linguagem assembly" que seja traduzida para diferentes máquinas, porque é basicamente o que é "IR" do LLVM. No entanto, pelas razões que David fornece, você normalmente não escreve um assembly LLVM. Além disso, como 99 vezes em 100, você faria um trabalho pior ao escrevê-lo do que o clang faz da conversão de seu C para LLVM. As linguagens assembly são potencialmente mais eficientes que as linguagens de alto nível, mas nas mãos da maioria dos programadores atuais, com um tempo típico disponível para otimizar, elas não atingem seu potencial de qualquer maneira.
Steve Jessop
9
@ nTuply, isso existe. O processo de passar dessa linguagem extra-assembly para as instruções da máquina é chamado de compilação.
Paul Draper
3
@PJTraill Não há nenhuma razão para escrever um compilador no assembler em um sistema moderno, exceto pela primeira etapa do bootstrap (e na maioria das vezes, nem mesmo assim). Compiladores escritos em uma linguagem de alto nível têm uma probabilidade muito maior de serem realmente mantidos. Compare também Como uma linguagem cujo compilador é escrito em C pode ser mais rápida que C? . O objetivo de um compilador é traduzir de um idioma (o idioma de origem) para outro (geralmente o idioma da máquina para uma arquitetura e sistema operacional específicos); isso pode ser escrito em qualquer idioma.
um CVn
13

A DEFINIÇÃO de linguagem assembly é que é um idioma que pode ser traduzido diretamente em código de máquina. Cada código de operação na linguagem assembly traduz para exatamente uma operação no computador de destino. (Bem, é um pouco mais complicado que isso: alguns montadores determinam automaticamente um "modo de endereçamento" com base em argumentos para um código operacional. Mas, ainda assim, o princípio é que uma linha de montagem se traduz em uma instrução em linguagem de máquina.)

Você poderia, sem dúvida, inventar uma linguagem que se parecesse com linguagem assembly, mas seria traduzida para diferentes códigos de máquina em computadores diferentes. Mas, por definição, isso não seria linguagem assembly. Seria uma linguagem de nível superior que se assemelha à linguagem assembly.

Sua pergunta é como perguntar: "É possível fazer um barco que não flutue ou que tenha outra maneira de atravessar a água, mas que tenha rodas e motor e possa viajar em terra?" A resposta seria que, por definição, esse veículo não seria um barco. Parece mais um carro.

Jay
fonte
1
C tem sido frequentemente descrito como "linguagem assembly portátil".
Larry Gritz
2
@LarryGritz Claro. E quando C foi inventado, foi inovador: ofereceu grande parte do poder da linguagem assembly com a facilidade de uso compilada. Mas, por definição, ainda é uma linguagem compilada.
Jay
8

Não há razão conceitual (eu diria, ciência da computação ) contra ter uma linguagem assembly para todos os computadores do mundo. De fato, isso tornaria muitas coisas muito mais fáceis. No que diz respeito à teoria, eles são todos iguais, de qualquer forma, até algumas bijuterias descoladas.

Na prática, no entanto, existem chips diferentes para diferentes finalidades, com diferentes operações e princípios de design (por exemplo, RISC vs CISC) que atendem a diferentes objetivos, e os conjuntos de instruções que os operam e com as linguagens de montagem diferem. No final, a resposta é a mesma que quando perguntamos por que existem tantas linguagens de programação diferentes: objetivos diferentes, decisões de design diferentes.

Dito isso, é claro que você pode introduzir níveis de abstração para acessar alguma interface compartilhada. O x86, por exemplo, foi eliminado no nível do chip por algum tempo; há um pequeno pedaço de hardware que traduz instruções x86 para o que o seu processador realmente trabalha. Idiomas como C estariam a um passo do hardware (se bem que minúsculo), até linguagens como Haskell, Java ou Ruby. Sim, o compilador é uma das principais realizações da ciência da computação, porque possibilita separar preocupações dessa maneira.

Rafael
fonte
6
"se for discutivelmente pequeno" - existem dois tipos de programadores aqui. Aqueles que consideram C uma linguagem de baixo nível porque suas operações básicas se parecem muito com os tipos de coisas que aparecem nos conjuntos de instruções da CPU, e aqueles que consideram C uma linguagem de alto nível porque não são as mesmas instruções da máquina.
Steve Jessop
Se, por linguagem assembly, você quer dizer um que oferece controle completo sobre o código de máquina gerado para um tipo específico (ou família) de hardware, seria possível definir um idioma "para todos os computadores" em nosso mundo em um determinado momento, mas seria tem que continuar mudando. É certo que (se bem projetado) reduziria a curva de aprendizado para codificação para uma nova arquitetura, mas espero que qualquer trabalho que você queira fazer com ela, em vez de um compilador, se aplique apenas a uma pequena fração das arquiteturas. O fato de os computadores serem iguais em nível abstrato é um arenque vermelho, trata-se de código de máquina.
PJTraill
7

Você menciona a frase "escreva uma vez, execute em qualquer lugar" sem parecer notar seu significado. Esse é o slogan de marketing da Sun Microsystems que inventou comercialmente o conceito de "máquina virtual" e "bytecodes" para Java, embora possivelmente a idéia possa ter se originado na academia 1 st. A idéia foi posteriormente copiada pela Microsoft para .Net depois que eles foram processados ​​com sucesso pela Sun por violação de violação do licenciamento de Java. Bytecodes Java são uma implementação da idéia de montagem entre máquinas ou linguagem de máquina. Eles são usados ​​para várias outras linguagens além do Java e teoricamente podem ser usados ​​para compilar qualquer linguagem. Após muitos anos de otimização muito avançada, o Java se aproxima do desempenho das linguagens compiladas, mostrando que o objetivo da tecnologia de máquina virtual independente de plataforma de alto desempenho é alcançável em geral.

Outra nova idéia, em estágios iniciais / em circulação, relacionada às suas necessidades, é chamada de projeto de recomputação e é para pesquisa científica, embora possa ser usada para outros fins. A idéia é tornar os experimentos computacionais replicáveis ​​via tecnologia de máquina virtual. Essa é principalmente a idéia de simular diferentes arquiteturas de máquinas em hardware arbitrário.

vzn
fonte
8
A Sun não inventou máquinas virtuais ou código de bytes, eles não foram o primeiro grupo a ganhar dinheiro com eles. Procure o código p.
jmoreno 8/09/2015
@moreno: ele também pode querer procurar Smalltalk.
Bob Jarvis - Restabelece Monica
o artigo não reivindica o código de bytes / máquinas virtuais inventado pela sun. existe outra história não citada, mas mencionada. btw outra tecnologia chave muito relevante aqui: google cliente nativo (cromo recurso)
vzn
5

Razões de alto nível

Quando você pensa sobre isso, um microprocessador faz uma coisa incrível: permite pegar uma máquina (como uma máquina de lavar ou um elevador) e substituir um pedaço inteiro de design personalizado mecanismos ou circuitos com uma barata, o silício produzido em massa lasca. Você economiza muito dinheiro em peças e muito tempo em design.

Mas espere, um chip padrão , substituindo inúmeras configurações personalizadas designs ? Não pode haver um único microprocessador perfeito para todas as aplicações. Alguns aplicativos precisam minimizar o uso de energia, mas não precisam ser rápidos; outros precisam ser rápidos, mas não precisam ser fáceis de programar, outros precisam ser de baixo custo etc.

Portanto, temos muitos "sabores" diferentes de microprocessador, cada um com suas próprias forças e fraquezas. É desejável que todos eles usem um conjunto de instruções compatível, pois isso permite a reutilização de código e facilita a localização de pessoas com as habilidades certas. No entanto, o conjunto de instruções não afetar o custo, complexidade, velocidade, facilidade de uso e limitações físicas do processador, e por isso temos um compromisso: há algumas "mainstream" conjuntos de instruções (e muitos outros menores), e dentro de cada conjunto de instruções, existem muitos processadores com características diferentes.

Ah, e à medida que a tecnologia muda, todas essas trocas são alteradas, assim os conjuntos de instruções evoluem, novos surgem e os antigos morrem. Mesmo se houvesse um "melhor" conjunto de instruções de hoje, talvez não seja daqui a 20 anos.

Detalhes de hardware

Provavelmente, a maior decisão de design em um conjunto de instruções é o tamanho da palavra , ou seja, qual o número que o processador pode "naturalmente" manipular. Os processadores de 8 bits lidam com números de 0 a 255, enquanto os de 32 bits lidam com números de 0 a 4.294.967.295. O código projetado para um precisa ser completamente repensado para outro.

Não se trata apenas de traduzir instruções de uma instrução definida para outra. Uma abordagem completamente diferente pode ser preferível em um conjunto de instruções diferente. Por exemplo, em um processador de 8 bits, uma tabela de pesquisa pode ser ideal, enquanto em um processador de 32 bits uma operação aritmética seria melhor para a mesma finalidade.

Existem outras grandes diferenças entre os conjuntos de instruções. A maioria das instruções se enquadra em quatro categorias:

  • Computação (aritmética e lógica)
  • Controle de fluxo
  • Transferência de dados
  • Configuração do processador

Os processadores diferem em que tipo de computação eles podem executar, bem como em sua abordagem do fluxo de controle, transferência de dados e configuração do processador.

Por exemplo, alguns processadores AVR não podem se multiplicar nem dividir; enquanto todos os processadores x86 podem. Como você pode imaginar, a eliminação do circuito necessário para tarefas como multiplicação e divisão pode tornar um processador mais simples e mais barato; essas operações ainda podem ser executadas usando rotinas de software, se forem necessárias.

O x86 permite instruções aritméticas para carregar seus operandos da memória e / ou salvar seus resultados na memória; O ARM é uma arquitetura de armazenamento de carga e, portanto, possui apenas algumas instruções dedicadas para acessar a memória. Enquanto isso, o x86 tem instruções de ramificação condicional dedicadas, enquanto o ARM permite praticamente todas instruções sejam executadas condicionalmente. Além disso, o ARM permite a troca de bits como parte da maioria das instruções aritméticas. Essas diferenças levam a diferentes características de desempenho, diferenças no design interno e no custo dos chips e diferenças nas técnicas de programação no nível da linguagem assembly.

Conclusão

A razão pela qual é impossível ter uma linguagem assembly universal é que, para converter adequadamente o código do assembly de um conjunto de instruções para outro, é necessário projetar o código novamente - algo que os computadores ainda não podem fazer.

Artelius
fonte
Excelente resposta! As pessoas não entendem bem o suficiente que coisas de computação que precisam ser programadas estão por toda parte entre nós. Não são apenas os aplicativos que vemos rodando em nossas telas. Quantos bilhões de chips são fabricados a cada ano?
Phs
4

Acrescentando a maravilhosa resposta da DW: se você gostaria de ter um montador, seria necessário manter todas as arquiteturas, um tradutor perfeito entre elas e entender completamente o que você está fazendo.
Alguns códigos altamente otimizados por uma arquitetura precisariam ser otimizados, entendidos em um nível mais abstrato e otimizados por outra.
Mas se isso fosse possível, teríamos um compilador C perfeito, e escrever em montagem pura não seria benéfico.
O ponto principal do uso do assembler é o desempenho, que não pode ser extraído dos compiladores recentes.
Escrever esse programa seria ainda mais difícil do que os compiladores existentes, e manter todas as novas arquiteturas que estão sendo criadas tornaria ainda mais difícil.
E para um programa "apenas um", isso também significaria total compatibilidade com versões anteriores.

Mal
fonte
Para a grande maioria dos casos, o gcc realiza uma otimização melhor do que um programador. O ponto principal do uso do assembler é fazer coisas que você não pode fazer em C, como acessar registros. Se você olhar para a árvore de código-fonte do Linux, é para isso que eles usam o assembly.
slebetman 8/09/2015
@slebetman - gcc permite que você coloque uma variável em um registro sem recorrer à montagem.
Jirka Hanika #
@JirkaHanika: você está falando sobre registros de CPU ou registros de hardware para uso específico, endereçados com instruções especiais? Eu suspeito que slebetman significa o último.
PJTraill
"Todos os códigos" - "O GCC se sai melhor" = "você usa o assembler". Sim, você pode acessar registros sem inserções de assembler.
Mal
@PJTraill - O comentário de Slebetman geralmente é excelente e talvez deva ser incorporado à resposta. Porém, seus dois exemplos (acesso ao registro e árvore de código-fonte do Linux) provavelmente alimentam conceitos errôneos comuns, em vez de serem excelentes exemplos do que não se pode fazer em C com extensões gcc; esses devem ser substituídos ou omitidos. (Se há uma instrução HW fazer alguma coisa hoje, você terá a extensão gcc correspondente de um ano a partir de agora Nem sempre, mas muitas vezes Exemplos idade...)
Jirka Hanika
3

A Microsoft inventou o MSIL para ser uma linguagem assembly intermediária. Os programas seriam compilados de C # ou VB.Net para MSIL. No tempo de execução, o MSIL foi compilado no código da máquina que a executava usando um compilador JIT . O arquivo que contém o MSIL era um arquivo .exe com algumas instruções no início do X86 para iniciar o programa. Em um processador ARM, você digitaria a palavra mono na frente do nome do programa para executá-lo.

Russell Harkins
fonte
Qual é a diferença entre "linguagem assembly intermediária" e "máquina virtual"?
Bob Jarvis - Restabelece Monica
@ BobJarvis: um é código, enquanto o outro é intérprete. Você deveria ter perguntado qual é a diferença entre a montagem intermediária e bytecode
slebetman
Isso não parece responder à pergunta. Enquanto cada máquina compila / monta o MSIL de maneira diferente, não há nada de universal nisso, e o objetivo dessa compilação é portar funcionalidades genéricas e não explorar um conjunto de instruções específico que, como DW ressalta, é o (ou a) razão para usar o assembler.
PJTraill
3

Como observado, o LLVM é a coisa mais próxima disso até agora. Uma grande barreira para uma linguagem realmente universal será as diferenças fundamentais relacionadas às trocas implícitas: simultaneidade, uso de memória, taxa de transferência, latência e consumo de energia. Se você escrever em um estilo explicitamente SIMD, poderá estar usando muita memória. Se você escrever em um estilo SISD explicitamente, obterá uma paralelização abaixo do ideal. Se você otimizar a taxa de transferência, prejudicará a latência. Se você maximizar a taxa de transferência de thread único (ou seja: velocidade do relógio), você prejudicará a vida da bateria.

No mínimo, o código precisaria ser anotado com as compensações. O que pode ser mais importante é que o idioma tenha boas propriedades algébricas / de tipo que dão ao compilador muito espaço de manobra para otimizar e detectar inconsistência lógica.

Depois, há a questão do comportamento indefinido. Grande parte da velocidade das linguagens C e assembly vem de um comportamento indefinido. Se você admitir um comportamento indefinido que realmente acontece, acabará tratando-o como casos especiais (ou seja: arquitetura e hackers específicos ao contexto).

Roubar
fonte
0

Talvez o que você está procurando seja uma notação da Universal Turning Machine, onde todos concordam com os símbolos dos comandos. ( https://en.wikipedia.org/wiki/Universal_Turing_machine )

Um 'assembler' que traduz um idioma Turning Acceptable para o código de máquina específico do fornecedor subjacente e é compilado para qualquer uma dessas coisas que chamamos de computadores.

Em A arte da programação de computadores, há um exemplo de como isso pode ser.

Mas considere a pergunta "por que não é uma linguagem universal disponível comercialmente que possa ser usada com todos os computadores"? Sugiro que as influências mais dominantes sejam: (1) conveniência, nem todas as linguagens assembly são as mais convenientes de usar; (2) economia, fornecendo incompatibilidade entre máquinas de diferentes marcas e fornecedores, é uma estratégia comercial, bem como o resultado de recursos limitados (tempo / dinheiro) para projetar máquinas.

Chris
fonte
A pergunta é sobre uma linguagem assembly que pode ser usada para programar qualquer computador, não uma linguagem assembly universal no sentido de "máquina de Turing universal".
precisa saber é o seguinte
1
Church-Turing nos diz que o UTC pode fazer o que qualquer computador programável pode fazer. Além de problemas finitos de armazenamento físico. Uma linguagem assembly para um UTC é bastante viável. Mas, como eu disse, a praticidade cultural e econômica pode limitar a implementação e adoção reais no mercado.
Chris
Você está perdendo o maior problema, que é o desempenho ! Por que usar uma linguagem milhares de vezes mais lenta apenas para um objetivo elevado de ser independente de hardware? A máquina de Turing é um modelo terrível para a computação prática.
Artelius 9/09/15
1
Os comentaristas gostariam de oferecer qualquer ciência da computação para apoiar suas reivindicações? Afinal, este é o fórum de ciência da computação.
Chris
1
Eu não sou um especialista em CS. Mas o que eu acredito é que a arquitetura von Neumann é uma brilhante peça de engenharia que encontra um equilíbrio entre programabilidade e desempenho, enquanto o objetivo da máquina de Turing é mostrar que mesmo a máquina mais básica pode computar tudo o que uma máquina mais complexa poderia. Certamente, você pode continuar adicionando mais e mais recursos a uma máquina de Turing (mais fitas, aritmética), mas depois obtém o mesmo problema que teve em primeiro lugar, ou seja, pessoas que não concordam com um conjunto de instruções. Além disso, a falta de acesso aleatório cria grandes despesas gerais em muitos algoritmos.
Artelius 12/09
0

suposição: compilar e otimizar uma linguagem de alto nível L1 para uma linguagem de nível inferior L0 é mais fácil do que compilar e otimizar uma linguagem de alto nível L2 (maior que L1) para L0; mais fácil no sentido em que você supostamente pode gerar um código mais otimizado ao compilar L1 a L0 do que L2 a L0.

Eu acho que a suposição provavelmente está correta, é por isso que provavelmente a maioria dos compiladores usa uma linguagem intermediária de baixo nível (IR / LLVM).

se isso for verdade, use qualquer idioma de baixo nível L0 e escreva compiladores para traduzir L0 para outros idiomas de baixo nível. Por exemplo, use o conjunto de instruções MIPS e compile-o para x86, arm, power, ...

-Taoufik

Taoufik Dachraoui
fonte
Então você não sabe se a sua resposta é verdadeira? E não pode suportar isso?
Mal