             i----------------------------------------------
              RBT      Curso de Assembly      Aula N 04 
             ----------------------------------------------

Por: Frederico Pissarra


i-------------
 ASSEMBLY IV 
-------------

    Comearemos a ver algumas instrues  do  microprocessador  8086
agora.  Existem os seguintes tipos de instrues:

     Instrues Aritimticas
     Instrues Lgicas
     Instrues de Controle de Fluxo de Programa
     Instrues de manipulao de flags
     Instrues de manipulao da pilha
     Instrues de manipulao de blocos
     Instrues de manipulao de registradores/dados
     Instrues de Entrada/Sada

    Vamos   comear   com   as   instrues   de   manipulao    de
registradores/dados por serem estas as mais fceis de entender.

i---------------
 Instruo MOV 
---------------

    MOV tem a finalidade  de  MOVimentar  um  dado  de um lugar para
outro.  Por exemplo, para carregar um registrador com um determinado
valor.  Isto  feito com MOV:

 +----------------------------------------------------------------+
   MOV AX,0001h                                                  
 +----------------------------------------------------------------+

     a mesma coisa que dizer: "AX = 1".  Na verdade, movimentamos o
valor 1 para dentro do registrador AX.

    Podemos mover o contedo de um registrador para outro:

 +----------------------------------------------------------------+
   MOV BH,CL                                                     
 +----------------------------------------------------------------+

     a mesma coisa que "BH = CL"!

    Os registradores de segmento no podem ser inicializados com MOV
tomando um parametro imediato (numrico).  Esses  registradores  so
inicializados indiretamente:

 +----------------------------------------------------------------+
   MOV DS,0    ; ERRADO!!!                                       
                                                                 
   MOV AX,0                                                      
   MOV DS,AX   ; CORRETO!                                        
 +----------------------------------------------------------------+

    Carregar um registrador com o contedo (byte ou word, depende da
instruo!) armazenado em um segmento  simples, basta especificar o
offset  do  dado  entre  colchetes.  Ateno que o segmento de dados
(DS)  assumido por default com algumas excesses:

 +----------------------------------------------------------------+
   MOV AL,[0FFFFh]                                               
 +----------------------------------------------------------------+

    A instruo acima, pega o byte armazenado no endereo DS:FFFFh e
coloca-o em  AL.   Sabemos  que  um  byte  vai  ser  lido  do offset
especificado porque AL tem 8 bits de tamanho.
    Ao  invs  de  usarmos  um  offset  imediato  podemos  usar   um
registrador:

 +----------------------------------------------------------------+
   MOV BX,0FFFFh                                                 
   MOV CH,[BX]                                                   
 +----------------------------------------------------------------+

    Neste caso, BX contm o offset e o  byte  no  endereo  DS:BX  
armazenado  em  CH.   Note  que  o  registrador  usado  como  indice
obrigatoriamente deve ser de 16 bits.

    Uma   observao   quanto   a  essa  modalidade:  Dependendo  do
registrador usado como offset, o segmento default poder ser  DS  ou
SS.   Se  ao invs de BX usassemos BP, o segmento default seria SS e
no DS - de uma olhada no diagrama de distribuio dos registradores
no texto anterior.  BP foi colocado  no mesmo bloco de SP, indicando
que ambos esto relacionados com  SS  (Segmento  de pilha) - Eis uma
tabela das modalidades e dos segmentos default que podem ser  usados
como offset:

 +---------------------------------------------------------------+
   Offset usando registros        Segmento default             
 +-----------------------------+---------------------------------
   [SI + deslocamento]            DS                           
   [DI + deslocamento]            DS                           
   [BP + deslocamento]            SS                           
   [BX + deslocamento]            DS                           
   [BX + SI + deslocamento]       DS                           
   [BX + DI + deslocamento]       DS                           
   [BP + SI + deslocamento]       SS                           
   [BP + DI + deslocamento]       SS                           
 +---------------------------------------------------------------+

    O  "deslocamento"  pode  ser  suprimido  se  for 0.

    Voc  pode evitar o segmento default explicitando um registrador
de segmento na instruo:

 +----------------------------------------------------------------+
   MOV DH,ES:[BX]      ;Usa ES ao invs de DS                    
   MOV AL,CS:[SI + 4]  ;Usa CS ao invs de DS                    
 +----------------------------------------------------------------+

    Repare que tenho usado os registradores de 8 bits para armazenar
os dados... Pode-se usar os de 16 bits tambm:

 +----------------------------------------------------------------+
   MOV ES:[BX],AX         ; Poe o valor de AX para ES:BX         
 +----------------------------------------------------------------+

    S que neste caso sero armazenados 2 bytes no  endereo  ES:BX.
O  primeiro  byte    o  menos  significativo  e  o  segundo  o mais
signigicativo.  Essa instruo equivale-se a:

 +----------------------------------------------------------------+
   MOV ES:[BX],AL            ; Instruess que fazem a mesma     
   MOV ES:[BX + 1],AH        ;coisa que MOV ES:[BX],AX           
 +----------------------------------------------------------------+

    Repare tambm que no  possvel mover o contedo de uma posio
da  memria  para  outra,  diretamente,  usando  MOV.   Existe outra
instruo que faz isso: MOVSB ou MOVSW.   Veremos  essas  instrues
mais tarde.

    Regra geral: Um dos operandos TEM que ser um registrador!  Salvo
no caso da movimentao de um imediato para uma posio de memria:

 +---------------------------------------------------------------+
   MOV [DI],[SI]       ; ERRO!                                  
   MOV [BX],0          ; OK!                                    
 +---------------------------------------------------------------+

    Para ilustrar o uso da instruo MOV, eis um  pedao  do  cdigo
usado  pela  ROM-BIOS  do  IBM  PS/2  Modelo  50Z  para  verificar a
integridade dos registradores da CPU:

 +----------------------------------------------------------------+
   ...                                                           
   MOV AX,0FFFFh            ;Poe 0FFFFh em AX                    
   MOV DS,AX                                                     
   MOV BX,DS                                                     
   MOV ES,BX                                                     
   MOV CX,ES                                                     
   MOV SS,CX                                                     
   MOV DX,SS                                                     
   MOV SI,DX                                                     
   MOV DI,SI                                                     
   MOV BP,DI                                                     
   MOV SP,BP                                                     
   ...                                                           
 +----------------------------------------------------------------+

    Se o contedo de BP no  for  0FFFFh  ento a CPU est com algum
problema e o computador no pode funcionar!  Os flags  so  testados
de uma outra forma...  :)


i------
 XCHG 
------

    Esta instruo serve para trocarmos o contedo de um registrador
pelo outro. Por exemplo:

 +----------------------------------------------------------------+
   XCHG    AH,AL                                                 
 +----------------------------------------------------------------+

    Se  AH=1Ah  e  AL=6Dh,  aps  esta instruo AH=6Dh e AL=1Ah por
causa da troca...

    Pode-se  usar uma referncia  memria assim como em MOV...  com
a  mesma  restrio  de  que  um   dos  operandos  TEM  que  ser  um
registrador.   No  h  possibilidade  de usar um operando imediato.


i---------------
 MOVSB e MOUSW 
---------------

    Essas  instrues  suprem   a   deficincia   de  MOV  quanto  a
movimentao  de  dados  de  uma   posio  de  memria  para  outra
diretamente.  Antes de ser chamada os  seguintes  registradores  tem
que ser inicializados:

 +---------------------------------------------------------------+
   DS:SI   <- DS e SI tm o endereo fonte                      
   ES:DI   <- ES e DI tm o endereo destino                    
 +---------------------------------------------------------------+

    Dai podemos executar MOVSB ou MOVSW.

    MOVSB move um byte, enquanto MOVSW move um word (16 bits).

    Os registradores SI e  DI  sao incrementados ou decrementados de
acordo com o flag D (Direction) - Veja discusso sobre os  flags  na
mensagem  anterior.   No  caso de MOVSW, SI e DI serao incrementados
(ou decrementados) de 2 posies de  forma que DS:SI e ES:DI apontem
sempre para a prxima word.


i---------------
 STOSB e STOSW 
---------------

    Essas  instrues  servem para armazenar um valor que est em AX
ou AL  (dependendo  da  instruo  usada)  no  endereo apontado por
ES:DI.  Ento, antes de  ser  chamada,  os  seguintes  registradores
devem ser inicializados:

 +----------------------------------------------------------------+
   AX      -> Valor a ser armazenado se usarmos STOSW            
   AL      -> Valor a ser armazenado se usarmos STOSB            
   ES:DI   -> Endereo onde o dado ser armazenado               
 +----------------------------------------------------------------+

    Depois   da   execuo   da  instruo  o  registrador  DI  ser
incrementado ou decrementado de acordo com o flag D (Direction).  DI
ser incrementado de 2 no  case  de  usarmos STOSW, isto garante que
ES:DI aponte para a proxima word.


i---------------
 LODSB e LODSW 
---------------

    Essas  instrues  servem para ler um valor que est no endereo
apontado  por  DS:SI  e  armazen-lo  em  AX  ou  AL  (dependendo da
instruo  usada).   Ento,  antes  de  ser  chamada,  os  seguintes
registradores devem ser inicializados:

 +----------------------------------------------------------------+
   DS:SI   -> Endereo de onde o dado ser lido                  
 +----------------------------------------------------------------+

    Depois   da   execuo   da  instruo  o  registrador  SI  ser
incrementado ou decrementado de acordo com o flag D (Direction).  No
caso de usarmos LODSW, SI ser incrementado de 2 para  garantir  que
DS:SI aponte para a prxima word.

i------------------------------------------------------------------
 Outras instrues de manipulao de registros/dados              
------------------------------------------------------------------

    Existem ainda as instrues LEA, LES e LDS.

  LEA:

    LEA ,  basicamente,  igual  a  instruo  MOV,  com  apenas uma
diferena: o  operando  "fonte"    um  endereo  (precisamente:  um
"offset").   LEA  simplesmente calcula o endereo e transfere para o
operando  "destino",  de   forma   que   as  instrues  abaixo  sao
equivalentes:

 +----------------------------------------------------------------+
   MOV     BX,100h                                               
   LEA     BX,[100h]                                             
 +----------------------------------------------------------------+

    Porm, a instruo:

 +----------------------------------------------------------------+
   LEA     DX,[BX + SI + 10h]                                         
 +----------------------------------------------------------------+

    Equivale a:

 +----------------------------------------------------------------+
   MOV     DX,BX                                                 
   ADD     DX,SI         ; DX = DX + SI                          
   ADD     DX,10h        ; DX = DX + 10h                         
 +----------------------------------------------------------------+

    Repare que apenas uma  instruo  faz  o  servio de trs!!  Nos
processadores 286 e  386  a  diferena    significativa,  pois,  no
exemplo acima, LEA gastar  3  (nos  286)  ou  2 (nos 386) ciclos de
mquina enquando o equivalente gastar 11 (nos 286) ou 6  (nos  386)
ciclos  de  mquina!   Nos processadores 8088/8086 a diferena no 
tao grande...

    Obs:
        Consideremos cada ciclo  de  mquina seria, aproximadamente,
        num 386DX/40, algo em torno de 300ns - ou 0,0000003s.   uma
        medida empirica e no expressa a grandeza real  (depende  de
        uma srie de fatores no considerados aqui!).

    O  operando  "destino"    sempre  um  registrador.   O operando
"fonte"  sempre um endereo.

  LDS e LES

    Existe  uma  forma  de  carregar   um   par   de   registradores
(segmento:offset)  de uma s vez.  Se quisermos carregar DS:DX basta
usar a instruo LDS, caso o alvo seja ES, usa-se LES.

    Suponhamos que numa posio  da  memria tenhamos um double word
(nmero  de  32  bits)  armazenado.   A  word   mais   significativa
correspondendo  a  um  segmento  e a menos signigicativa a um offset
(esse  o caso da tabela dos vetores de interrupo, que descreverei
com poucos detalhes em uma outra oportunidade!). Se usamos:

 +----------------------------------------------------------------+
   LES BX,[SI]                                                   
 +----------------------------------------------------------------+

    O par ES:BX  ser  carregado  com  o  double  word armazenado no
endereo  apontado  por  DS:SI  (repare  no  segmento  default   que
discutimos  em um texto anterior!).  A instruo acima  equivalente
a:

 +---------------------------------------------------------------+
   MOV     BX,[SI+2]                                            
   MOV     ES,BX                                                
   MOV     BX,[SI]                                              
 +---------------------------------------------------------------+

    De novo, uma instruo substitui trs!

i-----------------------------------------------------------------
 Manipulando blocos... parte I                                   
-----------------------------------------------------------------

    As instrues MOVSB, MOVSW, STOSB, STOSW, LODSB  e  LODSW  podem
ser usadas para lidar com blocos de dados.  Para isto, basta indicar
no  registrador  CX  a  quantidade  de  dados  a serem manipulados e
acrescentar  REP  na  frente  da  instruao.   Eis  um trecho de uma
pequena rotina que apaga o video em modo texto (80 x 25 colorido):

 +---------------------------------------------------------------+
   MOV AX,0B800h                                                
   MOD ES,AX           ; Poe em ES o segmento do vdeo          
   MOV DI,0            ; Comea no Offset 0                     
   MOV AH,7            ; AH = atributo do caracter              
                       ;      7 = cinza com fundo preto         
   MOV AL,' '          ; AL = caracter usado para apagar        
   MOV CX,2000         ; CX = contador (4000 bytes ou           
                       ;      2000 words).                      
   REP STOSW           ; Preenche os 2000 words com AX          
 +---------------------------------------------------------------+

    O modificador REP diz a instruo que esta deve ser executada CX
vezes.  Note que a cada execuo de STOSW o registrador DI  apontar
para a proxima word.

    Suponha que queiramos  mover  4000  bytes  de  alguma posio da
memria para o video, preenchendo a tela com esses 4000 bytes:

 +---------------------------------------------------------------+
   MOV AX,0B800h                                                
   MOD ES,AX           ; Poe em ES o segmento do vdeo          
   MOV AX,SEG TABELA                                            
   MOV DS,AX           ; Poe em DS o segmento da tabela         
   MOV SI,OFFSET TABELA ; Comea no offset inicial da tabela    
   MOV DI,0            ; Comea no Offset 0                     
   MOV CX,4000         ; CX = contador (4000 bytes)             
   REP MOVSB           ; Copia 4000 bytes de DS:SI para ES:DI   
 +---------------------------------------------------------------+

    Nota:  O  modificador  REP  s  pode  ser  preceder as seguintes
instrues: MOVSB, MOVSW, STOSB,  STOSW, LODSB, LODSW, CMPSB, CMPSW,
SCASB, SCASW, OUTSB, OUTSW, INSB, INSW.  As instrues nao vistas no
texto acima sero detalhadas mais tarde...

    Existem   mais    algumas    instrues    de   manipulao   de
registradores/dados, bem como mais algumas de manipulao de blocos.
Que ficaro para uma prxima mensagem.
