












































Estude fácil! Tem muito documento disponível na Docsity
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Prepare-se para as provas
Estude fácil! Tem muito documento disponível na Docsity
Prepare-se para as provas com trabalhos de outros alunos como você, aqui na Docsity
Encontra documentos específicos para os exames da tua universidade
Prepare-se com as videoaulas e exercícios resolvidos criados a partir da grade da sua Universidade
Responda perguntas de provas passadas e avalie sua preparação.
Ganhe pontos para baixar
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Linguagem assembly
Tipologia: Notas de estudo
Compartilhado em 11/08/2009
4.6
(22)148 documentos
1 / 52
Esta página não é visível na pré-visualização
Não perca as partes importantes!













































Este texto apresenta uma descrição da linguagem de montagem do microprocessador 8086/88. Este processador se tornou um enorme sucesso comercial, não apenas mas sobretudo devido ao lançamento em 1981 do primeiro microcomputador pessoal (PC) da IBM, que se baseava no 8088.
Figura 1 : Diagrama de blocos da arquitetura interna de um processador 8086/
Com o sucesso dos PCs e interessada em preservar ao investimento em software dos seus usuários a Intel, fabricante do processador, preocupou-se em preservar a compatibilidade das novas gerações de processadores com a arquitetura básica do 8086/88. Como resultado, mesmo os atuais membros da família Pentium ainda executam código escrito para os fundadores desta dinastia de
processadores Intel. Levando ainda em conta a simplicidade da arquitetura do 8086/88 é didaticamente conveniente construir o estudo sobre linguagem de montagem a partir deste processador. Este texto apresenta inicialmente a arquitetura interna destes microprocessadores visível ao programador Assembly. Em seguida é apresentada a sua linguagem Assembly. O aluno que desejar uma documentação completa, incluindo as novas instruções da família Pentium e as instruções para dados em ponto flutuante, poderão fazer o download do Manual correspondente ( http://developer.intel.com/design/pentium4/manuals/245471.htm ).
A Figura 1 mostra a arquitetura interna dos microprocessadores 8086 e 8088. Há basicamente duas diferenças entre eles: a largura do barramento externo de dados (8 bits no 8088, e 16 bits no 8086), e o tamanho do bloco "fila de instruções" ( bytes no 8088 e 6 bytes no 8086). Os principais blocos são: a) ULA capaz de executar operações sobre 8 ou 16 bits. b) Banco de Registradores , constituído de:
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Figura 2: Registrador de Estado do 8086/
somador (Σ), a fila de instruções, além dos quatro registradores de segmento já mencionados. A função destes elementos será discutida mais adiante.
Nas linhas que se seguem são apresentadas de modo resumido as principais características da linguagem Assembly do 8086/8088 (ASM86). Para ter uma descrição detalhada desta linguagem. O aluno deverá recorrer aos manuais e livros indicados.
Todos os sistemas reais são capazes de armazenar variáveis que ocupam mais do que um byte, em posições consecutivas da memória. Assim, se uma variável ocupa uma palavra de 16 bits, esta variável estará armazenada em dois endereços consecutivos. Há aqui duas convenções possíveis: a) armazenar o byte menos significativo no endereço A+1 e o mais significativo no endereço A, e b) armazenar o byte menos significativo no endereço A e o mais significativo no endereço A+1. A primeira convenção é chamada de “big endien” e é utilizada pelos processadores da Motorola, por exemplo. A segunda alternativa é chamada “little endien” e é utilizada por todos os processadores da linha Intel. A Figura 3 ilustra as duas convenções para armazenar o valor 3456H. Deve-se ainda acrescentar que nos processadores Intel o endereço de uma palavra de dois ou quatro bytes é o endereço do byte menos significativo. Em outras palavras, se uma variável tem comprimento igual a n bytes, e está armazenadas nos endereços A,..., A+n-1 , o endereço desta variável será A.
endereço conteúdo endereço conteúdo A A A+1 A+
“little endien” “big endien”
Figura 3 : Convenções “little endien” e “big endien”.
Existem dois tipos de comandos na linguagem Assembly-86 (ASM86): instruções e diretivas.
As instruções correspondem a códigos binários que são as instruções de máquina executadas pelo microprocessador. Enquanto as instruções assembler são simbólicas, as chamadas instruções de máquinas são binárias. A razão para usar instruções Assembly ao invés de instruções binárias é evidente. É muito mais fácil para o programador desenvolver de dar manutenção num programa escrito na forma de símbolos que sugerem a função de cada instrução do que num programa constituído por uma cadeia de 0’s e 1’s. O papel do programa montador (Assembler) é traduzir as instruções Assemby para as instruções de máquina. Ao contrário do que ocorre com as instruções, o montador não gera para as diretivas nenhuma instrução de máquina. As diretivas são informações fornecidas pelo programador que auxiliam o montador no processo de montagem. As instruções podem ter até cinco campos:
((rótulo :) (prefixo) mnemônico (operando(s)) (;comentários))
onde os parênteses denotam que se trata de campos opcionais (os parênteses não são escritos pelo programador). O campo rótulo fornece um nome à posição de memória que contém a instrução, de tal maneira que se pode fazer referência a ela simbolicamente numa instrução de desvio (p. ex.: JMP) em algum outro ponto do programa. Um prefixo leva o montador a gerar um byte de prefixo que modifica de alguma forma a execução normal da instrução. O uso de tais prefixos será melhor esclarecido mais adiante neste texto. O mnemônico identifica o tipo de instrução (p. e. MOV para movimentação, ADD para adição, etc.) que deve ser gerada.. Uma instrução pode ter zero, um ou dois operandos separados por uma vírgula. Os comentários não afetam a execução de um programa, mas constituem meramente um recurso que facilita a compreensão da lógica implementada no programa. É muitíssimo útil durante o desenvolvimento ou posteriormente na manutenção do programa. Recomenda-se enfaticamente que o aluno utilize extensivamente comentários em seus programas. As diretivas podem ter até quatro campos:
(nome) mnemônico (operando(s)) (;comentários)
Algumas diretivas exigem um nome, enquanto outras proíbem um nome. O montador reconhece a diretiva a partir do mnemônico escrito no segundo campo.Todos os eventuais operandos são escritos em seguida.
3.2.1 Algumas Diretivas
A relação de diretivas apresentada nesta seção é apenas adequada aos objetivos deste curso sem ser completa. Outras diretivas serão apresentadas nas
Os operandos destas diretivas indicam ao montador quantas unidades de armazenamento alocar - respectivamente 1, 2 e 4 bytes - e qual o valor inicial, se houver. Os exemplos abaixo esclarecem como utilizar estas diretivas:
ALFA DB? ; não inicializada
BETA DW? ; não inicializada
GAMA DD? ; não inicializada
UPSILON DW 5 ; constante 05H
IOTA DB ‘HELLO’ ; contém 48 45 4C 4C 4F H
MU DD 100 DUP 0 ; aloca e inicializa 100 bytes com 0 (zero)
Para cada variável num programa ASM86, o montador registra a informação do tipo, ou seja, do número de bytes alocados a ela. Quando uma variável é referenciada no programa, o montador utiliza esta informação para determinar a forma da instrução de máquina que deve ser gerada. Se o uso da variável conflita com o seu atributo, o montador gera uma mensagem de erro. Há casos em que o programador deve indicar explicitamente ao montador qual é o tipo do operando. Por exemplo, a instrução:
MOV [BX], escreve o valor 5 na posição de memória, cujo endereço está definido pelo conteúdo do registrador BX. Esta instrução não identifica o tipo da variável, se é um byte, uma palavra ou uma palavra dupla. Note, que dependendo do tipo da variável, a execução desta instrução envolverá a modificação de 1, 2 ou 4 bytes da memória. A informação do tipo de variável pode ser fornecido através das diretivas: byte ptr, word ptr, dword ptr , como nos exemplos a seguir
MOV word ptr [BX],5 ; indica que é palavra
SUB byte ptr [BX][SI],1 ; indica que é byte
ANA BETA,32H ; implícito que é palavra
CMP byte ptr ALFA[SI], 10 ; indica que é byte (redundante)
DEC byte ptr GAMA ; indica que é byte apesar da definição
A primeira e segunda linhas do exemplo esclarecem que o primeiro operando da instrução é um byte. Na terceira linha não é necessário utilizar estas diretivas, pois o montador assume o tipo indicado quando da definição da variável, neste caso, uma palavra (vide exemplo anterior). Na quarta linha o uso da diretiva é redundante e, portanto desnecessário, por que a variável já havia sido definida (vide
exemplo anterior), como byte. A última linha tem um aspecto interessante. Embora a variável GAMA tenha sido definida como palavra dupla, a instrução decrementa apenas o byte apontado pelo endereço GAMA, sem alterar os demais 3 bytes da palavra dupla. A diretiva TYPE identifica a unidade de alocação de memória (1 = byte; 2 = palavra, 4 = palavra dupla). A linguagem provê duas diretivas: LENGHT e SIZE , que podem ser escrito nas instruções com informações de atributo. LENGHT faz o montador retornar com o número de unidades de armazenamento (bytes, palavras ou palavras duplas) ocupadas por um vetor. SIZE leva o montador a retornar o número de bytes ocupados pela variável ou vetor. Estas diretivas permitem que se escrevam seqüências de instruções que não precisam ser mudadas (somente montadas novamente), se os atributos das variáveis mudarem, por exemplo, um vetor de bytes muda para um vetor de palavras. O exemplo a seguir ilustra uma aplicação típica destas diretivas.
; soma do conteúdo de uma tabela em AX
; observe que a mesma instrução funciona para
; TABELA DB 50 DUP(?)
SUB AX,AX ; zera contador
MOV CX, LENGHT TABELA ; número de iterações
MOV SI, SIZE TABELA ; aponta p/ o fim do vetor
SOMA_OUTRO:
SUB SI, TYPE TABELA ; pega elemento anterior
ADD AX, TABELA [SI] ; soma um elemento
; AX contém a soma
Existe também a diretiva OFFSET. Basta por enquanto considerar que esta diretiva retorna o próprio endereço da variável referenciada no programa logo em seguida a esta diretiva. Do mesmo modo, algumas outras diretivas relacionadas com o mecanismo de segmentação do processador, não serão apresentadas aqui. Embora todo programa
3.3.2 Imediato
O operando está contido na própria instrução. Este operando pode ter 8 ou 16 bits. Exemplos:
SUB CL, ADD DX,MENOS_ Note nos exemplos que as instruções utilizam também o modo de endereçamento registrador. De um modo geral, uma mesma instrução pode usar modos de endereçamento diferentes para cada um dos seus operandos. No caso deste processador cada instrução pode ter no máximo dois operandos. Cada operando pode ser referenciado usando um modo de endereçamento distinto. Quando o operando está na memória, o processador calcula o endereço da posição correspondente das formas que serão explicitadas a seguir. Este endereço é chamado de endereço efetivo ( effective address - EA). Na realidade o endereço efetivo não é propriamente o endereço do operando, mas a distância entre o endereço da posição de memória e um certo endereço de referência chamado endereço de início de segmento. Por enquanto convém admitir que o endereço efetivo é o próprio endereço do operando. Maiores esclarecimentos serão dados em seções posteriores.^1
Figura 4: Ilustração do modo de endereçamento direto
Nos modos de endereçamento que serão apresentados a seguir, o endereço efetivo será dado pela soma de até três componentes: base (fornecida por um dos registradores de base - BX ou BP ), índice (fornecido pelo conteúdo de um dos registradores de índice - SI ou DI ) e um deslocamento (contido na própria instrução). O que caracteriza cada um dos modos de endereçamento a seguir é qual ou quais destes três componentes estarão presentes na soma.
(^1) Na realidade o endereço efetivo não é propriamente o endereço do operando, mas a distância
deste a um certo endereço de referência, chamado endereço de início de segmento.
opcode mod reg r/m desloc camento
3.3.3 Direto
Trata-se do modo de endereçamento de memória mais simples. Não envolve nenhum registrador. O endereço efetivo é tomado diretamente do deslocamento contido na própria instrução. Este modo de endereçamento é tipicamente utilizado para referenciar escalares. A Figura 4 ilustra o formato destas instruções. Alguns exemplos: MOV AX,[8000H] SUB CX,BETA DEC byte ptr GAMA
3.3.4 Registrador Indireto
O endereço do operando pode ser tirado de um dos registradores de base ( BX ou BP ) ou índice ( SI ou DI ), como mostra a Figura 5. Qual destes registradores é usado está definido num dos campos da instrução.
Figura 5 : Ilustração do modo de endereçamento registrador indireto.
Somente um registrador de base ou de índice pode estar presente neste modo de endereçamento. Os registradores de 8 bits, assim como AX, DX, CX, SP, além dos registradores de segmento (CS, DS, ES, SS) são proibidos aqui, a menos de raras exceções. Exemplos:
MOV AL,[BX] SUB [SI],DX Convém, contudo, notar que qualquer registrador de uso geral pode ser utilizado neste modo de endereçamento nas instruções do tipo JMP e CALL. Exemplos destes casos são:
JMP [AX] CALL [DX]
opcode mod reg r/m
BX ou BP ou SI ou DI
Figura 7 : Ilustração do modo de endereçamento Indexado.
Abaixo são dados alguns exemplos deste modo de endereçamento. MOV AL,[SI+0B000H] SUB CL,MU[SI] ADD word ptr [DI][1000H], 43H
3.3.7 Indexado com Base
O modo de endereçamento indexado com base gera o endereço efetivo somando o conteúdo de um registrador de base (BP ou BX), o conteúdo de um registrador de índice (SI ou DI) e um deslocamento, como mostra a figura 8. É importante salientar aqui que neste modo de endereçamento está presente um registrador de base e um registrador de índice. Qualquer outra combinação de registradores é inválida. Este modo é freqüentemente utilizado para referenciar vetores localizados na pilha, como será discutido adiante. Novamente neste caso o campo mod_reg_r/m da instrução define quais os registradores participam do cálculo do endereço efetivo. Abaixo são dados alguns exemplos deste modo de endereçamento. MOV AL,[BX+SI+ 5H] ADD [BP][DI][1000H], AX
opcode mod reg r/m desloc camento
SI ou DI
Figura 8 : Ilustração do modo de endereçamento indexado com base.
A apresentação que se segue não contém todos os detalhes de cada instrução. Ela se propõe a ser um esquema a ser seguido em aula e ao mesmo tempo um resumo do assunto. É importante ter em mente que todas estas instruções estão presentes no conjunto de instruções dos demais processadores da família 80X86, de tal sorte que o conhecimento aqui adquirido pode ser utilizado na programação de sistemas mais modernos.
3.4.1 Convenções
Na apresentação a seguir adota-se a seguinte convenção: d - uma quantidade de 8 ou 16 bits. d8 - uma quantidade de 8 bits. d16 - uma quantidade de 16 bits. r, r 1 , r 2 - um registrador de 8 ou 16 bits de uso geral. r8 - um registrador de 8 bits. r16 - um registrador de 16 bits. ( ) - o conteúdo de um registrador, ou posição de memória, dependendo do que estiver entre os parênteses. m - endereço de um byte ou uma palavra na memória
opcode mod reg r/m desloc camento
BX ou BP
SI ou DI
(AH7,6,4,2,0)← (SF,ZF,AF,PF,CF)
SAHF SAHF 4
(SF,ZF,AF,PF,CF) ←(AH7,6,4,2,0)
3.4.3 Instruções de Manipulação de Cadeias de Caracteres (string)
Cada uma das instruções deste grupo tem três formatos diferentes. Para o primeiro formato (terminado com um "S"), o montador entende que o string é de bytes ou de palavras. O segundo (terminado com um "SB") e terceiro (terminado com um "SW") indicam explicitamente que se trata respectivamente de um string de bytes e palavras.
MOVS/MOVSB/MOVSW MOVSB 18
MOVSW
REP REP MOVSB 9+17*rep
REP REP LODSW 9+13*rep
REP REP STOSW 9+10*rep
REPZ/REPE REPZ CMPS 9+22*rep
REPNZ/REPNE REPNZ SCAS 9+15*rep
Nas cinco últimas linhas da tabela contém prefixos usados para repetir a
execução da instrução de manipulação de string escrita em seguida pelo número de vezes especificado em CX. Diante das instruções MOVS/MOVSB/MOVSW, LODS/LODSB/LODSW e STOS/STOSB/STOSW, pode-se usar o prefixo REP, que decrementa o registrador CX , sem afetar os flags, e repete a instrução de string,
enquanto CX ≠ 0. Diante das instruções CMPS e SCAS, pode-se usar os prefixos REPZ(ou REPE) ou REPNZ(ou REPNE). REPZ decrementa CX , sem afetar os flags,
e repete a instrução de string, enquanto CX ≠ 0 e ZF = 1. O prefixo REPNZ decrementa CX , sem afetar os flags, e provoca a repetição da instrução de string,
enquanto CX ≠ 0 e ZF = 0.
3.4.4 Instruções de Manipulação de Endereços
LEA r 16 ,m 16 LEA BX,[BP][DI] 2+EA
(r 16 ) ← m 16
LDS r 16 ,m 32 LDS SI,DATA_SEG[DI] 16+EA
(r 16 ) ← (m 32 )
(DS) ← (m 32 )+
LES r 16 ,m 32 LES SI,DATA_SEG[DI] 16+EA
(r 16 ) ← (m 32 )
(ES) ← (m 32 )+
3.4.5 Instruções Aritméticas
3.4.5.1 Adição
ADD r 1 ,r 2 ADD^ AX,SI^3
ADD CL,DH
ADD r,m ADD DL,[300] 9+EA
ADD CX,[BX+1234H]
ADD m,r ADD byte ptr [300],DL 16+EA
ADD word ptr [SI+BX+2],AX
ADD r,d ADD AL,4 4
(r) ← (r) + d ADD^ AX,
ADD m,d ADD byte ptr [DI],54 17+EA
(m) ← (m) + d ADD^ word ptr [BX+4],4FFH
SBB r,m SBB BL,[456] 9+EA
SBB CX,word ptr [300H]
SBB m,r SBB byte ptr [300],DL 16+EA
(m) ←(m) - (r) - (CF) SBB^ word ptr [SI],BX
SBB r,d SBB CL,24 4
(r) ←(r) - d - (CF) SBB^ BX,
SBB m,d SBB byte ptr [DI],54 17+EA
(m) ← (m) - d - (CF) SBB^ word ptr [BX+4],4FFH
DEC r DEC AX 2
(r) ←(r) - 1 DEC^ Cl^3
DEC m DEC byte ptr [SI] 15+EA
DEC word ptr [BX+100H]
NEG r NEG BX 3
NEG AL
NEG m NEG^ byte ptr [BX+DI]^ 16+EA
(m) ←0 - (m) NEG^ MULTIPLICADOR
CMP r 1 ,r 2 CMP^ BX,CX^3
CMP AL.BL
CMP r,m CMP DH, byte ptr ALPHA 9+EA
(r) - (m) CMP CH,[SI+BX+10]
CMP m,r CMP^ [BP+2],SI^ 9+EA
(m) - (r) CMP [SI],AX
CMP r,d CMP BL,02H 4
(r) - d CMP DL,85H
CMP m,d CMP RADAR[DI],3420H 10+EA
(m) - d
3.4.5.3 Multiplicação
MUL r MUL BL 70-
MUL CX 118-
MUL m MUL byte ptr MES[SI] (76-83)+EA
(AX) ← (AL) * (m 8 ) MUL^ word ptr DIA[SI]^ (124-139)+EA
(DX:AX) ← (AX) * (m 16 ) MUL^ BAUD_RATE
(sem sinal)
IMUL r IMUL BL 80-
(AX) ← (AL) * (r 8 ) IMUL CX^ 128-
(DX:AX) ← (AX) * r 16 )
(com sinal)
IMUL m IMUL byte ptr MES[SI] (86-104)+EA
(AX) ← (AL) * (m 8 ) IMUL word ptr DIA[SI]^ (134-160)+EA
(DX:AX) ← (AX) * (m 16 )
(com sinal)
3.4.5.4 Divisão
DIV r 8 DIV^ CL^ 80-
DIV r 16 DIV^ DX^ 144-
(sem sinal)