ASM – Tutorial 2 – Adam Hyde

Tutorial de Assembler de Adam Hyde 1.0
PARTE 2

Traduzido por Renato Nunes Bastos

Versão   :  1.2
Data       :  17-02-1996 / online by Renato 01-11-1998
Contato  :  blackcat@vale.faroc.com.au
http://www.faroc.com.au/~blackcat
;Renato  :  Contato
http://www.geocities.com/SiliconValley/Park/3174 (meu site antigo, agora está fora do ar)
http://www.krull.com.br


Segmentos e Offsets | Uma Arquitetura Segmentada | A Pilha

 


Olá de novo, futuros proramadores de Assembler. Para aqueles que perderam a primeira parte, pegue-a agora na minha homepage.

De qualquer modo, no último número eu disse que estaria discutindo sobre hexadecimal, segmentos + offsets, mais algumas intruções e algumas procedures contendo assembler que você poderia realmente usar.

Então, lá vamos nós, com segmentos e offsets!


LIÇÃO 3 – Segmentos e Offsets

 

Antes de explorarmos o grande e mau mundo dos segmentos e offsets, há umas terminologias que você precisar  conhecer.

  • O BIT – a menor parte de dados que podemos usar. Um bit – um oitavo de um byte pode ser ou um 1 ou um 0.  Usando esses dois dígitos podemos fazer números em BINÁRIO ou BASE 2.

EX.:

0000 = 0    0100 = 4   1000 = 8    1100 = 12
0001 = 1     0101 = 5   1001 = 9     1101 = 13
0010 = 2     0110 = 6   1010 = 10   1110 = 14
0011 = 3     0111 = 7   1011 = 11     1111 = 15
10000 = 16 … Acho que você já sacou…

  • O NIBBLE, ou quatro bits. Um nibble pode ter um valor máximo de 1111 que é 15 em decimal. É aqui que o hexadecimal entra. Hex é baseado naqueles 16 números, (0-15), e quando escrevemos em hex, usamos os ‘dígitos’ abaixo:

0 1 2 3 4 5 6 7 8 9 A B C D E F

Hexadecimal é na verdade muito fácil de se usar, e, apenas como curiosidade, eu acho que os Babilônios – uma civilização antiga qualquer – usava um sistema de numeração em BASE 16. Tem algum historiador aí fora que queira confirmar isso?

IMPORTANTE >>> Um nibble pode aguentar um valor até Fh <<< IMPORTANTE

  • O BYTE – o que mais usaremos. O byte tem 8 bits de tamanho – isso é 2 nibbles, e é o único valor que você vai conseguir colocar num registrador de 8 bits. EX.: AH, AL, BH, BL, …

Um byte tem um valor máximo de 255 em decimal, 11111111 em binário, ou FFh em hexadecimal.

  • A WORD – outra unidade comumente usada. Uma word é um número de 16 bits, e é capaz de armazenar um número até 65535. Isso é 1111111111111111 em binário, e FFFFh em hex.

Obs.:  Como uma word equivale a quatro nibbles, é também representada por quatro dígitos hexadecimais.

Obs.:  Isto é um número de 16 bits, e corresponde aos registradores de 16 bits. Ou seja, AX, BX, CX, DX, DI, SI, BP,          SP, DS, ES, SS e IP.

  • A DWORD, ou double word consiste de 2 words ou 4 bytes ou 8 nibbles ou 32 bits. Você não vai usar muito as double words nestes tutoriais, mas vamos mencioná-las mais tarde quando falarmos de PROGRAMAÇÃO EM 32 BITS.

Uma DWORD pode armazenar de 0 a 4,294,967,295, que é FFFFFFFFh, ou 11111111111111111111111111111111.  Espero que haja 32 um’s lá atrás.

A DWORD também é o tamanho dos registradores extendiddos de 32 BITS, ou seja, EAX, EBX, ECX, EDX, EDI, ESI, EBP, ESP e EIP.

  • O KILOBYTE, é 1024 bytes, NÃO 1000 bytes.  O kilobyte é igual a 256 double-words, 512 words, 1024 bytes, 2048 nibbles ou 8192 BITS. Eu não vou escrever todos os um’s.
  • O MEGABYTE, ou 1024 kilobytes. Isso é 1,048,576 bytes ou 8,388,608 bits.

Agora que já cobrimos a terminologia, vamos dar uma  olhada mais de perto como aqueles registradores são estruturados. Nós dissemos que AL e AH eram registradores de 8 bits, logo, eles não deveriam se parecer com algo assim?

AH AL
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Neste caso, ambos AH e AL = 0, OU 00h e 00h.  Como resultado, para calcular AX usamos:  AX = 00h + 00h. Quando digo “+” eu quero dizer, ‘ponha junto’ não AX = AH “MAIS” AL.

Assim, se AH era igual a 00000011 e AL era igual a 0000100, para calcular AX nós devemos fazer o seguinte.

1) Pegue os valores hexadecimais de AH e AL.

00000011 = 03h   00010000 = 10h

2) Combine-os.

AX = AH  + AL
AX = 03h + 10h
AX = 0310h

E aí você consegue o resultado. Não é tão macetoso assim.

Okay, agora vamos ver os registradores de 16 bits:

AX
AH AL
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

De onde podemos ver que AX = 00000000 e 00000000, ou 0000000000000000.

Agora por último, vejamos como um registrador de 32 bits se parece:

EAX
AX
AH AL
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

(by Renato – essa tabela estava errada na versão original, colocando o AX na parte mais significtiva de EAX. Eu tomei o direito de consertar. Se estiver errado – era mesmo na parte mais significativa? – me avisem)

Não é muito difícil, espero. E se entendeu isso, você está pronto para SEGMENTOS e OFFSETS.


Uma Arquitetura Segmentada

 

Há muito, muito tempo atrás, quando a IBM construiu o primeiro PC, não era costume programas terem mais de 1 megabyte – eca, os primeiros XT’s tinham apenas 64K de RAM! De qualquer modo, vendo que os projetistas do XT não consideravam aplicações enormes, decidiram dividir a memória em SEGMENTOS, pequenas áreas de memória RAM que você pode colocar APENAS uma tela virtual para gráficos em modo 320x200x256.

É claro, você pode acessar mais de um megabyte de RAM, mas você tem que dividi-la em segmentos para usá-la, e esse é o problema. É obvio, com programação em 32 bits dé pra acessas até 4GB de RAM sem usar segmentos, mas isso é uma outra história.

Segmentos e offsets são apenas um método de especificar uma posição na memória.

Exemplo:

3CE5:502A

^^^^  ^^^^
SEG       OFS

Ok, aqui está a especificação:

Um OFFSET  = SEGMENTO x 16
Um SEGMENTO = OFFSET  / 16

Alguns registradores de segmento são:

CS, DS, ES, SS e FS, GF  – Obs.: Os últimos 2 são registradores que só existem em 386 ou superiores.

Alguns registradores de offset são:

BX, DI, SI, BP, SP, IP   – Obs.: Quando em modo protegido, você pode usar qualquer registrador de uso geral como
um registrador de offset – EXCETO o registrador IP.

Alguns segmentos e offsets comuns são:

CS:IP – Endereço do código executando no momento.
SS:SP – Endereço da posição atual da pilha.

OBS.: NÃO SE INTROMETA COM ESSES DOIS!!!

Assim quando nos referirmos a segmentos e offsets, faremos dessa forma:

SEGMENTO:OFFSET

Um bom exemplo seria:

A000:0000 – que na verdade corresponde ao topo esquerdo da tela VGA em modo colorido 320x200x256.

** FATO ENGRAÇADO ** A RAM da VGA começa em A000h  🙂


Ufa! Isso foi muito para o segundo tutorial. Contudo, ainda não terminamos.
Esse negócio de AX, AH, AL é um conceito que você pode não ter sacado ainda, então lá vamos nós:

 

MOV   AX, 0     ; AX = 0
MOV   AL, 0     ; AL = 0
MOV   AH, 0     ; AH = 0
MOV   AL, FFh   ; AL = FFh
                ; AX = 00FFh
                ; AH = 00h
INC   AX        ; AX = AX + 1
                ; AX = 0100h
                ; AH = 01h
                ; AL = 00h
MOV   AH, ABh   ; AX = AB00h
                ; AH = ABh
                ; AL = 00h

Pegou?


COISAS A FAZER:

 

1) Aprender aquele negócio de BIT/NIBBLE/BYTE… de cor.
2) Voltar nos exemplos de segmento e offset.
3) Tenha certeza que você entendeu a relação entre AX, AH e AL.
4) Que tal um problemas de adição hexadecimal?


A Pilha

 

A pilha é uma característica muito útil de que podemos tirar vantagem. Pense nela como uma pilha de papéis numa bandeja de ENTRADA. Se você põe algo no topo, ela será a primeira a ser tirada.

À medida que você adiciona algo à pilha, o apontador de pilha é DECREMENTADO, e quando tira, é INCREMENTADO. Para explicar isso melhor, veja o diagrama abaixo:

A PILHA
SP

<<<<<  Quando colocamos um byte na pilha, ele vai aqui – último a entrar, primeiro a sair.

<<<<<<  O ponteiro de pilha se move para baixo.

E na prática:

MOV   AX, 03h   ; AX = 03h
PUSH  AX        ; PUSH AX na pilha (coloca no topo)
MOV   AX, 04Eh  ; AX = 04Eh
       ; Faça alguma coisa... uma soma?
POP   AX        ; AX = 03h
Ou:
MOV   AX, 03h   ; AX = 03h
PUSH  AX        ; Adiciona AX à pilha
MOV   AX, 04Eh  ; AX = 04Eh
       ; Faça alguma coisa... uma soma?
POP   BX        ; BX = 03h

Você acabou de aprender duas instruções:

  • PUSH <registrador>   – PUSH (coloca algo na pilha), e
  • POP <registrador>      – POP (retira ele de volta).

É tudo o que você precisa de aprender sobre pilha – por enquanto.


Por último, algumas procedures que demonstram algo disso tudo. Note que os comentários foram DELIBERADAMENTE REMOVIDOS. É seu dever tentar comentá-los. Note também, que algumas novas instruções são introduzidas.

 

Procedure ClearScreen(A : Byte; Ch : Char);   Assembler;
Asm     { ClearScreen }
 mov   ax, 0B800h
 mov   es, ax
 xor   di, di
 mov   cx, 2000
 mov   ah, A
 mov   al, &Ch
 rep   stosw
End;    { ClearScreen }
Procedure CursorXY(X, Y : Word);   Assembler;
Asm    { CursorXY }
 mov   ax, Y
 mov   dh, al
 dec   dh
 mov   ax, X
 mov   dl, al
 dec   dl
 mov   ah, 2
 xor   bh, bh
 int   10h
End;    { CursorXY }
Procedure PutPixel(X, Y : Integer; C : Byte; Adr : Word);    Assembler;
Asm     { PutPixel }
 mov   ax, [Adr]
 mov   es, ax
 mov   bx, [X]
 mov   dx, [Y]
 xchg  dh, dl
 mov   al, [C]
 mov   di, dx
 shr   di, 2
 add   di, dx
 add   di, bx
 stosb
End;    { PutPixel }
Procedure Delay(ms : Word);   Assembler;
Asm     { Delay }
 mov   ax, 1000
 mul   ms
 mov   cx, dx
 mov   dx, ax
 mov   ah, 86h
 int   15h
End;    { Delay }

COISAS A FAZER:

1) Vá ao exemplo de pilha. Faça seu próprio código exemplo.
2) Comente as procedures acima do melhor modo que puder. Tente adivinhar o que  as novas intruções fazem. Não é tão difícil.


NA PRÓXIMA SEMANA

 

  • Muito mais instruções, todos os JUMPS.
  • O que são flags?
  • As procedures acima com comentários.
  • Um programa só em assembler. Você vai precisar pelo menos do DEBUG, embora TASM e TLINK sejam uma boa idéia.

Se você deseja ver um tópico discutido num tutorial no futuro, escreva-me, e eu vou ver o que eu posso fazer.


Não perca!!! Baixe o tutorial da próxima semana na minha homepage:

 

– Adam Hyde.
– Renato Nunes Bastos.

Um comentário em “ASM – Tutorial 2 – Adam Hyde”

  1. Muito bom estou estudando seu tutorais tenho que praticar o2 tutoral ajuda é benvinda nos dias normais sou eletricista trabalho com clp obrigada vou seguindo em frente pois assembli é otimo

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

 

A Nova Krull's HomePage