Você está na página 1de 32

Arquitectura de Computadores – Curso Informática

Componente Linguagem Assembly

Guia Prático
Índice

1. Introdução .................................................. 3
1.1. Linguagem ................................................................................................................. 3
1.2 Representação de dados .................................................................................... 3
1.3 Estrutura de um programa ............................................................................... 4
2. Organização do CPU .......................................... 6
2.1. Registos ................................................................................................................... 6
 A) Registos de uso geral ............................................................................ 6
 B) Registos de endereço .............................................................................. 6
 C) Registos de Segmento .............................................................................. 6
 D) Registos de controlo e Flags ........................................................... 7
 E) Registos de 32 bits ................................................................................. 7
 F) Esquema dos registos ............................................................................... 7
3. Instruções e operações básicas com registos ................. 9
3.1 Operações básicas ................................................................................................ 9
3.2 Operações com registos .................................................................................. 13
a. Registo AX ....................................................................................................... 13
b. Registo BX ....................................................................................................... 13
c. Registo CX ....................................................................................................... 14
d. Registo DX ....................................................................................................... 14
e. Registo IP ....................................................................................................... 14
f. Registo SI (Source Index) ................................................................... 15
g. Registo DI (Destination Index) ....................................................... 15
h. Registos BP, SP e a Pilha (Stack) ................................................ 15
4. Segmentação e o Segmento DS ................................ 17
4.1 Segmentos ................................................................................................................. 17
4.2 CS (Code Segment) .............................................................................................. 18
4.3 ES (Extra Data Segment) ................................................................................ 18
4.4 SS (Stack Segment) ............................................................................................ 18
5. Modos de endereçamento ..................................... 19
5.1 Imediato .................................................................................................................... 19
5.2 Registo ...................................................................................................................... 19
5.3 Directo ...................................................................................................................... 19
5.4 Indirecto ................................................................................................................. 19
5.5 Relativo .................................................................................................................... 20
5.6 Indexado .................................................................................................................... 20
6. Chamadas ao sistema (System calls) ......................... 21
7. Directivas ................................................. 23
7.1 Directivas mais usadas .................................................................................. 23
7.2 Directivas de alocação .................................................................................. 24
7.3 Outras Directivas .............................................................................................. 25
7.4 Operandos ................................................................................................................. 26

2
1. Introdução

1.1. Linguagem

As razões que levam a usar a programação em assembly prendem-se por


permitir uma maior aproximação à máquina Os programas em assembly
ocupam menos espaço em memória (10 x menos), são mais rápidos (2 a 3 x
mais rápidos) e os programas em alto nível podem usar rotinas feitas
em assembly.
O esquema usado é apresentado na figura seguinte.

1.2 Representação de dados

Consideramos aconselhável introduzir, desde já, a forma como em


assembly se representam números nos diferentes sistemas de numeração.
A transformação de números entre sistemas de numeração é do âmbito
introdutória a este manual.
Vamos então ilustrar a representação de 100 em diferentes sistemas de
numeração. Note-se a presença ou ausência de um sufixo.

 Em decimal o número escreve-se sem qualquer alteração; exemplo:

Mov bx, 100

 Em binário acrescenta-se um b ao fim do número; exemplo:

Mov bx, 01100100b

 Em Octal acrescenta-se um º no fim do número; exemplo:

Mov bx, 144º

 Em hexadecimal acrescenta-se um h no fim do número. Se o número


começar por letra acrescenta-se um 0 no princípio para não confundir
com um label; exemplo:

Mov bx, 64h


Mov bx, 0E5Bah

 Os caracteres são carregados entre plicas, aspas ou é


introduzido o valor ASCII, exemplo:

Mov dl, 65; ASCII A

3
Mov dl, 41h
Mov dl, ‘A’
Mov dl, “A”

 Os números em vírgula flutuante são carregados através de


Directivas DD, DQ e DT que abordaremos no capítulo 7.

1.3 Estrutura de um programa

Um programa em Assembly comporta:


 Comentários
 Etiquetas (Labels)
 Directivas
 Operadores
 Conjunto de instruções
 Modos de endereçamento
 Chamadas ao sistema (System Calls)

Atendemos à estrutura básica de um programa

.MODEL small ; Modelo

.STACK 100h ; Tamanho da stack

.DATA ; Início secção de dados (DS)

.CODE ; Início código (CS)

inicio: ; Label

Mov ah, 4ch ; Terminar programa


Int 21h ; Interrupção do DOS
END inicio ; Fim e indicação do inicio da execução
do código

Este programa não faz nada de útil, regressando ao DOS. As linhas de


código, instruções ou comandos, têm o seguinte formato:

<label:> <instrução/Directiva> <operando, operando> <;comentário>

Por exemplo:

l1: Mov ax, cx ; axcx

Por serem muito simples iremos abordar os comentários e as etiquetas


nesta introdução. Os comentários servem para reflectir o que o
programador quer fazer com a instrução. Antes de cada bloco de código
deve ser explicada a sua função. Os comentários são colocados após o
sinal de ponto e vírgula (;).
As etiquetas ou labels, em inglês, são nomes simbólicos dados a
endereços, úteis, principalmente para referências de linhas de código,
bem como saltos. As variáveis ou constantes permitem ir buscar
instruções à memória.
Seguem-se alguns exemplos:

.DATA
val1 dw ? ; Espaço para dois bytes (1 word)
msg db ‘Olá, Bom dia’ ; Cada carácter ocupa 1 byte
max equ 100 ; Definição de constante max = 100
decimal

4
inicio:

jmp inicio ;Salta para inicio

Nestes dois extractos de código as palavras val1 e msg são variávies,


max é uma constante e inicio é uma etiqueta ou label.

5
2. Organização do CPU

2.1. Registos

Os registos são células de memória no interior do processador com um


acesso muito rápido. Os registos comuns da família de processadores
conhecida por iAPx86 (INTEL): 8086, 8088, 80186, 80286, 80386,80486...

Em comum: 16/8 bits

A) Registos de uso geral

Acumulador: registo “especial”, apesar de ser “general purpose”


principalmente destinado a operações aritméticas, lógicas e
deslocamento. É uma espécie de memória auxiliar muito útil durante o
processo de computação, de tecnologia avançada e extremamente rápida,
localizada dentro da CPU.

Acumulador: AX  AH + AL

AX 16 bits
AH 8 bits (High byte)
AL 8 bits (Low byte)

Tal como AX, existem outros registos de aplicação geral, mas incluindo
finalidades específicas:

Endereço Base: BX  BH + BL

Contadores: CX  CH + CL

Dados gerais e endereços de I/O: DX  DH + DL

B) Registos de endereço

Existem registos com funções específicas. Estes registos são


especializados a guardar endereços:

Base Pointer: BP Registos de gestão da pilha


Stack Pointer SP
(Topo):
Source Index: SI Registos de índice (acesso a
Destination Index: DI vectores)

C) Registos de Segmento

Temos registos de Segmento de memória. O 8086 pode endereçar até 1


Mbyte de memória. De uma só vez apenas pode endereçar 254 Kbytes em
blocos de 64 Kbytes (segmentos). Estes são, assim, áreas distintas de
um programa.

- Code Segment: CS
- Data Segment: DS
- Stack Segment: SS
- Extra Segment: ES

6
D) Registos de controlo e Flags

O ponteiro de instruções, Instruction Pointer (IP), é um registo que


aponta o endereço da próxima instrução a ser executada.

Todo o processador contém um registo especial chamado SR (Status


Register), constituído por bits indicadores de estados de operações,
popularmente conhecidos por Flags. (Operação anterior resultou em zero
ou carry? Há uma interrupção?), etc..
As flags principais, em qualquer processador são:

Flag Descrição
Overflow  O bit “O” é ‘1’ quando a operação anteriormente
O
executada resultou em overflow. É ‘0’ se não existiu overflow;
Z Zero  Z é ‘1’ quando a operação anterior resultou em 0;
Sign  S é ‘1’ quando a operação anterior resultou num resultado
S
negativo (MSB=1);
Parity  P é ‘1’ quando o resultado de uma operação contém um
P
número para de bits igual a ‘1’;
Direction  Direcção do movimento no acesso a strings. D é ‘0’ se
D os offsets SI e DI são incrementados. Se D é ‘1’ se são
decrementados;
I Interrupção
C Carry  Transporte final numa operação;
A Auxiliary carry  Operações entre bits;
T Trap Flag

E) Registos de 32 bits

A arquitectura x86 evoluiu, e há registos que não são comuns aos 80386
e 80486. São registos de 32 bits: eax, ebx, ecx, edx, ebp, esi, edi,
esp, eip, em que o ‘e’ significa “extended”.

F) Esquema dos registos

Organização dos registos da família de processadores Intel x86:

31 23 15 7 0 16 32 bits
bits
AH AL AX EAX
DH DL DX EDX
CH CL CX ECX
BH BL BX EBX

Stack Base BP EBP


Pointer
Source Index SI ESI
Destination Index DI EDI
Stack Pointer SP ESP

CS Code Segment
SS Stack Segment
DS Data Segment

7
31 23 15 7 0 16 32 bits
bits
ES Extra Segment
FS Extra Segment
GS Extra Segment

EFLAGS
EIP Extended Instruction Pointer

Flags
AF – Auxiliary CF – Carry
Carry
OF – Overflow PF – Parity
SF – Sign ZF – Zero

8
3. Instruções e operações básicas com registos

3.1 Operações básicas

Vamos abordar as instruções mais simples com registos já estudados. As


instruções podem ser agrupadas em 6 grandes conjuntos:

 Movimentação de dados;
 Aritméticas;
 Lógicas e de deslocamento;
 Controlo;
 Derivação;
 Manipulação de blocos e strings;

a) MOV

Mnemónica Descrição Exemplo


mov ax, 5h (ax é carregado
Movimento. Usada na com o valor de 5
MOV transferência de informação hexadecimal)
(Move byte or Word) mov bx, ax (bx é carregado
com o conteúdo de ax)

b) Aritméticas

Mnemónica Descrição Exemplo


mov ax, 5H (Ao conteúdo de ax é
adicionado com o valor de 5
Adição (Arithmetic
ADD hexadecimal)
addition)
mov ax, cx (ax é carregado com a soma
de ax com cx)
ADC Adição com carry Adiciona o carry da operação anterior
mov bx, 5H (Ao conteúdo de bx é
subtraido o valor de 5 hexadecimal)
SUB Subtracção (Subtract)
mov ax, cx (ax é carregado com a
subtracção de ax com cx)
SBB Subtracção com borrow Usa o borrow da operação anterior
Multiplicação (AX *
mov al, 2
Reg)
MUL mov bx, 3
Se 32 bits usa o DX
mul bx ;ax fica com 6
para auxiliar.
Divisão
mov ax, 30
Se 32 bits
DIV mov bl, 10
axquociente
div bx ;AHquociente, ALresto
Dx  resto

9
c) INC

Mnemónica Descrição Exemplo


Incremento de 1 inc dx (Ao conteúdo de dx é
INC
(Increment) incrementado o valor de 1)
dec dx (Ao conteúdo de dx é
DEC Decremento (Decrement)
decrementado o valor de 1)
mov bx, 2h
NEG Troca de sinal
neg bx
Loop
Decrementa CX e repete o Mov cx, 30h
LOOP
ciclo até CX = 0 L1:
Loop L1
Ciclo que também teste a
LOOPZ
ZF = 1

d) Salto

Mnemónica Descrição Exemplo


Salto incondicional Jmp l1 (Salto para a linha de
Jmp
(Unconditional Jump) código contendo a label l1)
sub cx,1; Qd cx=0  ZF = 1
Salto condicional; É uma jnz l2 (Salto para a label l2
Jnz instrução que analisa a flag se o resultado da operação
Z (Jump not zero) anterior foi diferente de
zero)

JA Jump if Above CF=0 and ZF=0


JAE Jump if Above or Equal CF=0
JB Jump if Below CF=1
JBE Jump if Below or Equal CF=1 or ZF=1
JC Jump if Carry CF=1
JCXZ Jump if CX Zero CX=0
JE Jump if Equal ZF=1
JG Jump if Greater(signed) ZF=0 and SF=OF
JGE Jump if Greater or Equal(signed) SF=OF
JL Jump if Less(signed) SF!= OF
JLE Jump if Less or Equal(signed) ZF=1 or SF!= OF
JMP Unconditional Jump unconditional
JNA Jump if Not Above CF=1 or ZF=1
JNAE Jump if Not Above or Equal CF=1
JNB Jump if Not Below CF=0
JNBE Jump if Not Below or Equal CF=0 and ZF=0
JNC Jump if Not Carry CF=0
JNE Jump if Not Equal ZF=0
JNG Jump if Not Greater(signed) ZF=1 or SF!= OF
JNGE Jump if Not Greater or Equal(signed) SF!= OF
JNL Jump if Not Less(signed) SF=OF
JNLE Jump if Not Less or Equal(signed) ZF=0 and SF=OF
JNO Jump if Not Overflow(signed) OF=0
JNP Jump if No Parity PF=0
JNS Jump if Not Signed(signed) SF=0
JNZ Jump if Not Zero ZF=0
JO Jump if Overflow(signed) OF=1
JP Jump if Parity PF=1
JPE Jump if Parity Even PF=1
JPO Jump if Parity Odd PF=0
JS Jump if Signed(signed) SF=1
JZ Jump if Zero ZF=1

10
e) Deslocação e rotação

Mnemónica Descrição Exemplo


shl al,1 ; o bit à direita
Shift left (o bit mais à recebe um zero
SHL/SAL
esquerda passa para a CF) mov cl, 4
shl al, cl ; 4 deslocações
Shift rigth (o bit da direita
SHR/SAR
vai para o carry)
ror dx, 1; o LSB vai para
ROR Rotate right (Sem carry)
MSB
rol dx,1 ;o MSB vai para
ROL Rotate left (Sem carry)
LSB
RCR Rotate right (Com carry) rcr al, 1
RCL Rotate left (Com carry) rcl dx, 1

Mnemónica Descrição Exemplo


mov al, -1 ;positivo ou negativo
Cbw Converte byte numa word
cbw
mov axl, 600H ;usa registo dx
Converte Word numa
Cwd auxiliar
doubleword.
cbw

f) Lógicas

Mnemónica Descrição Exemplo


and bx, cx
AND AND lógico bit a bit
and al, 2
OR Ou lógico bit a bit or cx, dx
XOR Ou exclusivo xor al, 11101001b
mov dl, 10000001b
NOT Complementa os bits
NOT dl

g) XCHG

Mnemónica Descrição Exemplo


Troca de informação
Xchg xchg ax,cx
entre registos
IN Leitura dos portos in al, 4h ; leitura porto 41h
mov dx, 20h ; escrita do valor 5 no
mov al, 5 ; porto 20h dx recebe o nº
OUT Escrita nos portos
porto
out dx, al

h) Uso de subrotinas e pilha

Mnemónica Descrição Exemplo


call Sub1 ; Faz push
CALL Chamada a uma subrotina automático
Sub1: …
RET Retorno de um call ret ;Faz pop automático
Guarda a informação de registos
PUSH push bx
na pilha
POP Devolve a informação da pilha pop bx
PROC NEAR;Pequenos retornos
PROC Inicia um bloco de código PROC FAR;Grandes Retornos >
64 K
ENDP Termina um bloco de código ENDP

11
i) Operações com strings

 Operador $

O símbolo $ é sempre igual ao OFFSET no segmento onde o programa está


a executar. Isto é útil para obter tamanhos de strings, exemplo:

str1 DB ‘Olá, como estão?’, 13, 10


tam equ ($-str1)

A variável tam fica com o tamanho da string.

Mnemónica Descrição Exemplo


(Load
string/byte/Word) Estas instruções usam o DI como
Substitui: índice fonte do DS. Carrega em AL
… o byte endereçado por DS:SI e
LODS/LODSB/LODSW mov si, OFFSET incrementa ou decrementa SI,
str1 dependendo do estado da flag D. Se
mov al, [si] D=0, SI é incrementado; Se D=1, SI
inc si é decrementado.
...
CLD Clear D Flag cld
STD Set D Flag std
Oposto de LODS. Carrega string em
STOS/STOSB/STOSW
memória a partir do AC
Transferência directa de Memória
(DS) para Memória (ES), DS:SI
Move
MOVS/MOVSB/MOVSW passa para ES:DI, SI e Di são
String/byte/Word
incrementados ou decrementados no
processo
Compara Al com o byte apontado por
Scan
SCAS/SCASB/SCASW ES:DI, actualizando as flags. DI é
String/Byte/word
incrementado ou decrementado
Compara
CMPS/CMPSW
string/Word

Vamos ver um exemplo de utilização de alguns comandos de strings.


Vamos procurar se a letra ‘t’ se encontra na string testestring.


.DATA
testestring DB ‘Texto de teste’,0
tamanho EQU ($-testestring)

.CODE ;Início do código (CS)

Mov ax,@data ; início segmento de dados
Mov es, ax
Mov di, OFFSET testestring ;ES:DI Apontar DI para a
string
Mov al, ‘t’ ;Carregar AL com ‘t’
Mov cx, tamanho ; comprimento da string a ser verificada
Cld ; verificação incrementando o DI
pesquisa:
Scasb ;faz ES:DI igual a Al?
Je encontrou_t ; Salta se encontrou um t
Loop pesquisa ; Salta enquanto cx não for zero
… ;Não encontrou nenhum t

12
encontrou_t:
Dec di ; Aponta para o offset de “t”

Iremos analisar algumas das instruções principais com maior detalhe.

3.2 Operações com registos

a. Registo AX

Vamos exemplificar com as instruções mov e add. Note que o ponto e


vírgula (;) é o sinal de comentário.

Mov ah,3 ; AH  3 ; O registo AH (o High-byte do acumulador) é


carregado com o valor 3

AX
AH AL
3 ????

Mov al,2 ;AL  2

AX
AH AL
3 2

Mov CX,1 ; CX  3

Add ax,cx ; ax  ax + cx

20H AX
3H CX
23H AX

Note-se que a notação ax  ax + cx no campo de comentário é simplista.


Tem como objectivo representar o seguinte (ax)  ((ax) + (cx)). Isto
significa que AX é carregado com o resultado da soma do valor anterior
de AX com o valor (conteúdo) de CX.

b. Registo BX

Este é um registo de aplicação geral usado com maior frequência para


apontar localizações de memória.
Mov bx,4 ; bx 4
Mov al,[bx] ; Ver esquema abaixo

O Registo bx é um offset em relação ao segmento de dados (DS). O


conteúdo (dados) apontado por bx é carregado em AL. Esta instrução tem
o nome de endereçamento indirecto (a ser analisada detalhadamente em
breve).
DS (Data Segment) contém endereços base, como apresentado no 20H 0
esquema. O Registo bx é aqui usado como um offset que tem os 30H 1
valores indicados à direita. Temos então que as instruções 23H 2
acima representadas resultam em carregar o registo AL com o 1AH 3
valor de 4BH. 4BH 4
AX … …
Mov al,[bx]
AH AL
? 4BH

13
c. Registo CX

O registo CX é usado principalmente como um contador. Vamos ver dois


exemplos:

i) Tendo o seguinte código:

Mov cx, 20H


repetir:

Sub cx, 1
Jnz repetir

A secção entre a Label repetir e a instrução de salto (jnz) é repetida


até que CX seja zero. Neste caso a flag Z toma o valor um devido ao
resultado de sub cx,1.

ii) Iremos agora ver o caso da instrução loop em conjunto com o


registo CX. A instrução loop executa um ciclo que decrementa
automaticamente CX e pára quando CX=0. Podemos então reescrever o
código acima de uma forma mais simples usando esta instrução:

Mov cx, 20H


repetir:

Loop repetir

A secção código compreendida entre a label repetir e a instrução loop


será repetida CX vezes.

d. Registo DX

Este registo tem como principal utilização o endereçamento de I/O. É o


único registo que pode ser usado para este efeito. Neste caso,
trabalha juntamente com AL e OUT em que no registo DX se armazena o
endereço, no AL os dados e OUT representa o porto de saída. Vejamos a
escrita de 30H no porto 200.

Mov al, 30h ;


Mov dx, 200 ;
Out dx, al ;

Vejamos agora as instruções de entrada:

Mov dx,100 ;
In al, dx ;

Carrega AL com a informação contida no Porto 100.

e. Registo IP

Este Registo não é acedido pelo utilizador. Aponta para a instrução


(código) seguinte a ser executada. Este endereço é um offset, ou seja
a base deste endereço é o code segment (CS).

14
f. Registo SI (Source Index)

É um registo que, tal como BX, aponta para posições de memória. Vamos
carregar AL com o conteúdo endereçado por SI.

Mov si, 30h


Mov al, [si]

DS SI
… …
4AH 30h
… …

Após esta instrução o acumulador fica como se mostra:

AX
AH AL
? 4A H

g. Registo DI (Destination Index)

É um registo que pode ser usado tal como SI.

Mov di, 30h


Mov bl, [di]
DS DI
… …
3BH 30h
… …

Após esta instrução o BX fica como se mostra:

BX
BH BL
? 3B H

Oportunamente veremos que os registos SI e DI têm aplicações


específicas na manipulação de strings. Aqui estes registos servem para
endereçar a fonte e o destino, respectivamente SI e DI.

h. Registos BP, SP e a Pilha (Stack)

Os registos BP e SP apontam para posições relativas da Pilha (stack).


O processador acede à Pilha por meio do registo SP. BP aponta para a
base da pilha e SP aponta para o topo da pilha. O registo BP, que
indexa o segmento da pilha, não tem qualquer função directa na
manipulação da pilha. Utiliza-se para aceder aos elementos da pilha
pela posição que nela ocupam. Não confundir estes dois registos com
BX, SI e DI. A memória apontada por estes três registos é em relação
ao DS (Data Segment), ou, no caso de DI, também ao ES.
A pilha (stack) armazena dados especiais, como por exemplo, cálculos
recursivos ou temporários, o endereçamento e retorno de uma subrotina,
etc.

…  SP

 BP

15
As instruções usadas para colocar e retirar dados da pilha são o push
e o pop. O push coloca um valor (dado) no topo da pilha. O pop retira
o valor da stack. Sempre que se efectua estas operações o SP é
actualizado automaticamente. Note-se que a pilha funciona como uma
LIFO (Last In, First out), ou seja o último valor a ser carregado é o
primeiro a sair. Vejamos um exemplo:

… End. da Pilha
306
305
304
303
45 302  SP
2B 301
1A 300  BP

O seguinte código produz alterações na pilha:

Mov dx, 5 ; dx  5
Mov cx, dx; cx  5 … End. da Pilha
Push dx ; stack dx 306
; SP = 303 305
Add cx, 1 ; cx 6 6 304  SP
Push cx ; stack dx 5 303
; SP = 304 45 302
Pop cx ; o valor de cx é 2B 301
; retirado da stack 1A 300  BP
Pop dx ; o valor de dx é
; retirado da stack

Destaque-se a sequência das instruções Push e Pop:

Push dx
Push cx

Pop cx
Pop dx

Assim é a única forma correcta de retirar os valores de CX e DX da


pilha. Isto deve-se à característica LIFO da pilha.
As instruções PUSHF e POPF são idênticas às PUSH e POP mas servem para
os registos FLAGS.

16
4. Segmentação e o Segmento DS

4.1 Segmentos

Segmentos são blocos de memória de 64 K (nos processadores mais


modernos 386/486/Pentium podem ir até 4 Gigabyte) onde residem,
separadamente, o código e os dados. O stack é também um segmento, mas
de tamanho menor (512 a 1024 bytes apenas).
Num programa os segmentos representam áreas distintas. A informação é
acedida à base de segmento : offset.
O registo de segmento é deslocado à esquerda de 4 vezes, ou seja, uma
multiplicação por 16 e adicionado o offset. Isto acontece porque os
registos são de 16 bits (8086 ao 80286) e as linhas de endereço serem
de 20 bits. Portanto há um conflito, pois 216 = 64 K (Registos) e 220
= 1 Megabyte (dos endereços). Esquematicamente:

A0
AX …
BX …
CX
… A19

Temos então 20linhas de endereço para registos de 16 bits. Notemos que


a partir do processador 80386 começaram a aparecer registos de 32
bits.
Vamos ver um exemplo para determinar um determinado endereço físico:

DS = 2000 H ; o endereço base do segmento de dados é 2000 H


SI = 300 H ; O SI é o offset, neste caso com o valor de 300 H
Temos então que
2000 H : 300 H (Ambos de 16 Bits)
deslocar 2000 H à esquerda de 4 bits (0010 0000 0000 0000 0000)
fica
20000H
donde o endereço efectivo colocado no address bus é de 20000H + 300
H
ou seja
20300 H
Normalmente não se carrega estes segmentos directamente com números
(endereços), mas sim através dos seus próprios nomes simbólicos. No
caso do turbo assembler: .DATA, .CODE, .STACK, etc. O processo de
compilação e linkagem encarrega-se de carregá-los com valores
específicos. No caso do sistema operativo DOS o nome do segmento de
dados é:
.DATA

Pelo que podemos acedê-lo através do comando @data e carregá-lo (o se


endereço base) no registo do segmento de dados (DS) com o auxílio de
um registo de aplicação geral; nunca directamente. Vamos exemplificar:

Mov ax, @data ;DS contém o endereço base da secção de dados


Mov ds,ax ;
Assim num programa há uma secção de dados chamada .DATA
.DATA ;início da área de dados (DS ou ES)
Val1 dw 5 ;
Val2 db 4 ;

17
.CODE ; início da secção de código (CS)
;
Mov ax, @data ;
Mov ds, ax ;DS aponta, neste momento, para a variável
Val1;
;Início do bloco de dados

4.2 CS (Code Segment)

O segmento de código é o registo que aponta para o endereço base do


Code Segment (CS), normalmente um bloco de 64 K.
Conforme analisado o registo IP contém o endereço da próxima instrução
a ser executada, pode ser um comando ou linha de código. Donde se pode
concluir que o CS está directamente relacionado com o registo IP.

4.3 ES (Extra Data Segment)

Na continuação da análise sobre segmentação, o registo ES (64 K) pode


servir de área adicional de armazenagem de dados. Esta área, quando
usada na maniplação de strings, serve de local de destino. ES : DI

4.4 SS (Stack Segment)

Já analisado.

18
5. Modos de endereçamento

Vamos considerar seis formas de endereçamento: imediato, registo,


directo, indirecto, relativo e indexado.

5.1 Imediato

A instrução contém o valor do operando. Não há o recurso a qualquer


posição de memória. Aqui os dados especificados como fazendo parte da
instrução. Alguns exemplos:

Mov al, 00 ; al 00H


Add al,04 ; al al + 4
Mov ax,0ffffh ; ax FFFFFH (16 bits)
Mov ebx,0BCD1A123h ;32 bits

5.2 Registo

Neste método existe a transferência de dados entre registos. Os


operandos estão contidos em registos:

Mov bl, al ;
Mov ds,cx ;
Mov edx, ebx ; Só para processadores 32 bits

5.3 Directo

A instrução contém o endereço de memória onde está armazenado o valor


que se pretende usar.

Mov ax, data1 ; ax é carregado com o conteúdo da localização


de memória apontado pelo endereço de memória associado à variável
data1

DS Endereço
… …
3BH 30h Low Byte
01 31h High byte
… …

0 1 3 B
AX
0000 0001 0011 1010

5.4 Indirecto

O endereçamento é efectuado através de um dos seguintes registos. SI,


DI, BX ou BP. Estes registos devem estar contidos entre parêntesis
rectos [ ], por exemplo, [bx]. É um modo de endereçamento muito eficaz
para aceder a tabelas.
Para serem usados estes registos necessitam de ser carregados, vejamos
dois exemplos:

a) Atente ao seguinte código:

Lea bx, data1 ; load effective address


Mov ax, [bx] ; address data1

19
End Mem DS
Temos que bx é carregado com o offset, ou endereço … …
de data1 no DS. Na instrução seguinte ax é carregado
com o valor apontado por bx. No caso ax é carregado 0005 AB L Byte
com o valor 01AB. 0006 01 H Byte

b) Atente ao seguinte código:

Mov bx, OFFSET data1

Carrega bx com o endereço offset de data1. Chama-se directiva a label


OFFSET.

5.5 Relativo

Neste modo de endereçamento existe uma base relativa e um offset, por


exemplo:

data2 db ‘BOA TARDE!’
offset Mem data2

… …
Lea bx, data2
Mov al, [bx]+0 ; Carrega B 20 B
Mov al, [bx]+7 ; Carrega D 21 O
... 22 A
23
A instrução mov al, [bx]+0 poderia ser substituída 24 T
por mov al, [bx]. 25 A
26 R
São possíveis algumas variações à forma como 27 D
adicionar o endereço que se quer carregar, por 28 E
exemplo [bx] + 7 ou [bx + 7] ou 7 [bx]. 29 !
2A …

5.6 Indexado

Nesta forma de endereçamento é permitida a utilização de um índice.



Data4 db ‘Boa tarde!’

Mov si, 0
Mov al, data4[si]

Desta forma podemos incrementar o índice SI de forma a aceder normalmente aos


elementos de um dado array.

20
6. Chamadas ao sistema (System calls)

O sistema
operativo (SO)
(MS-DOS) ocupa
parte da RAM tal
como os
segmentos. O SO
fornece um
conjunto de
funções,
devidamente
numeradas, as
quais podem ser
invocadas
directamente pelo
programa
assembly, o qual
deve carregar o
registo AH com o
número da função
e invocar o
interrupt 21 H
conforme
brevemente
ilustrado.
Destaque-se que o
objectivo desta
secção é
demonstrar como
aplicar estas
funções, através
de exemplos com
números de
funções possíveis
de serem
executadas no
laboratório.
Para se poder
fazer uma chamada
de uma função do
DOS carrega-se o
Registo AH com o
número dessa
função. Os outros
registos podem,
ou não, ser
usados pela
função.
Depois de se
carregar o
registo AH com o
número da função
chama-se o
interrupt 21h. Na tabela em Exemplo: Função 01H Read Keyboard and
Echo.
O carácter digitado é carregado no registo AL.

Mov ah, 1
Int 21h

21
Ler o carácter que está agora no AL (é necessário digitá-lo)
Exemplo: Função 02H Display Character.
Esta função mostra o caracter em DL.

Mov ah,2
Mov dl, ‘B’
Int 21h

Assim combinando estas duas funções podemos ler e visualizar, para
além do próprio eco, o carácter digitado do seguinte modo:

Mov ah, 1 ; leitura de carácter
Int 21h ; al  carácter
Mov ah,2 ;
Mov dl, al ; al fica à espera que se escreva no ecrã
Int 21h

Exemplo: Função 4CH Terminate a Process.


Esta função termina um processo em execução. Vejamos o exemplo
ilustrado. Aqui o programa mostra o carácter digitado duas vezes, uma
vez devido á digitação, outra devido à acção do eco. O programa
termina quando a tecla <ENTER> é pressionada.
Destaque-se ainda que este programa contém alguns princípios,
directivas, etc., a serem introduzidos mais à frente neste manual.
Queremos agora exemplificar o método de aplicação das funções.

.MODEL small ;modelo para segmentos separados de 64K


cada

.STACK 100h ;Tamanho da Pilha

.CODE ;Início do código (CS)

echoloop: ; Label (serve para indicar um ponto de


salto)
Mov ah,1 ; ler a tecla digitada
Int 21h
Cmp al, 13 ;Comparar se a tecla foi <ENTER>
Jz fim ;Sim foi <ENTER>, chegamos ao fim da
leitura
;A comparação é uma subtracção.
;Se o resultado é uma igualdade
; produz um zero daí a z flag =1
Mov dl, al ; visualizar outra vez o digitado
Mov ah, 2
Int 21h
Jmp echoloop ;repetir até que o <ENTER> seja lida
fim:
Mov ah, 4ch ;fim do programa
Int 21h ;Executar a função 4CH
END ;Directiva END

Exemplo:

Outra função importante é Display String.


A string deve terminar com o carácter ‘$’ e DX é o offset inicialmente
carregado com o primeiro elemento da string. Um programa sobre esta
função é introduzido mais tarde, já que precisamos de mais princípios
a serem abordados. No entanto para referência indicamos que em anexo
apresentamos exemplos de várias utilizações de funções do DOS

22
7. Directivas

Neste capítulo vamos abordar as directivas. Ao longo deste texto já


temos usado várias directivas e temos incluído um comentário
explicativo da sua função. Devemos começar por dizer que as directivas
não são instruções do processador. Antes são ordens para o assembler
“organizar” a memória e os programas em assembler.

7.1 Directivas mais usadas

 END
Indica o fim do código. Se escrevermos END xxx, este
operando representa uma label que indica onde o código deve
começar a ser executado.

 .STACK
Define o tamanho da pilha para programas que façam uso dela.
Define o Stack Segment (SS). A instrução .STACK 200h define
uma pilha com 512 bytes.

 .CODE
Define o início segmento de código (Code Segment) –
Instruções.

 .DATA
Define o início do segmento de dados ou do segmento extra de
dados. Para se aceder a posições de memória nestes segmentos
de dados deve-se carregar o registo DS com o símbolo @data
Mov ax, @data ;para o segmento de dados
Mov ds, ax
Mov dx, @data ;para o segmento extra de dados
Mov es, dx
Um dos métodos para se inicializar o offset de DS, para se
poder trabalhar conjuntamente com DS ou ES é o seguinte:
mov dx, OFFSET dados
Ou seja no contexto vamos apresentar um programa que mostra
no ecrã uma mensagem, utilizando a função do DOS #9 (Print
String)

.MODEL small
.STACK 200h
.DATA
dados DB ‘Viva as aulas de AC’
.CODE
inicioprograma:
Mov bx, @data ; bx é carregado com o início de DS
; não tem que ser sempre o ax
Mov ds, bx ; ds inicio do segmento de dados
Mov dx, OFFSET dados ; dx é carregado com o endereço da
; label dados (ex: offset 600H)
Mov ah, 9 ; função DOS
Int 21h ;invoca função do DOS de impressão
Mov ah, 4Ch ; função DOS de terminar o pgm
Int 21h
END inicioprograma

23
Este programa mostra no ecrã a mensagem “Viva as aulas de AC”

dados V 600H
i 601H
v 602H

 DOSSEG
Ordena os segmentos segundo uma ordem convencionada pela
Microsoft. Não é necessário invocá-la.

 MODEL
Modelo de memória utilizado. Modelos mais utilizados
Tiny – O código e os dados cabem num mesmo segmento de 64 K.
Small – O código e os dados cabem em segmentos separados de
64 K
Medium – Código pode exceder 64 K e dados cabem num segmento
de 64 K.
Compact – Código em 64 K e dados excede 64 K.
Large – Código e dados maiores que 64 K; Nenhum array excede
64K.
Huge – tudo pode exceder 64 K.

 CONST
Área de dados contendo as constantes.

 RADIX
Directiva que permite indicar opcionalmente o sistema de
numeração a seguir (valor por defeito; é pouco usada)

7.2 Directivas de alocação

Estas directivas servem para definir bytes, podendo-se assim carregar


valores:

DB (Define Byte - 1 byte)


DW (Define Word - 2 bytes)
DD (Define Double Word - 4 bytes)
DF, DP (6 bytes)
DQ (Define Quadword - 8 bytes)
DT (Define Ten Bytes)
EQU(Equate) - atribui um valor a uma variável. Atribuição de
constantes.

Alguns exemplos. Alocação de um carácter:



.DATA
letra1 DB ‘A’

Mov ah,2 ; Função Display
Mov dl, [letra1]
Int 21h

Alocação de tabelas (arrays), caso 1:



.DATA
array1 DB 20, 21, 22, 23, 24, 25
array2 DW 19, 11, 12, 13, 14, 15

24
Alocação de tabelas (arrays), caso 2:

.DATA
array3 DB 100h DUP (0)

Aqui mostra-se o exemplo de como reservar espaço para um determinado
array e inicializá-lo a zero. A tabela array3 tem 256 bytes, 100h,
totalmente inicializados a zero, DUP (0).

Alocação de tabelas (arrays), caso 3:



.DATA
array3 DB 50 DUP (‘A’)

Alocação de tabelas (arrays), caso 4:

.DATA
str1 DB ‘A’, ‘B’, ‘C’, ‘D’
str2 DB ‘ABCD’

Aqui mostra-se que ambos os métodos são equivalentes pois a directiva
DB guarda cada carácter num byte. Lembra-se que em strings deve-se
avançar o cursor para linha seguinte inserindo o CR(carriage return),
LF(Line Feed).
Alocação de tabelas (arrays), caso 5:

.DATA
val1 DW ((2000/2)+1)
val2 DW 10 DUP (0)
v DW val2

Note-se que v guarda o valor do endereço de val2 e não o valor
apontado pelo endereço.
Exemplo de um programa que lê do teclado e armazena os caracteres num
array:

.DATA
caract DB 10 DUP(0)

.CODE
Mov ax, @data
Mov ds, ax
Mov bx, OFFSET caract
Mov cx, 10
repete:
Mov ah, 1 ; DOS leitura de caracteres
Int 21h
Mov [bx], al ;Escrever no array o carácter
digitado
Inc bx
Loop repete

7.3 Outras Directivas

 LABEL
Esta directiva permite especificar o nome e o tipo de uma label,
exemplo:
caract DB 10 DUP(0)
pode ser substituído por:
caract LABEL BYTE
DB 10 DUP (0)

25
Os tipo de label podem ser: WORD (2 Bytes), DWORD (4 Bytes),
FWORD (6 Bytes), PWORD (8 Bytes), QWORD (10 Bytes).

 SEGMENT, ENDS e ASSUME


Até agora analisámos as directivas de segmento simplificadas.
Estas novas directivas, do tipo standard, são bastante úteis em
programas mais complexos, permitindo-nos nomear as suas partes
constituintes. Por exemplo, a secção de código seguinte começa
em código, e os blocos de dados são associados data1 a DS e
data2 a ES, através da directiva ASSUME:

data1 SEGMENT WORD ‘DATA’


var1 DW 0
data1 ENDS

data2 SEGMENT WORD ‘DATA’


var2 DW 0
data2 ENDS

codigo SEGMENT WORD ‘CODE’


Assume cs:codigo
Inicio:
Mov ax, data1
Mov ds, ax ; coloca Data1 em DS
ASSUME ds:data1
Mov ax, data2
Mov es, ax ; coloca Data2 em ES
ASSUME ds:data2

codigo ENDS
END Inicio

 PUBLIC, EXTERN e GLOBAL


Estas directivas são necessárias para declarações das
componentes globais, externas (programa chamante) e públicas
(programa chamado), pertencentes a programas contidos em
diferentes ficheiros.

7.4 Operandos

Como temos visto os operandos de uma operação podem ser registos, ax,
bx, al, entre outros, e constantes, 5, ‘A’. Vamos agora analisar os
casos em que os operandos podem ser expressões mais complexas.

.DATA
valor1 DB 0
valor2 DB 0
valor3 DB 0
.CODE
Mov ax, SEG valor1
Mov ds, ax
Mov bx, OFFSET valor2
Mov BYTE PTR [bx], 5H
Mov al, SIZE valor3

Vamos atender à instrução mov ax, SEG valor1. A instrução referida


carrega ax com o segmento de dados onde está valor1. Ou seja a
expressão SEG faz o mesmo que mov ax, @data.

26
Num segundo caso vamos ver a expressão mov bx, OFFSET valor2. Aqui o
registo bx é carregado com o valor do endereço da label (variável
valor2). Assim [bx] acede ao valor, conteúdo, apontado por bx.
A terceira expressão é mov BYTE PTR[bx], 5H. A expressão indica que é
do tipo byte e carrega o valor 5H (1 byte) na variável valor2. Vejamos
e exemplo de um programa que efectua a soma de duas palavras longas (4
bytes cada). O resultado é armazenado em soma (4 bytes).

.DATA
valor1 DD 100h
valor2 DD 150h
soma DD ?
.CODE
Mov ax, WORD PTR [valor1] ; ax  L-word de valor1
Mov dx, WORD PTR [valor1+2] ;dx H-word de valor 1
Add ax, WORD PTR [valor2] ;axL-word de valor2 +ax
Add dx, WORD PTR [valor2+2] ;dxH-word de valor2
+dx
Mov WORD PTR [soma], ax ; L-word de soma ax
Mov WORD PTR [soma+2], dx ; H-word de soma dx

A última expressão é mov al, SIZE valor3. Aqui SIZE indica o tamanho
da variável. Ou seja 2 é carregado em al pois é a definição de valor
2, dois bytes.

27
Anexo A – Exemplos de uso de funções do DOS

Exemplo da utilização da Função de mostrar uma string no ecrã.

Exemplo de utilização da função de obtenção da data (Get Date)

28
Exemplo da função de (Set date)

Exemplo de uma função de Get Time

29
Exemplo de uma função de Set Time

30
Exemplo de uma função de Open File

31
32

Você também pode gostar