Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas


Linguagem assembly, Notas de estudo de Matemática

Linguagem assembly

Tipologia: Notas de estudo

Antes de 2010

Compartilhado em 11/08/2009

usuário desconhecido
usuário desconhecido 🇧🇷

4.6

(22)

148 documentos

1 / 52

Toggle sidebar

Esta página não é visível na pré-visualização

Não perca as partes importantes!

bg1
Linguagem Assembly Família Intel
última revisão Ago/2007
1
Linguagem ASSEMBLY da Família INTEL
1 Introdução
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/88
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
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a
pf2b
pf2c
pf2d
pf2e
pf2f
pf30
pf31
pf32
pf33
pf34

Pré-visualização parcial do texto

Baixe Linguagem assembly e outras Notas de estudo em PDF para Matemática, somente na Docsity!

Linguagem ASSEMBLY da Família INTEL

1 Introdução

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 ).

2 Arquitetura interna

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:

  • Quatro registradores gerais, de 16 bits, AX, BX, CX e DX, que podem ser subdivididos em (e referenciados separadamente como) registradores de 8 bits, AH, AL, BH, BL, CH, CL, DH e DL. Neste caso, X representa o registrador de 16 bits, enquanto H ("high") e L ("low") representam respectivamente seus 8 bits mais e menos significativos. Os registradores A têm a função de acumulador para algumas operações lógicas/aritméticas. Os registradores B são utilizados em algumas instruções como registradores de base. Há instruções que utilizam implicitamente os registradores C como contadores. Os registradores D não têm nenhuma função específica, além de funcionarem como registradores de rascunho.
  • Dois Registradores de Índice, de 16 bits, SI e DI.
  • Apontador de Pilha, de 16 bits, SP.
  • Um segundo Registrador de Base, de 16 bits, BP.
  • Contador de Programa, de 16 bits, IP.
  • Quatro Registradores de Segmento, de 16 bits, CS, DS, ES, SS. Estes registradores participam na formação do endereço físico que é gerado nos pinos de endereço do processador. Sua função será descrita, mais adiante.
  • Registrador de Estado, de 16 bits. Na verdade somente 9 destes 16 bits têm significado, conforme mostra a Figura 2. Cada sinalizador ("flag") tem o seguinte significado:

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.

3 Linguagem Assembly do 8086/

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.

3.1 Convenção para o armazenamento de variáveis.

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”.

3.2 Comandos

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(?)

; TABELA DD 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

Endereço

Efetivo

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

Endereço

Efetivo

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

Endereço

Efetivo

SI ou DI

Figura 8 : Ilustração do modo de endereçamento indexado com base.

3.4 Conjunto de Instruções do 8086/

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

Endereço

Efet-ivo

BX ou BP

SI ou DI

LAHF LAHF 4

(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

CMPS/CMPSB/CMPSW CMPSB^22

CMPSW

SCAS/SCASB/SCASW SCASB 15

SCASW

LODS/LODSB/LODSW LODSB 12

LODSW

STOS/STOSB/STOSW STOSB^11

STOSW

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)