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

Propaganda
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
assembly se representam números nos diferentes
A transformação de números entre sistemas de
introdutória a este manual.
Vamos então ilustrar a representação de 100 em
numeração. Note-se a presença ou ausência de um
já, a forma como em
sistemas de numeração.
numeração é do âmbito
diferentes sistemas de
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
introduzido o valor ASCII, exemplo:
entre
plicas,
aspas
ou
é
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
Directivas DD, DQ e DT que abordaremos no capítulo 7.
através
de
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
Int 21h
END inicio
do código
; Terminar programa
; Interrupção do DOS
; Fim e indicação do inicio da execução
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:
val1
msg
max
decimal
.DATA
dw
?
; Espaço para dois bytes (1 word)
db ‘Olá, Bom dia’ ; Cada carácter ocupa 1 byte
equ
100
; Definição de constante max = 100
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.
AX  AH + AL
Acumulador:
AX
AH
AL
16 bits
8 bits (High byte)
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.
especializados a guardar endereços:
Base Pointer:
Stack Pointer
(Topo):
Source Index:
Destination Index:
Estes
registos
BP
SP
Registos de gestão da pilha
SI
DI
Registos de índice (acesso a
vectores)
são
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:
Data Segment:
Stack Segment:
Extra Segment:
CS
DS
SS
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
O
Z
S
P
D
I
C
A
T
Descrição
Overflow  O bit “O” é ‘1’ quando a operação anteriormente
executada resultou em overflow. É ‘0’ se não existiu overflow;
Zero  Z é ‘1’ quando a operação anterior resultou em 0;
Sign  S é ‘1’ quando a operação anterior resultou num resultado
negativo (MSB=1);
Parity  P é ‘1’ quando o resultado de uma operação contém um
número para de bits igual a ‘1’;
Direction  Direcção do movimento no acesso a strings. D é ‘0’ se
os offsets SI e DI são incrementados. Se D é ‘1’ se são
decrementados;
Interrupção
Carry  Transporte final numa operação;
Auxiliary carry  Operações entre bits;
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
AH
DH
CH
BH
0
AL
DL
CL
BL
Stack Base
Pointer
Source Index
Destination Index
Stack Pointer
16
bits
AX
DX
CX
BX
32 bits
EAX
EDX
ECX
EBX
BP
EBP
SI
DI
SP
ESI
EDI
ESP
CS Code Segment
SS Stack Segment
DS Data Segment
7
31
23
15
7
0
16
bits
32 bits
ES Extra Segment
FS Extra Segment
GS Extra Segment
EFLAGS
EIP Extended Instruction Pointer
Flags
AF – Auxiliary
Carry
OF – Overflow
SF – Sign
CF – Carry
PF – Parity
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
MOV
Descrição
Movimento. Usada na
transferência de informação
(Move byte or Word)
Exemplo
mov ax, 5h (ax é carregado
com o valor de 5
hexadecimal)
mov bx, ax (bx é carregado
com o conteúdo de ax)
b) Aritméticas
Mnemónica
Descrição
ADD
Adição (Arithmetic
addition)
ADC
Adição com carry
SUB
Subtracção (Subtract)
SBB
Subtracção com borrow
Multiplicação (AX *
Reg)
Se 32 bits usa o DX
para auxiliar.
Divisão
Se 32 bits
axquociente
Dx  resto
MUL
DIV
Exemplo
mov ax, 5H (Ao conteúdo de ax é
adicionado com o valor de 5
hexadecimal)
mov ax, cx (ax é carregado com a soma
de ax com cx)
Adiciona o carry da operação anterior
mov bx, 5H (Ao conteúdo de bx é
subtraido o valor de 5 hexadecimal)
mov ax, cx (ax é carregado com a
subtracção de ax com cx)
Usa o borrow da operação anterior
mov al, 2
mov bx, 3
mul bx ;ax fica com 6
mov ax, 30
mov bl, 10
div bx ;AHquociente, ALresto
9
c) INC
Mnemónica
INC
Descrição
Incremento de 1
(Increment)
DEC
Decremento (Decrement)
NEG
Troca de sinal
LOOP
Decrementa CX e repete o
ciclo até CX = 0
LOOPZ
Ciclo que também teste a
ZF = 1
Exemplo
inc dx (Ao conteúdo de dx é
incrementado o valor de 1)
dec dx (Ao conteúdo de dx é
decrementado o valor de 1)
mov bx, 2h
neg bx
Loop
Mov cx, 30h
L1:
Loop L1
d) Salto
Mnemónica
Jmp
Descrição
Salto incondicional
(Unconditional Jump)
Salto condicional; É uma
instrução que analisa a flag
Z (Jump not zero)
Jnz
JA
JAE
JB
JBE
JC
JCXZ
JE
JG
JGE
JL
JLE
JMP
JNA
JNAE
JNB
JNBE
JNC
JNE
JNG
JNGE
JNL
JNLE
JNO
JNP
JNS
JNZ
JO
JP
JPE
JPO
JS
JZ
Exemplo
Jmp l1 (Salto para a linha de
código contendo a label l1)
sub cx,1; Qd cx=0  ZF = 1
jnz l2 (Salto para a label l2
se o resultado da operação
anterior foi diferente de
zero)
Jump if Above
Jump if Above or Equal
Jump if Below
Jump if Below or Equal
Jump if Carry
Jump if CX Zero
Jump if Equal
Jump if Greater(signed)
Jump if Greater or Equal(signed)
Jump if Less(signed)
Jump if Less or Equal(signed)
Unconditional Jump
Jump if Not Above
Jump if Not Above or Equal
Jump if Not Below
Jump if Not Below or Equal
Jump if Not Carry
Jump if Not Equal
Jump if Not Greater(signed)
Jump if Not Greater or Equal(signed)
Jump if Not Less(signed)
Jump if Not Less or Equal(signed)
Jump if Not Overflow(signed)
Jump if No Parity
Jump if Not Signed(signed)
Jump if Not Zero
Jump if Overflow(signed)
Jump if Parity
Jump if Parity Even
Jump if Parity Odd
Jump if Signed(signed)
Jump if Zero
CF=0 and ZF=0
CF=0
CF=1
CF=1 or ZF=1
CF=1
CX=0
ZF=1
ZF=0 and SF=OF
SF=OF
SF!= OF
ZF=1 or SF!= OF
unconditional
CF=1 or ZF=1
CF=1
CF=0
CF=0 and ZF=0
CF=0
ZF=0
ZF=1 or SF!= OF
SF!= OF
SF=OF
ZF=0 and SF=OF
OF=0
PF=0
SF=0
ZF=0
OF=1
PF=1
PF=1
PF=0
SF=1
ZF=1
10
e) Deslocação e rotação
Mnemónica
Descrição
Exemplo
shl al,1 ; o bit à direita
recebe um zero
mov cl, 4
shl al, cl ; 4 deslocações
SHL/SAL
Shift left (o bit mais à
esquerda passa para a CF)
SHR/SAR
Shift rigth (o bit da direita
vai para o carry)
ROR
Rotate right (Sem carry)
ROL
Rotate left (Sem carry)
RCR
RCL
Rotate right (Com carry)
Rotate left (Com carry)
Mnemónica
Descrição
Cbw
Converte byte numa word
Cwd
Converte Word numa
doubleword.
ror dx, 1; o LSB vai para
MSB
rol dx,1 ;o MSB vai para
LSB
rcr al, 1
rcl dx, 1
Exemplo
mov al, -1 ;positivo ou negativo
cbw
mov axl, 600H ;usa registo dx
auxiliar
cbw
f) Lógicas
Mnemónica
AND
OR
Descrição
Exemplo
and bx, cx
AND lógico bit a bit
and al, 2
Ou lógico bit a bit or cx, dx
XOR
Ou exclusivo
NOT
Complementa os bits
xor al, 11101001b
mov dl, 10000001b
NOT dl
g) XCHG
Mnemónica
Xchg
IN
OUT
Descrição
Troca de informação
entre registos
Leitura dos portos
Escrita nos portos
Exemplo
xchg
ax,cx
in al,
mov dx,
mov al,
porto
out dx,
4h ; leitura porto 41h
20h ; escrita do valor 5 no
5 ; porto 20h dx recebe o nº
al
h) Uso de subrotinas e pilha
Mnemónica
CALL
RET
PUSH
POP
Descrição
Chamada a uma subrotina
Retorno de um call
Guarda a informação de registos
na pilha
Devolve a informação da pilha
PROC
Inicia um bloco de código
ENDP
Termina um bloco de código
Exemplo
call Sub1 ; Faz push
automático
Sub1: …
ret ;Faz pop automático
push bx
pop bx
PROC NEAR;Pequenos retornos
PROC FAR;Grandes Retornos >
64 K
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
tam
DB ‘Olá, como estão?’, 13, 10
equ
($-str1)
A variável tam fica com o tamanho da string.
Mnemónica
Descrição
(Load
string/byte/Word)
Substitui:
…
LODS/LODSB/LODSW mov si, OFFSET
str1
mov al, [si]
inc si
...
CLD
Clear D Flag
STD
Set D Flag
STOS/STOSB/STOSW
MOVS/MOVSB/MOVSW
Move
String/byte/Word
SCAS/SCASB/SCASW
Scan
String/Byte/word
CMPS/CMPSW
Exemplo
Estas instruções usam o DI como
índice fonte do DS. Carrega em AL
o byte endereçado por DS:SI e
incrementa ou decrementa SI,
dependendo do estado da flag D. Se
D=0, SI é incrementado; Se D=1, SI
é decrementado.
cld
std
Oposto de LODS. Carrega string em
memória a partir do AC
Transferência directa de Memória
(DS) para Memória (ES), DS:SI
passa para ES:DI, SI e Di são
incrementados ou decrementados no
processo
Compara Al com o byte apontado por
ES:DI, actualizando as flags. DI é
incrementado ou decrementado
Compara
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
3
AL
????
Mov al,2 ;AL  2
AX
AH
3
AL
2
Mov CX,1 ; CX  3
Add ax,cx
; ax  ax + cx
20H
3H
23H
AX
CX
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
Mov
Out
al, 30h
dx, 200
dx, al
;
;
;
Vejamos agora as instruções de entrada:
Mov
In
dx,100
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
Mov
si, 30h
al, [si]
DS
…
4AH
…
SI
…
30h
…
Após esta instrução o acumulador fica como se mostra:
AH
?
AX
AL
4A H
g. Registo DI (Destination Index)
É um registo que pode ser usado tal como SI.
Mov
Mov
di, 30h
bl, [di]
DS
…
3BH
…
DI
…
30h
…
Após esta instrução o BX fica como se mostra:
BH
?
BX
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:
…
45
2B
1A
End. da Pilha
306
305
304
303
302
301
300
 SP
 BP
O seguinte código produz alterações na pilha:
Mov
Mov
Push
Add
Push
Pop
Pop
dx, 5 ;
cx, dx;
dx
;
;
cx, 1 ;
cx
;
;
cx
;
;
dx
;
;
dx  5
cx  5
stack dx
SP = 303
cx 6
stack dx
SP = 304
o valor de cx é
retirado da stack
o valor de dx é
retirado da stack
…
6
5
45
2B
1A
End. da Pilha
306
305
304
303
302
301
300
 SP
 BP
Destaque-se a sequência das instruções Push e Pop:
Push
Push
…
Pop
Pop
dx
cx
cx
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:
AX
BX
CX
…
A0
…
…
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
Mov
Mov
Val1;
ax, @data
ds, ax
; início da secção de código (CS)
;
;
;DS aponta, neste momento, para a variável
;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:
directo, indirecto, relativo e indexado.
imediato,
registo,
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
Add
Mov
Mov
al, 00
al,04
ax,0ffffh
ebx,0BCD1A123h
; al 00H
; al al + 4
; ax FFFFFH (16 bits)
;32 bits
5.2 Registo
Neste método existe a transferência
operandos estão contidos em registos:
Mov
Mov
Mov
bl, al
ds,cx
edx, ebx
de
dados
entre
registos.
Os
;
;
; 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
…
3BH
01
…
AX
Endereço
…
30h
31h
…
0
0000
1
0001
Low Byte
High byte
3
0011
B
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
Mov
bx, data1
ax, [bx]
; load effective address
; address data1
19
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
com o valor 01AB.
End
…
Mem
…
DS
0005
0006
AB
01
L Byte
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
exemplo:
…
data2
…
Lea
Mov
Mov
...
de endereçamento existe uma base relativa e um offset, por
db
‘BOA TARDE!’
bx, data2
al, [bx]+0
al, [bx]+7
; Carrega B
; Carrega D
A instrução mov al, [bx]+0 poderia ser substituída
por mov al, [bx].
São possíveis algumas variações à forma como
adicionar o endereço que se quer carregar, por
exemplo [bx] + 7 ou [bx + 7] ou 7 [bx].
offset
…
20
21
22
23
24
25
26
27
28
29
2A
Mem
…
B
O
A
data2
T
A
R
D
E
!
…
5.6 Indexado
Nesta forma
…
Data4
…
Mov
Mov
…
de endereçamento é permitida a utilização de um índice.
db
‘Boa tarde!’
si, 0
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
cada
small
;modelo para segmentos separados de 64K
.STACK
100h
;Tamanho da Pilha
.CODE
;Início do código (CS)
echoloop:
; Label (serve para indicar um ponto de
salto)
Mov
Int
Cmp
Jz
leitura
Mov
Mov
Int
Jmp
fim:
Mov
Int
END
ah,1
21h
al, 13
fim
dl, al
ah, 2
21h
echoloop
ah, 4ch
21h
; ler a tecla digitada
;Comparar se a tecla foi <ENTER>
;Sim foi <ENTER>, chegamos ao fim da
;A comparação é uma subtracção.
;Se o resultado é uma igualdade
; produz um zero daí a z flag =1
; visualizar outra vez o digitado
;repetir até que o <ENTER> seja lida
;fim do programa
;Executar a função 4CH
;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
Instruções.

segmento
de
código
(Code
Segment)
–
.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
i
v
…
600H
601H
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
constantes.
a
uma
variável.
Atribuição
de
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
exemplo:
caract
DB
10
pode ser substituído
caract
LABEL
DB
10
especificar o nome e o tipo de uma label,
DUP(0)
por:
BYTE
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
var1
data1
SEGMENT WORD ‘DATA’
DW 0
ENDS
data2
var2
data2
SEGMENT WORD ‘DATA’
DW 0
ENDS
codigo
SEGMENT WORD ‘CODE’
Assume
cs:codigo
Inicio:
codigo

Mov
Mov
ASSUME
Mov
Mov
ASSUME
…
ENDS
END
ax, data1
ds, ax
ds:data1
ax, data2
es, ax
ds:data2
; coloca Data1 em DS
; coloca Data2 em ES
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
Download