Skip to content

Aula 01: Curso de Assembly

Cleilson edited this page Dec 24, 2018 · 1 revision
         i----------------------------------------------©
         ¦ RBT   ¦   Curso de Assembly   ¦   Aula Nº 01 ¦
         È----------------------------------------------¥

Por: Frederico Pissarra

i------------©
¦ ASSEMBLY I ¦
È------------¥

A linguagem ASSEMBLY (e näo  assemblER!) dá medo em muita gente!

Só näo sei porque! As liguagens ditas de "alto nível" säo MUITO mais complexas que o assembly! O programador assembly tem que saber, antes de mais nada, como está organizada a memória da máquina em que trabalha, a disponibilidade de rotinas pré-definidas na ROM do micro (que facilita muito a vida de vez em quando!) e os demais recursos que a máquina oferece.

Uma  grande  desvantagem  do  assembly  com  relaçäo  as  outras

linguagens é que näo existe tipagem de dados como, por exemplo, ponto-flutuante... O programador terá que desenvolver as suas próprias rotinas ou lançar mao do co-processador matemático (o TURBO ASSEMBLER, da Borland, fornece uma maneira de emular o co-processador). Näo existem funçöes de entrada-saída como PRINT do BASIC ou o Write() do PASCAL... Näo existem rotinas que imprimam dados numéricos ou strings na tela... Enfim... näo existe nada de útil! (Será?! hehehe)

Pra que serve o  assembly  entäo?   A  resposta é: Para que você

possa desenvolver as suas próprias rotinas, sem ter que topar com bugs ou limitaçöes de rotinas já existentes na ROM-BIOS ou no seu compilador "C", "PASCAL" ou qualquer outro... Cabe aqui uma consideraçäo interessante: É muito mais produtivo usarmos uma liguagem de alto nível juntamente com nossas rotinas em assembly... Evita-se a "reinvençäo da roda" e näo temos que desenvolver TODAS as rotinas necessárias para os nossos programas. Em particular, o assembly é muito útil quando queremos criar rotinas que näo existem na liguagem de alto-nível nativa! Uma rotina ASM bem desenvolvida pode nos dar a vantagem da velocidade ou do tamanho mais reduzido em nossos programas.

O  primeiro  passo  para  começar  a  entender  alguma  coisa de

assembly é entender como a CPU organiza a memória. Como no nosso caso a idéia é entender os microprocessadores da família 80x86 da Intel (presentes em qualquer PC-Compatível), vamos dar uma olhadela no modelamento de memória usado pelos PCs, funcionando sob o MS-DOS (Windows, OS/2, UNIX, etc... usam outro tipo de modelamento... MUITO MAIS COMPLICADO!).

i---------------------------------------------©
¦ Modelamento REAL da memória - A segmentaçäo ¦
È---------------------------------------------¥

A memória de qualquer PC é dividida em segmentos.  Cada segmento

tem 64k bytes de tamanho (65536 bytes) e por mais estranho que pareça os segmentos näo säo organizados de forma sequencial (o segmento seguinte näo começa logo após o anterior!). Existe uma sobreposiçao. De uma olhada:


                               64k
    +-----------------------------------------------------+
    +------------------------------------------------------------+
    ¦                                                     ¦
    ¦      ¦      ¦                                       ¦      ¦
    ¦                                                     ¦
    +------------------------------------------------------------+
    0      1      2 <- Numero do segmento
    +-------------+
       16     16
     bytes   bytes

O  segundo  segmento  começa   exatamente  16  bytes  depois  do

primeiro. Deu pra perceber que o inicio do segundo segmento está DENTRO do primeiro, já que os segmentos tem 64k de tamanho!

Este  esquema  biruta  confunde  bastante os programadores menos

experientes e, até hoje, ninguem sabe porque a Intel resolveu utilizar essa coisa esquisita. Mas, paciência, é assim que a coisa funciona!

Para  encontrarmos  um  determinado  byte  dentro de um segmento

precisamos fornecer o OFFSET (deslocamento, em inglês) deste byte relativo ao inicio do segmento. Assim, se queremos localizar o décimo-quinto byte do segmento 0, basta especificar 0:15, ou seja, segmento 0 e offset 15. Esta notaçäo é usada no restante deste e de outros artigos.

Na  realidade  a  CPU  faz  o  seguinte cálculo para encontrar o

"endereço físico" ou "endereço efetivo" na memória:

 +-----------------------------------------------------------------+
 ¦         ENDEREÇO-EFETIVO = (SEGMENTO * 16) + OFFSET             ¦
 +-----------------------------------------------------------------+

Ilustrando  a  complexidade   deste  esquema  de  endereçamento,

podemos provar que existem diversas formas de especificarmos um único "endereço efetivo" da memória... Por exemplo, o endereço 0:13Ah pode ser também escrito como:

0001h:012Ah     0002h:011Ah     0003h:010Ah     0004h:00FAh
0005h:00EAh     0006h:00DAh     0007h:00CAh     0008h:00BAh
0009h:00AAh     000Ah:009Ah     000Bh:008Ah     000Ch:007Ah
000Dh:006Ah     000Eh:005Ah     000Fh:004Ah     0010h:003Ah
0011h:002Ah     0012h:001Ah     0013h:000Ah

Basta fazer as contas que você verá que todas estas formas daräo

o mesmo resultado: o endereço-efetivo 0013Ah. Generalizando, existem, no máximo, 16 formas de especificarmos o mesmo endereço físico! As únicas faixas de endereços que näo tem equivalentes e só podem ser especificados de uma única forma säo os desesseis primeiros bytes do segmento 0 e os últimos desesseis bytes do segmento 0FFFFh.

Normalmente o programador näo tem que se preocupar com esse tipo

de coisa. O compilador toma conta da melhor forma de endereçamento. Mas, como a toda regra existe uma excessäo, a informaçäo acima pode ser útil algum dia.

+-------------------------------------------------------------------+
¦ A BASE NUMÉRICA HEXADECIMAL E BINARIA (para os novatos...)        ¦
+-------------------------------------------------------------------+

Alguns  talvez  näo  tenham  conhecimento  sobre as demais bases

numéricas usadas na área informata. É muito comum dizermos "código hexadecimal", mas o que significa?

É bastante lógico que usemos o sistema decimal  como  base  para

todos os cálculos matemáticos do dia-a-dia pelo simples fato de temos DEZ dedos nas mäos... fica facil contar nos dedos quando precisamos (hehe).

Computadores usam o sistema binário por um outro motimo simples:

Existem apenas dois níveis de tensäo presentes em todos os circuitos lógicos: níveis baixo e alto (que säo chamados de 0 e 1 por conveniência... para podermos medi-los sem ter que recorrer a um multímetro!). O sistema hexadecimal também tem o seu lugar: é a forma mais abreviada de escrever um conjunto de bits.

Em decimal, o número 1994, por exemplo, pode ser escrito como:
       1994 = (1 * 10^3) + (9 * 10^2) + (9 * 10^1) + (4 * 10^0)
Note a base 10  nas  potências.   Faço  agora uma pergunta: Como

representariamos o mesmo númer se tivessemos 16 dedos nas mäos?

Primeiro teriamos que obter mais digitos... 0 até 9 näo säo suficientes. Pegaremos mais 6 letras do alfabeto para suprir esta deficiencia.

Segundo, Tomemos como inspiraçäo um odômetro (equipamento disponível em qualquer automóvel - é o medidor de quilometragem!): Quando o algarismo mais a direita (o menos significativo) chega a 9 e é incrementado, o que ocorre?... Retorna a 0 e o próximo é incrementado, formando o 10. No caso do sistema hexadecimal, isto só acontece quando o último algarismo alcança F e é incrementado! Depois do 9 vem o A, depois o B, depois o C, e assim por diante... até chegar a vez do F e saltar para 0, incrementando o próximo algarismo, certo?

Como contar em base diferente  de  dez  é uma situaçäo näo muito

intuitiva, vejamos a regra de conversäo de bases. Começaremos pela base decimal para a hexadecimal. Tomemos o número 1994 como exemplo. A regra é simples: Divide-se 1994 por 16 (base hexadecimal) até que o quoeficiente seja zero... toma-se os restos e tem-se o númer convertido para hexadecimal:

  +---------------------------------------------------------------+
  ¦ 1994 / 16     -> Q=124, R=10      -> 10=A                     ¦
  ¦ 124 / 16      -> Q=7, R=12        -> 12=C                     ¦
  ¦ 7 / 16        -> Q=0, R=7         ->  7=7                     ¦
  +---------------------------------------------------------------+

Toma-se entäo os restos de baixo para cima, formando o número em

hexadecimal. Neste caso, 1994=7CAh

Acrescente um 'h' no fim do número para sabermos que se trata da

base 16, do contrário, se olharmos um número "7CA" poderiamos associa-lo a qualquer outra base numérica (base octadecimal por exemplo!)...

O processo inverso,  hexa->decimal,  é  mais  simples...   basta

escrever o númer, multiplicando cada digito pela potência correta, levando-se em conta a equivalencia das letras com a base decimal:

 +-----------------------------------------------------------------+
 ¦  7CAh = (7 * 16^2) + (C * 16^1) + (A * 16^0) =                  ¦
 ¦         (7 * 16^2) + (12 * 16^1) + (10 * 16^0) =                ¦
 ¦         1792 + 192 + 10 = 1994                                  ¦
 +-----------------------------------------------------------------+

As mesmas regras podem  ser  aplicadas  para a base binária (que

tem apenas dois digitos: 0 e 1). Por exemplo, o número 12 em binário fica:

 +-----------------------------------------------------------------+
 ¦  12 / 2      -> Q=6, R=0                                        ¦
 ¦  6 / 2       -> Q=3, R=0                                        ¦
 ¦  3 / 2       -> Q=1, R=1                                        ¦
 ¦  1 / 2       -> Q=0, R=1                                        ¦
 ¦                                                                 ¦
 ¦  12 = 1100b                                                     ¦
 +-----------------------------------------------------------------+

Cada digito na base binária é conhecido como BIT (Binary digIT -

ou digito binário, em inglês)! Note o 'b' no fim do número convertido...

Faça o processo inverso... Converta 10100110b para decimal.

A vantagem de usarmos um  número  em base hexadecimal é que cada

digito hexadecimal equivale a exatamente quatro digitos binários! Faça as contas: Quatro bits podem conter apenas 16 números (de 0 a 15), que é exatamente a quantidade de digitos na base hexadecimal.

Clone this wiki locally