ASM1B

********************

AX ( Acumulador)

********************

 

Como o nome já diz, AX tem como função principal acumular dados quando envolvido com as operações IN ( entrada de dados), OUT (saída de dados ), Multiplicação, Divisão, Ajuste Decimal e XLAT. Além disso em AX pode ser  retornado algum dado ao se usar as INTs ou algumas instruções. Por exemplo:

 

mov    AH , 01H

INT      21H

 

Conforme dito, estas linhas acima imprimem a correspondente tecla pressionada e também retornam o código ASCII da tecla pressionada. O valor ASCII da tecla fica então em AL. Mais exemplos disso tudo será visto adiante.

 

No entanto, só pra matar a curiosidade, veja este exemplo:

 

< rotina > tecla

< inicio > vamos

 

    < leia E imprima teclado >   ;guarda o código ASCII da tecla pressionada                                                         ; em AL

    < se > AL = "L" < faça >:

            < vá para > fim

    < se não> 

            < vá para > vamos

 

 

fim :

        < saída >

 

tecla       < fim rotina >

vamos    < fim inicio >

 

Em ASM isso seria assim :

 

tecla    segment

         assume cs : tecla

         org    100h

 

vamos:

            mov    AH,01h

            int    21h

 

            cmp    AL,"L"    ; CMP diz: compare o dado de AL com "L"

            je     fim      ; , JE diz :Se AL for igual a "L", vá 

                                                              ;para o rótulo fim

 

            jmp    vamos       ; Vá para o rótulo vamos

 

fim:

            mov    AH,04ch     ; função para sair do pro DOS

            int    21h

 

tecla    ends

            end        vamos

 

Ou se não:

 

tecla    segment

         assume cs : tecla

         org    100h

 

vamos:

 

            mov    ax,0

             .while    ax != "L"

       

                        mov    AH,01h

                  int    21h

 

             .endw

                    

                 mov    AH,04ch     ; função para sair do pro DOS

               int    21h

 

tecla    ends

         end        vamos

 

 

 

 

********************

BX ( Base )

********************

 

Pode ser usado como registrador BASE para referenciar posições na memória.

 

 

<Posição> <Dados> X <Variáeis> <Tipo> <Valor>
0129 00 X array DB ?
012A 41  42  43  44  45 X ponto DB "A", "B","C", "D", "E"
012F 00 X mais DB ?

 

 

Os códigos que representam as posições de memória ( <posição> ) estão em hexadecimal. Observe que as posições de memória estão em ordem crescente.

 

"DB" significa declare BYTE. "Sim...mas como BX é usado para referenciar posições de memória ?"

 

O significado de BX é registro de BASE. Portanto ele irá guardar uma posição de memória, que servirá, como diz o nome, de BASE para acessar outras variáveis, ou dados "dentro" dessas variáveis, vetor  ( array ).

 

Veja este exemplo:

                                        1              2            3              4            5

<declare>     dia [ "segunda", "terça", "quarta", "quinta", "sexta"]     <array>

<declare>     hoje     <caractere>

<declare> deslo1, deslo2 < numérico> 

 

deslo1 = 2

deslo2 = 5

 

hoje = dia[ deslo1  ]                       ; hoje  = terça

hoje = dia[ deslo2 ]                       ; hoje = sexta

 

 

No nosso caso isso seria assim:

 

mov    BX , offset ponto    ; BX = 012AH

mov    DI , 3                        ; DI = 3H

mov    CL,  [ BX + DI ]       ; CL =  BX  + DI >>> CL = 012A + 3>>> 

                                            ; CL = 012C

 

 

Se BX é 012AH e DI é 3H, então o dado que deverá ter CL será BX + DI =

012Ah + 3h = 012Ch. Que por sua vez, é igual a letra "C" ou 43h em hexadecimal.

 

Portanto, BX guarda um endereço BASE, que será acessado por meio de um deslocamento. O algoritmo disso seria assim:

 

                            1     2      3      4      5 

<declare> BX [ "A", "B", "C", "D", "E" ] <array>

<declare> CL <caractere>

<declare> DI <numérico>

 

DI = 3

 

CL = BX [ DI ]                        ; CL = "C"

 

 

Agora em ASM seria assim :

 

planeta    segment

               assume cs:planeta

               org    100h

 

inicio:

            mov    AL,03h    ;função para definir modo texto e limpar tela

            mov    ah,00h

            int       10h

 

            Lea    bx,ponto     ; carrega bx com o endereço efetivo  de "ponto"                                                       

 

            mov    ah,01h        ; função para imprimir tecla na tela

            int       21h           

            

            sub      AL,30h    ; subtraia de AL 30h( AL = AL - 30h )

            cbw                   ; converta o dado de AL( que é byte,DB, para word DW

            mov     di, ax                           ; di = ax

            mov     CL, [ bx + di ]              ; CL = bx + di, mas lembre-se, bx=ponto

                                  

            mov     ah,02h        ;função para definir a posição do cursor

            mov     dl,00h          ; DL = coluna

            mov     dh,04h        ; DH = linha

            mov     bx,00h        ; página

            int        10h 

             

            mov     ah,02h    ;função para imprimir um caractere na tela

            mov    DL, CL    ;DL = valor do caractere

            int       21h

    

    ; Aqui em baixo temos a saída do programa

 

            mov    ah,04ch

            int        21h

 

    ; Aqui em baixo temos a declaração das variáveis

 

ponto        DB    "A", "B", "C", "D", "E"

 

planeta    ends

                 end    inicio

 

Para compilar jogue isso no bloco de notas e salve como "dicas.asm" ou qualquer coisa ".asm". Mas lembre-se de salvar na pasta onde esta o MASM e o LINK . Feito isso vá para o DOS e siga os passos descritos em "ASM Nível 1 A".

 

Para brincar com ele, você só deve usar o teclado NUMÉRICO. E e os números de 1 a 5. Se digitar "1", na tela aparecerá "1" e a letra "A". Caso escolha "2", a letra "B" e assim sucessivamente. 

 

Quanto ao demais instruções, no tempo certo haverá exemplos apropriados.           

 

********************

CX ( Contador )

********************

 

 

Novamente, como sugere o nome, CX é usado como contador. Nas instruções de escrita e leitura em arquivos, onde temos de "dizer" a quantidade de bits a ser movida de uma posição de memória para outra. É usado em conjunto com a instrução LOOP e "companhia", onde certa operação será repetida até o conteúdo de CX ( ou CL ) chegar a zero. Uma outra que pega a alguns são as instruções de deslocamento e rotação. Já vi várias paginas e tutoriais assim:

 

    mov    ax , 02H

    sal      ax , 1    ; onde "1" é o expoente, ou seja 2^n, onde n é "1"

 

    Isso nos diz :

    ax = 02h

    ax = 2^n * ax     ; onde n=1 >>>  ax = 2^1 * 02h >>> ax = 04h

 

Como resultado temos que : ax = 04h

 

SAL multiplica apenas números múltiplos de 2^n. Ou seja se: n=1, 2^1 =2; mas se n=2, 2^2 =4; se n=3, 2^3 = 8 e assim vai. "Onde entra CX nisso tudo ?" Com o SAL e companhia, se quiser multiplicar por um número 2^n, diferente de 2 é claro, tem de fazer "n" = CL. Por exemplo: Talvez queira multiplicar o número 5( decimal ) por 8 ( decimal ), usando SAL. Se fizer isso está completamente ERRADO :

 

mov    ax , 5

SAL    ax , 3

 

Isso ai em cima esta ERRADO !!! O correto é  movimentar o valor do expoente para CL, o exemplo CORRETO disso está ai em baixo :

 

mov    CL , 3

mov    ax , 05H

SAL    ax,CL

 

Como resultado teremos :

CL = 03H    ; em decimal 3

AX = 05H    ; em decimal 5

AX = 2^n * AX     ; onde n = CL = 3  >>>  AX = 2^3 * 2 >>> AX = 8 * 5 = 40  em decimal

 

 

E falta agora o LOOP. Lembra-se dessa estrutura ? :

 

< para > conta = 1 < até > 10 < faça >

        [ Bloco de instruções ]

< fim para >

 

Em ASM seria :

 

xor    cx , cx    ; Isso zera CX, CX = 0

mov    CX , 100

 

zere :                ; "zere :" é um rótulo

 

lea      si , dado1

mov    [ si ] , 0

inc       si

 

LOOP    zere

 

Digamos que queira zerar 100 variáveis de seu programa, é lógico que não faria, um a um, até 100, faria? :

 

mov    dado1, 0

mov    dado2, 0

mov    dado3, 0

          . 

          .

          .

mov    dado100, 0

 

Acho que não faria isso 100 vezes, faria ? Nem eu! :)  Por isso usamos  o CX, ou CL. "E com "CH", não funciona ?" NÃO!!! a razão disso, ainda não sei, mas prometo perguntar aos meus "gurus" :) Mas caso duvide de min, compile e execute este programa:

 

loop1  segment
            assume     cs:loop1
            org         100h

inicio:
            mov     al,3
            mov     ah,0
            int         10h

            lea         si,m1
            xor         cx,cx

            mov      ch,3
            mov      al,30h

volte:
            inc         al
            mov     [si],al
            inc     si
            loop     volte


            mov     ah,9
            lea     dx,m1
            int     21h


            mov     ah,04ch
            int     21h


m1         db     3 dup (?),"$"
c1          db      ?


loop1     ends
               end         inicio 

Se compilar verá "123456789..." e um monte de caracteres na tela. Mas se trocar "mov    CH,3" por "mov    CL,3" ou "mov    CX,3" ve´ra que o programa funciona corretamente.

Depois que falarmos sobre DX, SP, BP, SI e DI, veremos as instruções em ASM, quanto aos FLAGS deixo para a o Nível 2.

 

 

 

********************

DX ( Dados )

********************

 

 

Muito usado em operações de IN e OUT para especificar o endereço de uma porta de I / O ( IN/OUT )

DX também é usado em operações de multiplicações para armazenar parte um produto de 32 bits, ou em operações de divisão para armazenar o resto.

 

 

Nas aulas práticas de Assembly tínhamos sempre que escolher uma(s) porta(s) para acionar algum led, display numérico ou sensor. Isso era feito assim :

 

mov    DX , 80h     ; onde 80h é endereço da porta de entrada ou saída

IN        AL , DX      ; IN diz : leia o conteúdo da porta 80h e mova para AL

AND   AL , 03H    ; AND diz : AL = AL * 03H ou AL = AL AND 03h 

 

JNZ    eh_um_pule    ; JNZ diz : Se a operação anterior resultar em "1" vá para o rótulo

 

Assim que acabar com o Nível 3 [ Nem acabei o Nível 1! :)  ] Vou dedicar-me a eletrônica Digital, que é tão vasto quanto o assembly. Aliás, programação e eletrônica digital é uma coisa só!

 

DX é usado também para armazenar parte de um produto de 32bits. Nesses casos, o número mais significativo, de maior valor, é armazenado em DX, em quanto o número menos significativo em AX. A "soma" de DX e AX resulta num número de 32bits. Por exemplo :

 

AX = 5

CX = 2    ; ambos os números decimais, 5 e 2, são de 16bits ( DW )

 

MUL = AX * vamos     ; MUL diz : Multiplique AX por CX, resultado mais 

                                      ;significativo salve em DX, e o menos em AX                    

                                     

 

Os bits de DX e AX são preenchidos da seguinte forma :

 

DX = 0000 0000B    ;número mais significativo, os últimos 16bits

 

AX = 10001 0000B    ;número menos significativo, os primeiros 16bits

 

Em ASM seria assim :

 

mov    cinco, 5

mov    dois, 2

 

mov    cx , cinco

mov    ax , dois

 

MUL   cx

 

cinco     dw    5

dois       dw    2

 

Em DX teremos : 00H. 

Em AX teremos : 0AH, que é 10 em decimal

 

Mais exemplos sobre a instrução MUL, só no futuro.

 

 

Com isso chegamos ao fim dos Registradores de Utilidade Geral. 

No entanto ainda falta comentar os Registradores Ponteiros e de Índice que possuem as mesmas características dos registradores vistos acima, com a diferença destes serem de APENAS 16bits, NÃO podendo "segmenta-los" ou "dividi-los" em dois outros registros. 

 

 

Registradores Ponteiros e de Índice

 

Lembram-se dos velhos vetores ( array) ? Os registradores ponteiros e de índice servem para armazenar valores de deslocamento, que por sua vez, podem acessar certo dado na memória.

 

BP e SP servem pra armazenar o deslocamento no segmento de pilha corrente.( "Deslocamento, segmento, o que é isso ?" ) No Nível 1 C respondo. Já SI e DI armazenam deslocamentos no segmento de dados corrente. Se não entendeu, você é normal :) Alguns exemplos irão "clarear" o que foi dito acima.

 

********************

SP

*******************

 

SP tem como função apontar sempre para a o topo da pilha. Por isso é chamado de ponteiro de pilha. " ...pilha, o que é... ? " Lembre-se duma pilha de livros. Você coloca um livro de Matemática na mesa. Depois, um livro de Física, em cima do de Matemática, formando uma pilha de 2 livros. Agora você coloca um livro de "C" nessa pilha, em cima do de Física, formando uma pilha de 3 livros. E para encerrar um livro de "C++", em cima do de "C".

 

Sua pilha ficaria assim :

 

C++                        4º livro a ser posto na pilha     /  1º livro a ser pego       

C                             3º livro a ser posto na pilha     /  2º livro a ser pego

Física                      2º livro a ser posto na pilha     /  3º livro a ser pego

Matemática            1º livro a ser posto na pilha     /  4º livro a ser pego

 

Qual livro você pega primeiro ? Não é o 4º, que foi o último posto na pilha ? 

E o segundo livro ? Não é o 3º, que foi o penúltimo posto na pilha ?

E o terceiro livro ? Não é o 2º, que foi o ante-penúltimo posto na pilha ?

 

A nossa pilha, em ASM, funciona da mesma forma. De modo que o primeiro dado a ser posto na pilha, será SEMPRE o último a sair.

 

Veja como se faz isso:

 

 

< declare > c1, b2 < numérico>

< rotina > pilha

 

< defina modo texto e limpe a tela >

 

inicio:

 

< imprima tecla>            

< se > AX = 13 < faça >

          < vá para > mostre

C1 = C1 + 2

< pilha = AX, pilha = pilha+1 >

< vá para > inicio

 

< imprima tecla >

AX = AX - 30H        ;

AX = 2 * AX             ; esqueça esta parte!!!

C1 = C1 - AX           ;

 

DI = C1

 

< pilha, BP = SP >        ; Esta instrução aponta para o topo da pilha,

                                        ; e vimos que o "topo" da pilha,  é "último livro posto"

AX = [ BP + DI ]

 

< imprima AX >

 

< fim rotina>

O algoritmo acima diz o seguinte: Toda tecla digitada pelo usuário é SALVA na pilha. Quando se digita ENTER ( = 13 decimal ou 0Dh ) Damos início a 2º parte do programa. Agora vamos recuperar um dado SALVO na pilha. Para isso temos que apontar para BP ( que é explicado logo em baixo ) o topo da pilha, que é SP. Feito isso podemos acessar os dados digitados pelo usuário, bastando para tanto, que este DIGITE um valor numérico. É esse número que diz em que posição os dados digitados estão. 

 

Depois que compilar o programa abaixo, o execute, e digite :

 

ABCDEF 

 

Feito isso tecle em ENTER . Você notará que o cursor ficará em baixo da letra "A". Agora tecle o número "3". Ao fazer isso aparecerá :

 

C

 

Digitando "3" temos como resultado a letra "C". Se fosse 2, a letra "B" e assim sucessivamente. Só pra matar a curiosidade, foi feito um ASM.

 

;

; Acesso a pilha de modo crescente, ou seja, o 1º dado digitado pelo usuário

; é imprimido na tela, quando digitamos o número "1"

;

;E poderíamos fazer o contrario, como a acesso a pilha de modo decrescente

; , ou seja, o último dado digitado pelo usuário é imprimido na tela, quando

; digitamos o número "1"

;

;Neste exemplo o acesso a pilha é feito de modo crescente.


pilha         segment
                assume cs:pilha
                org 100h

inicio:
            mov     ah,0
            mov     al,3
            int     10h

escre:
            mov ah,1            ;imprima tecla na tela sem o echo, ou seja é VÍSIVEL
            int     21h
            cbw

            push     ax                ; Salve na pilha

            add     c1,2               ; incrementa-se C1 de 2 em 2

            cmp     al,0dh            ; compare AL com 0DH
            je         mostre                ; Se for igual, vá para o rótulo "mostre"

            jmp     escre        ; vá para o rótulo "escre"

 mostre:

            mov     ah,7        ; imprime tecla com echo, ou seja, NÃO é visível
            int        21h
            cbw


            sub       ax,30h
            sal         ax,1             ; lógica crescente para acessar a pilha, ou seja
            sub       c1,ax         ; o dígito "1" corresponde ao 1º dado da pilha
          
            mov     di,c1
            MOV    BP,SP    ;Basta fazer isso, e pronto!
                                         ; Esta instrução aponta para o topo da pilha,

                                         ; e vimos que o "topo" da pilha,  é "último livro posto"

            mov     ax,[bp+di]

            mov     b2,ax

            mov     ah,2        ; imprima na posição da  LINHA e COLUNA
            mov     dl,0         ; o cursor
            mov     dh,4        
            mov     bx,0
            int        10h


            mov     ah,2            ; imprima caracter
            mov     dx,b2
            int         21h

fim:

            mov     ah,04ch        ; sai pro DOS
            int         21h    


b2         dw         ?
c1         dw         ?    


pilha         ends
                 end         inicio
    

 

Um pouco grande não acha ? Só  serviu para mostrar como se usa SP.

O mesmo exemplo citado em cima é válido para BP, portanto não haverá um exemplo de programa com BP.

 

 

********************

BP

*******************

 

 

Serve apenas para acessar dados que foram salvos via pilha. É conhecido como ponteiro base, pois serve de referência para acessar dados salvos na pilha. O exemplo disso esta logo em cima.

 

 

********************

SI

*******************

 

Exemplos de aplicações para essa "coisinha" não faltam :) SI é conhecido como "índice fonte". Ou seja, em algumas instruções ASM, contém o "índice fonte", o início ou começo de qualquer coisa que deverá ser "passado" para outro registro, ou variável. Não entendeu ? É como se SI "lê-se" um dado e armazena-se "todo" seu conteúdo. Nas aplicações de "strings", a string a ser copiada TEM DE ESTAR em SI, que é o "índice fonte".

 

Algo que deve ter notado em SI, pelos exemplos citados, é que pode armazenar um deslocamento, que é usado para ter acesso a um vetor (array)

 

Usarei o mesmo algoritmo e exemplo citado em BX para SI  :

                                        1              2            3             4             5

<declare>     dia [ "segunda", "terça", "quarta", "quinta", "sexta"]     <array>

<declare>     hoje     <caractere>

<declare> deslo1, deslo2 < numérico> 

 

deslo1 = 2

deslo2 = 5

 

hoje = dia[ deslo1  ]                       ; hoje  = terça

hoje = dia[ deslo 2 ]                       ; hoje = sexta

 

Em ASM seria assim :

                             1     2      3      4      5

<declare> BX [ "A", "B", "C", "D", "E" ] <array>

<declare> CL <caractere>

<declare> SI <numérico>

 

SI = 3

 

CL = BX [ SI ]                        ; CL = "C"

 

O exemplo ASM disso é visto em BX. Mas pra matar a curiosidade,  veja como SI é usado em operações com strings :

 


dados         segment
                    assume     cs:dados
                    org 100h

inicio:
            mov     ah,0
            mov     al,3
            int     10h

            lea     di,copy
senha:
            mov     ah,1
            int     21h

            mov     [di],al
             inc       di

            cmp     al,13
            jne     senha

            xor     di,di

            lea     si,blk1
            lea     di,copy
            mov     cx,10
            repe     cmps     blk1,copy
            cmp     cx,0
            je         volte

            jmp     fim

volte:

            mov     ah,2
            mov     dl,0
            mov     dh,2
            mov     bx,0
            int         10h

            mov     ah,9
            lea      dx,copy
            int       21h

            mov     ah,04ch
            int         21h


fim:
            mov     ah,2
            mov     dl,0
            mov     dh,4
            mov     bx,0
            int     10h

            mov     cont,cx
            mov     ax,10
            sub     ax,cx
            inc       ax
            sal       ax,1
            add     ax,36
            mov    cx,cont
            add     cx,ax

            mov     ah,2
            mov     dx,cx
            int         21h


            mov     ah,04ch
            int         21h


blk1               db         "AssemblyBR",13,"$"
copy             db         11 dup(?),"$"
cont              dw         ?

dados         ends
                    end         inicio

 

Compile e execute este ASM.

 

Esse troço funciona assim : Você tem de digitar a senha : "AssemblyBR"

e depois teclar ENTER. Feito isso aparecerá o número "0", indicando que nenhum erro foi encontrado. 

Execute o programa novamente. agora digite:"AssomblyBR" e depois tecle ENTER . Feito isso aparecerá o número "3", indicando que a 3ª letra depois do "A" está incorreta.

 

OBS : Para não ver a tela coberta de caracteres "estranhos" não digite mais de 10 caracteres.

 

Neste exemplo SI é usado como "índice fonte" ou referência, pois é a string de SI que é a nossa senha :"AssemblyBR". Por isso o valor a ser comparado tem como referência correta a senha : "AssemblyBR".

 

 

 

 

**************

DI

**************

 

DI é usado como "índice destino",ou seja, em operações de escrita de strings (caractere). É usado da mesma forma que SI, e pode alocar um deslocamento, e acessar dados em um vetor (array). Exemplos do uso de DI para acessar dados em um vetor foram vistos em BX. Mas veja este exemplo:

 

leia    segment

          assume    cs:leia

          org    100h

 

inicio:

 

            mov        ah,0

            mov        al,3

            int            10h

 

            mov        ah,1

            int           21h

 

            cld

            lea        si,leia_dado

            lea        di,esc_dado

            mov      cx,10    

            rep        movsb    

 

            mov        ah,9

            lea          dx,esc_dado

            int           21h

 

fim:

            mov        ah,04ch

            int           21h

           

leia_dado    db    10 dup ("AssemblyBR"),"$"

esc_dado    db    10 dup(?),"$"

 

leia        ends

              end    inicio

 

O que este exemplo faz é mover a string "AssemblyBR" para DI. Pois em SI,"índice fonte", temos a string a ser copiada, e em DI "índice destino",o "local" onde será salvo a string de SI.

 

Compile e execute o programa acima. Nesse caso não precisará fazer nada, basta executar o programa, que logo em seguida, a frase :"AssemblyBR" estará na tela. Quanto ao "cld","rep" e "movs" só mais tarde :(

 

Bem, sobre o que significa "deslocamento", "segmento","offset" e ect, será visto no Nível 1 C, bem como um exame mais detalhado sobre a instrução MOV. Quanto aos modos de endereçamento, que são uns 6, ou 7, não lembro bem agora, ficarão para o Nível 1 D.