Seja Bem Vindo(a)




|
Registradores

Este texto é de livre distribuição. Como também estou em fase de aprendizado resolvi escrever este texto para pessoas com um pouco de dificuldade como eu ou que queiram aprender (ou tentar). Tentarei ser o mais claro possível.
Vamos mandar a bala.
Registradores
Os processadores possuem espaços específicos onde são guardados valores, os chamados registradores. Esses espaços são parecidos com variáveis de uma linguagem de programação de alto nível, onde se guarda um valor qualquer até que este seja modificado.
Explicarei neste humilde artigo os registradores dos processadores x86 (*86, pentiuns, etc) Tomarei como base que o leitor possui uma pequena noção sobre computação.
Registradores de uso geral (genéricos): Os registradores de uso geral, como o próprio nome diz :-), podem ser usados para quaisquer fins, porém para haver uma maior compreensão do código assembly, atribuimos certas funções a estes registradores. Bem, dependendo do código, somos obrigados a usar certos registradores
AX -> Registrador acumulador, geralmente onde instruções devolvem resultado e também usado para o processador saber o número de uma suposta interrupção.
BX -> Base. Eu sinceramente não sei dar uma explicação mais completa deste registrador, porém é usado geralmente guardando endereços base (ou apontador) para endereços (offsets)
CX -> Contador. Este registrador é usado como contador, geralmente em loops (iterações), onde se guarda um valor em CX e este é usado para saber quantas "voltas", ou técnicamente dizendo, quantas iterações irão ser executadas, ao fim de cada volta, diminuindo seu valor em 1.
DX -> Dados. Usado genéricamente para guardar dados de outras instruções. Por exemplo em sua parte baixa (ver adiante) é guardado o código ASCII do simbolo a ser exibido na tela.
Registradores de Destíno/Origem
São usados geralmente com instruções onde blocos de memória ou dados são movidos copiados, etc.
SI -> Índice Fonte. É usado geralmente para apontar a origem de uma seqüencia de dados em certas instruções de manuseio bloco.
DI -> Índice Destíno. Usado para apontar o destíno de uma seqüencia de dados usado em certas instruções de manuseio bloco.
Registradores de Pilha (Stack)
A pilha é realmente como uma pilha de pratos onde vai se colocando pratos (dados) e logo após retirando-os. Sempre seguindo a regra LIFO (Last in First Out - Ultimo a entrar, primeiro a sair). Sempre o último dado que você colocou na pilha, é o primeiro que você obterá ao requisitar o dado. Geralmente esses registradores só são mechidos por instruções específicas, nunca manualmente.
BP -> Base Pointer, apontador de base. Aponta o endereço base da pilha, ou seja o primeiro offset (local da memória) onde os dados começarão a ser empilhados.
SP -> Stack Pointer, apontador da pilha. Aponta, referencia o endereço onde foi colocado o último dado na pilha.
Registradores de Segmento
São os registradores que apontam segmentos da memória onde sao colocados o código, dados, etc. Veja a seguir.
CS -> Code Segment, segmento de código. Aponta para o local da memória onde o código do programa começa.
DS -> Data Segment, segmento de dados. Aponta para o local da memória onde os dados (variáveis, etc) estão. É usado geralmente em instruções de manuseio de bloco.
ES -> Extra segment, segmento extra. É como um local a mais para se guardar dados, geralmente usado em algumas instruções de manuseio de bloco.
SS -> Stack Segment, segmento de pilha. É onde o processador coloca dados de retorno de uma função (como em linguagens de alto nível)
Instrução
IP -> Instruction Pointer. (apontador de instrução). Este simples registrador aponta para a próxima instrução (local da memória da mesma). Tome cuidado com este :-). Modificando-o pode se causar sérios problemas no programa hehehe
Flag
Flag é um registrador onde cada bit significa um estado da cpu. Vai o significado de cada bit (copiarei de um tutorial do Frederico Pissarra)
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).
(Fim da cópia :-) )
Sobre a parte alta e baixa dos registradores de uso geral que prometi falar.
Estes registradores são de 16 bits (2 bytes ou 1 word, tudo equivalente, não se preocupe), e são dividitos em duas partes de oito bits (ou duas partes de 1 byte).
Estes registradores tem sua parte alta "H" (High) e sua parte baixa "L" (Low). Para usa-los, substitui o X de AX, BX, CX ou DX pelo H ou L.
A grande sacada disto tudo é pelo fato de que interrupções e instruções devolvem ou "pegam" valores de somente uma parte deste registradores.
É óbvio, não tão óbvio mas é :-), que ao se alterar o valor da parte baixa ou alta, você estara alterando o valor do registrador inteiro.
Ex: AX -> 16 Bits AX = 2 ("2" em binario eh "10") AH = "00000000" em binario AL = "00000010" em binário
Se vc alterar AH para o valor 3 (11 em binario), vc tera estes valores
AX = 0000001100000010 = 770 AH = 00000011 AL = 00000010
Bem. O que tenho para dizer sobre registradores é isso. Existe muitíssimas coisas a mais para aprender com assembly, eu ainda sei somente o básico, estou querendo aprender, ainda sou adolescente estudante de curso técnico de informática, por isso não é preciso exigir tanto de mim :-).
Escrevi este tutorial para pessoas igual ou melhores que eu que queiram aprender, aperfeiçoar ou simplesmente passar o tempo lendo algo diferente :-)
Qualquer dúvida, sujestão, crítica, correção, errata, qualquer coisa, ficarei muitíssimo grato se vc me enviar um email para lucas_r@uol.com.br.
Bem isso é tudo.
Obrigado.
Lucas
|
Autor: Lucas
|
|