i--------------©
¦ ASSEMBLY III ¦
È--------------¥
Comecemos a dar uma olhadela na arquitetura dos
microprocessadores da família INTEL 80x86... Vamos aos
registradores!
Entenda os registradores como se fossem variáveis que o
microprocessador disponibiliza ao sistema. TODOS os registradores
têm 16 bits de tamanho e aqui vai a descriçäo deles:
+------+
¦ AX ¦<--+
+------¦ ¦
¦ BX ¦<--¦
+------¦ +- Registradores de uso geral
¦ CX ¦<--¦
+------¦ ¦
¦ DX ¦<--+
+------+
+------+
¦ SI ¦<---- índice FONTE (Source Index)
+------¦
¦ DI ¦<---- índice DESTINO (Destination Index)
+------+
+------+
¦ SP ¦<---- Apontador de pilha (Stack Pointer)
+------¦
¦ BP ¦<---- Apontador de base (Base Pointer)
+------+
+------+
¦ CS ¦<---- Segmento de Cógido (Code Segment)
+------¦
¦ DS ¦<---- Segmento de Dados (Data Segment)
+------¦
¦ ES ¦<---- Segmento de dados Extra (Extra data Segment)
+------¦
¦ SS ¦<---- Segmento de Pilha (Stack Segment)
+------+
+------+
¦ IP ¦<---- Apontador de instruçäo (Instruction Pointer)
+------+
+------+
¦Flags ¦<---- Sinalizadores
+------+
Por enquanto vamos nos deter na descriçäo dos registradores uso
geral... Eles podem ser subdivididos em dois registradore de oito
bits cada:
AX (16 bits) BX (16 bits)
+-----------------+ +-----------------+
+-----------------+ +-----------------+
¦ AH ¦ AL ¦ ¦ BH ¦ BL ¦
+-----------------+ +-----------------+
15 8 7 0 15 8 7 0
CX (16 bits) DX (16 bits)
+-----------------+ +-----------------+
+-----------------+ +-----------------+
¦ CH ¦ CL ¦ ¦ DH ¦ DL ¦
+-----------------+ +-----------------+
15 8 7 0 15 8 7 0
AH é o byte mais significativo do registrador AX, enquanto que
AL é o menos significativo. Se alterarmos o conteúdo de AL,
estaremos alterando o byte menos significativo de AX ao mesmo
tempo... Näo existem registradores de oito bits em separado...
tudo é uma coisa só. Portanto, ao manipularmos AH, estaremos
manipulando AX ao mesmo tempo!
O nome de cada registrador tem o seu sentido de ser... "A" de
AX quer dizer que este registrador é um "acumulador" (usado por
default em algumas operaçöes matematicas!), por exemplo...
AX -> Acumulador
BX -> Base
CX -> Contador
DX -> Dados
O "X" de AX significa "eXtended". "H" de AH significa "High
byte".
Embora estes registradores possam ser usados sem restriçöes, é
interessante atribuir uma funçäo para cada um deles nos nossos
programas sempre que possível... Isto facilita a leitura do código
e nos educa a seguirmos uma linha de raciocínio mais concisa...
Mas, se for de sua preferência näo seguir qualquer padräo no uso
desses registradores, näo se preocupe... näo haverá qualquer
desvantagem nisso (Well... depende do código, as vezes somos
obrigados a usar determinado registrador!).
Alguns pontos importantes quanto a esses nomes seräo observados
no decorrer do curso... Por exemplo, certas instruçöes usam AX (ou
AL, ou AH) e somente ele, näo permitindo o uso de nenhum outro
registrador... Outras, usam CX para contar, etc... essas
instruçöes específicas seräo vistas em outra oportunidade.
Os registradores SI e DI säo usados como índices para tabelas.
Em particular, SI é usado para leitura de uma tabela e DI para
escrita (fonte e destino... lembra algum procedimento de cópia,
nao?). No entanto, esses registradores podem ser usados com outras
finalidades... Podemos incluí-los no grupo de "registradores de uso
geral", mas assim como alguns registradores de uso geral, eles têm
aplicaçäo exclusiva em algumas instruçöes, SI e DI säo usados
especificamente como índices em instruçöes que manipulam blocos
(também veremos isso mais tarde!).
Os registradores CS, DS, ES e SS armazenam os segmentos onde
estäo o código (programa sendo executado), os dados, os dados
extras, e a pilha, respectivamente. Lembre-se que a memória é
segmentada em blocos de 64kbytes (dê uma olhada na primeira mensagem
dessa série).
Quando nos referimos, através de alguma instruçäo, a um endereço
de memória, estaremos nos referindo ao OFFSET dentro de um segmento.
O registrador de segmento usado para localizar o dado no offset
especificado vai depender da própria instruçäo... Um exemplo em
assembly:
+----------------------------------------------------------------+
¦ MOV AL,[1D4Ah] ¦
+----------------------------------------------------------------+
O número hexadecimal entre os colchetes é a indicaçäo de um
offset em um segmento... Por default, a maioria das instruçöes usa
o segmento de dados (valor em DS). A instruçäo acima é equivalente
a:
+----------------------------------------------------------------+
¦ AL = DS:[1D4Ah] ¦
+----------------------------------------------------------------+
Isto é, em AL será colocado o byte que está armazenado no offset
1D4Ah do segmento de dados (valor em DS). Veremos mais sobre os
segmentos e as instruçöes mais tarde :)
Se quisessemos localizar o byte desejado em outro segmento (mas
no mesmo offset) devemos especificar o registrador de segmento na
instruçäo:
+----------------------------------------------------------------+
¦ MOV AL,ES:[1D4Ah] ¦
+----------------------------------------------------------------+
Aqui o valor de ES será usado.
O registrador IP (Instruction Pointer) é o offset do segmento de
código que contém a próxima instruçäo a ser execuatda. Este
registrador näo é acessível por qualquer instruçäo (pelo menos näo
pelas documentadas pela Intel)... é de uso interno do
microprocessador. No entanto existem alguns macetes para
conseguirmos obter o seu conteúdo (o que na maioria das aplicaçöes
näo é necessario... Para que conhecer o endereço da próxima
instruçäo se ela var ser executada de qualquer jeito?).
O registrador SP é o offset do segmento SS (segmento de pilha)
onde o próximo dado vai ser empilhado. A pilha serve para armazenar
dados que posteriormente podem ser recuperados sem que tenhamos que
usar um dos registradores para esse fim. Também é usada para
armazenar o endereço de retorno das sub-rotinas. A pilha "cresce"
de cima para baixo, isto é, SP é decrementado cada vez que um novo
dado é colocado na pilha. Note também que existe um registrador de
segmento exclusivo para a pilha... SP sempre está relacionado a esse
segmento (SS), como foi dito antes.
Para ilustrar o funcionamento da pilha, no gráfico abaixo
simularemos o empilhamento do conteúdo do registrador AX através da
instruçäo:
+-----------------------------------------------------------------+
¦ PUSH AX ¦
+-----------------------------------------------------------------+
+-----------------------------------------------------------------+
¦ AX = A527h (Valor em AX) ¦
¦ ¦
¦ +-------+ +-------+ ¦
¦ ¦ ????h ¦<----- SP = n ¦ A527h ¦ ¦
¦ +-------¦ +-------¦ ¦
¦ ¦ ¦ ¦ ¦<----- SP = n - 1 ¦
¦ +-------+ +-------+ ¦
¦ ¦
¦ (antes de PUSH AX) (depois de PUSH AX) ¦
+-----------------------------------------------------------------+
Observe que SP sempre aponta para um espaço vago na pilha.
Na realidade SP é decrementado de duas posiçöes ao invés de
apenas uma... mas, esse detalhe deixo para mais tarde.
O registrador BP pode ser usado como apontador para a base da
pilha (já que, por default, está relacionado a SS) ou como um
registrador de uso geral... depende do seu programa. Veremos isso
detalhadamente mais tarde.
Um dos registradores mais importantes de qualquer
microprocessador é o de "Flags". Eis uma descriçäo dos bits deste
registrador (a descriçäo abaixo aplica-se ao 8086. Normalmente näo
acessamos diretamente o registrador de flags - embora possamos
fazê-lo - por isso näo é conveniente assumirmos que os bits estäo
sempre no mesmo lugar para qualquer microprocessador da família
80x86!):
+----------------------------------------------------------------+
¦ +-------------------------------+ ¦
¦ ¦ ¦ ¦ ¦ ¦O¦D¦I¦T¦S¦Z¦ ¦A¦ ¦P¦ ¦C¦ ¦
¦ +-------------------------------+ ¦
¦ 15 0 ¦
¦ ¦
¦ C = Carry ¦
¦ P = Parity ¦
¦ A = Auxiliar Carry ¦
¦ Z = Zero ¦
¦ S = Signal ¦
¦ T = Trap ¦
¦ I = Interrupt Enable Flag ¦
¦ D = Direction ¦
¦ O = OverFlow ¦
+----------------------------------------------------------------+
¦ Carry:
Esse flag é setado sempre quando houver "vai um" depois de
uma adiçäo ou quando há BORROW depois de uma subtraçäo. Ou
quando, numa operaçäo de deslocamento de bits, o bit mais ao
extremo for deslocado para fora do dado (suponha um byte... se
todos os bits forem deslocados em uma posiçäo para a direita, o
que acontece com o bit 0?... Resposta: Vai para o carry!)
¦ Parity:
Depois de uma instruçäo aritimética ou lógica este bit
informa se o resultado tem um número par de "1"s ou näo.
¦ Auxiliar Carry:
Igual ao carry, mas indica o "vai um" no meio de um dado (no
caso de um byte, se houve "vai um" do bit 3 para o bit 4!).
¦ Zero:
Depois de uma operaçäo aritimética ou lógica, esse flag
indica se o resultado é zero ou näo.
¦ Signal:
Depois de uma instruçäo aritimética ou lógica, este flag é
uma cópia do bit de mais alta ordem do resultado, isto é, seu
sinal (dê uma olhada na "representaçäo de números negativos em
binário" no texto anterior!).
¦ Trap:
Quando setado (1) executa instruçöes passo-a-passo... Näo
nos interessa estudar esse bit por causa das diferenças de
implementaçäo deste flag em toda a família 80x86.
¦ Interrupt Enable Flag
Habilita/Desabilita o reconhecimento de interrupçöes
mascaráveis pela CPU. Sobre interrupçöes, veremos mais tarde!
¦ Direction:
Quando usamos instruçöes de manipulaçäo de blocos,
precisamos especificar a direçäo que usaremos (do inicio para o
fim ou do fim para o inicio).
Quando D=0 a direçäo é a do início para o fim... D=1, entäo
a direçäo é contrária!
¦ OverFlow:
Depois de uma instruçäo aritimética ou lógica, este bit
indica se houve mudança no bit mais significativo, ou seja, no
sinal. Por exemplo, se somarmos FFFFh + 0001h obteremos 00h. O
bit mais significativo variou de 1 para 0 (o counteúdo inicial
de um registrador era FFFFh e depois da soma foi para 0000h),
indicando que o resultado saiu da faixa (overflow) - ora, FFFFh
+ 0001h = 10000h, porém um registrador tem 16 bits de tamanho e
o resultado cabe em 17 bits. Neste exemplo, o bit de carry
também será setado pois houve "vai um" do bit 15 para o
inexistente bit 16, mas näo confunda o flag de overflow com o
carry!
Quando aos demais bits, näo se pode prever seus estados lógicos
(1 ou 0).
Na próxima mensagem começaremos a ver algumas instruçöes do
microprocessador 8086. Ainda näo escreveremos nenhum programa, a
intençäo é familiarizá-lo com a arquitetura do microprocessador
antes de começarmos a colocar a mäo na massa... tenha um pouco de
paciência! :)
Nenhum comentário:
Postar um comentário