Montador | ||
Data da primeira versão | 1949 | |
---|---|---|
Extensão de arquivo | asm e s | |
Uma linguagem assembly ou linguagem assembly é, na programação de computadores , a linguagem de nível mais baixo que representa a linguagem de máquina em uma forma legível por humanos. As combinações de bits de linguagem de máquina são representadas pelos chamados símbolos “ mnemônicos ” , ou seja, fáceis de lembrar. O programa de montagem converte esses mnemônicos em linguagem de máquina, bem como os valores (escritos em decimal) em binários e os rótulos das localizações em endereços, com o objetivo de criar, por exemplo, um arquivo-objeto ou um arquivo executável .
Na prática atual, o mesmo termo assembler é usado para designar a linguagem assembly e o programa de montagem que a traduz. Portanto, falamos de “programação em assembler”.
A tradução de uma vez por todas por muitos intérpretes de cada nome de variável encontrado em uma instrução (avançada) pela posição de memória associada e de cada constante (escrita pelo usuário em decimal) em binário é típica de uma operação d. ' O montador de nomes não é comumente usado neste caso particular.
Os programas do EDSAC (1949), o primeiro computador com programas gravados , foram escritos usando mnemônicos alfabéticos de uma letra para cada instrução. A tradução foi então feita manualmente pelos programadores, uma operação longa, tediosa e sujeita a erros.
O primeiro programa de montagem foi escrito por Nathaniel Rochester para o IBM 701 (o primeiro computador lançado pela IBM ) em 1954.
As linguagens assembly eliminaram muitos dos erros cometidos pelos programadores da primeira geração de computadores, dispensando a necessidade de memorizar os códigos numéricos das instruções e de fazer cálculos de endereços. A programação assembly foi então usada para escrever todos os tipos de programas.
Nas décadas de 1970 e 1980, o uso de assembler para escrever aplicativos foi amplamente suplantado pelo uso de linguagens de programação de alto nível: Fortran , COBOL , PL / I , etc. : o poder das máquinas o permitia e dedicar alguns minutos do tempo do computador a uma compilação para economizar algumas horas do tempo do programador era uma operação lucrativa, mesmo que os compiladores da época fornecessem códigos menos eficientes (maiores e muitas vezes mais lentos). Além disso, essas linguagens de alto nível possibilitaram superar a dependência de uma única arquitetura de hardware.
Os sistemas operacionais foram escritos em linguagem assembly até a introdução do MCP para Burroughs em 1961, que foi escrito em ESPOL, um dialeto de Algol .
A montadora voltou um pouco a favor dos primeiros microcomputadores, onde as características técnicas (tamanho reduzido da memória, baixo poder de computação, arquitetura de memória específica, etc.) impunham fortes restrições, às quais se acrescenta um fator psicológico importante, a atitude "amadora" dos primeiros usuários de microcomputadores, que não se contentavam com a lentidão dos programas escritos com o BASIC interpretado geralmente fornecido com o computador.
Grandes programas foram escritos inteiramente em montagem para microcomputadores, como o sistema operacional DOS do IBM PC (cerca de 4000 linhas de código) e a planilha Lotus 1-2-3 (seu rival Multiplan, que já existia sob CP / M , era escrito em C ). Na década de 1990, isso também acontecia com a maioria dos jogos para consoles de vídeo (por exemplo, para o Mega Drive ou o Super Nintendo ).
A linguagem de máquina é a única linguagem que um processador pode executar. No entanto, cada família de processadores usa um conjunto diferente de instruções .
Por exemplo, um processador da família x86 reconhece uma instrução do tipo:
10110000 01100001Na linguagem assembly, esta instrução é representada por um equivalente mais fácil de entender para o programador:
movb $0x61,%al(10110000 = movb% al
01100001 = $ 0x61)
O que significa: "escreva o número 97 (o valor é dado em hexadecimal : 61 16 = 97 10 ) no registro AL".
Assim, a linguagem assembly, uma representação exata da linguagem de máquina, é específica para cada arquitetura de processador . Além disso, vários grupos de mnemônicos ou sintaxes de linguagem assembly podem existir para um único conjunto de instruções, criando assim macroinstruções .
A transformação do código assembly em linguagem de máquina é realizada por um programa denominado programa assembly . A operação inversa , ou seja, encontrar o montador equivalente a um pedaço de código de máquina, tem um nome: é desmontagem .
Ao contrário do que se possa pensar, nem sempre há uma correspondência um-para-um (uma bijeção ) entre o código assembly e a linguagem de máquina. Em alguns processadores, a desmontagem pode, portanto, resultar em um código que é muito difícil para um ser humano entender, embora permaneça perfeitamente compilável por um computador. A impossibilidade de uma desmontagem pode ter vários motivos: uso de código auto-modificador, instruções de tamanho variável, impossibilidade de distinção entre código e dados, etc. ( código impenetrável )
Além disso, muitos elementos presentes no código assembly são perdidos durante sua tradução para a linguagem de máquina. Ao criar código em assembler, o programador pode atribuir nomes a posições na memória, comentar seu código , usar macro-instruções ou usar código gerado sob condições no momento da montagem. Todos esses elementos são reduzidos durante a montagem ao estritamente necessário para a máquina e, portanto, não aparecem claramente durante a desmontagem: por exemplo, uma posição na memória é marcada apenas por seu endereço numérico ou por um deslocamento .
Algumas operações fundamentais estão disponíveis na maioria dos conjuntos de instruções.
E há instruções específicas com uma ou algumas instruções para operações que deveriam ter levado muito. Exemplos:
Além de codificar instruções de máquina, as linguagens de montagem têm diretivas adicionais para montar blocos de dados e atribuir endereços a instruções por meio da definição de tags ou rótulos.
Eles são capazes de definir expressões simbólicas que são avaliadas em cada montagem, tornando o código ainda mais fácil de ler e entender.
Eles geralmente têm uma linguagem de macro embutida para facilitar a geração de códigos complexos ou blocos de dados.
Aqui estão alguns exemplos simples:
(Os comentários estão após ponto e vírgula)
str: .ascii "Bonjour\n" .global _start _start: movl $4, %eax movl $1, %ebx movl $str, %ecx movl $8, %edx int $0x80 movl $1, %eax movl $0, %ebx int $0x80 ;Compilation: ;as code.s -o code.o ;ld code.o -o code ;Execution: ;./codeAqui estão os mesmos exemplos, com algumas diferenças:
(Os comentários estão após ponto e vírgula)
section .data ; Variables initialisées Buffer: db 'Bonsoir', 10 ; En ascii, 10 = '\n'. La virgule sert à concaténer les chaines BufferSize: equ $-Buffer ; Taille de la chaine section .text ; Le code source est écrit dans cette section global _start ; Définition de l'entrée du programme _start: ; Entrée du programme mov eax, 4 ; Appel de sys_write mov ebx, 1 ; Sortie standard STDOUT mov ecx, Buffer ; Chaine à afficher mov edx, BufferSize ; Taille de la chaine int 80h ; Interruption du kernel mov eax, 1 ; Appel de sys_exit mov ebx, 0 ; Code de retour int 80h ; Interruption du kernelExistem debates sobre a utilidade da linguagem assembly. Em muitos casos, compiladores - otimizadores podem transformar a linguagem de alto nível em código que é executado de forma tão eficiente quanto o código assembly escrito à mão por um bom programador, embora seja muito mais fácil, rápido (e, portanto, menos eficiente). Caro) de escrever, ler e manter.
Eficiência já era uma preocupação na década de 1950, encontramos um traço dela no manual da linguagem Fortran (lançado em 1956) para o computador IBM 704 : Programas de objetos produzidos por Fortran serão quase tão eficientes quanto aqueles escritos por bons programadores .
Tendo os compiladores entretanto feito um enorme progresso, é óbvio que a grande maioria dos programas agora são escritos em linguagens de alto nível por razões econômicas, o custo adicional de programação superando o ganho resultante da melhoria esperada no desempenho.
No entanto, ainda existem alguns casos muito específicos em que o uso de assembler ainda se justifica:
Alguns compiladores transformam, quando sua opção de otimização mais alta não está habilitada , programas escritos em linguagem de alto nível em código de montagem, cada instrução de alto nível resultando em uma série de instruções de montagem rigorosamente equivalentes e usando os mesmos símbolos; isso permite que você veja o código para fins de depuração e criação de perfil , o que às vezes pode economizar muito mais tempo ao revisar um algoritmo . Sob nenhuma circunstância essas técnicas podem ser mantidas para a otimização final.
A programação de sistemas embarcados , muitas vezes baseados em microcontroladores , é um “nicho” tradicional para programação de montagem. Na verdade, esses sistemas são frequentemente muito limitados em recursos (por exemplo, um microcontrolador PIC 16F84 é limitado a 1.024 instruções de 14 bits e sua RAM contém 136 bytes) e, portanto, requerem uma programação de baixo nível muito otimizada para explorar suas possibilidades. Porém, a evolução do hardware faz com que os componentes destes sistemas se tornem cada vez mais potentes a um custo constante e com um consumo de energia constante, o investimento em uma programação "qualquer montador" muito mais caro em horas de trabalho então se torna um problema absurdo em termos de esforço. Normalmente, a programação em assembly é muito mais longa, mais delicada (porque o programador deve levar em consideração todos os micro-detalhes de desenvolvimento dos quais ele se abstém em linguagem de alto nível) e, portanto, consideravelmente mais cara do que a programação em linguagem de alto nível. Portanto, deve ser reservado apenas para situações para as quais não podemos fazer de outra forma.
Muitos montadores oferecem suporte a uma linguagem de macros . É uma questão de agrupar várias instruções para ter uma sequência mais lógica e menos tediosa.
Por exemplo (no Microsoft MASM assembler ):
é uma macro que exibe um caractere no MS-DOS . Será usado, por exemplo, da seguinte forma:
E vai gerar:
mov dl,"X" mov ah,2 int 21hUma pseudo-instrução é um tipo especial de instrução macro. É predefinido pelo editor do software de montagem e sua função é emular uma instrução do processador ausente ou facilitar o uso de uma instrução existente. Como a pseudo-instrução tem um nome muito semelhante ao de uma instrução real do processador, é possível, à primeira vista, confundi-la com uma das últimas. Por exemplo, um processador RISC pode não ter uma instrução JMP, o que permite pular para um ponto específico no programa e continuar a executá-lo em sequência. Neste caso, o editor de software terá criado para o programador uma pseudo-instrução "JMP <parameter>", que será substituída durante a montagem por uma instrução "mov pc , <parameter>", sendo pc o ponteiro. Instrução para ser executado. Outro exemplo, uma pseudo-instrução “PUSH <parameter>” será substituída por um armazenamento de <parameter> no endereço apontado por sp com pré-decremento deste último, sendo sp o ponteiro da pilha do processador.
Em microprocessadores RISC ou microcontroladores, como os da família ARM , não há nenhuma instrução de montagem permitindo que qualquer constante imediata seja carregada em um registrador, independentemente de seu valor. A maioria dos montadores possui uma pseudo-instrução que permite tal carregamento da forma mais eficiente possível em termos de tempo de execução, poupando essa tarefa para o programador.
Suporte para programação estruturada : alguns elementos da programação estruturada foram integrados para codificar o fluxo de execução pelo Dr. HD Mills (Março de 1970), e implementado por Marvin Kessler, que estendeu o montador de macro S / 360 com blocos de controle if / else / endif e até mesmo de fluxo. Essa era uma forma de reduzir ou eliminar o uso de operações de salto no código assembly.