SET 39 Call For Papers

¿Eres un hacker? Si deseas pasar a formar parte de la historia del hacking hispano, colabora con la próxima edición de SET 39 enviándonos un artículo. No esperes más, esta es tu oportunidad de demostrar lo que sabes. Ayúdanos a construir una revista de hackers para hackers. SET Staff

SET 13

92845 visitas

Diseccion del 8086

      4472

Autor: Sir Willy the Psikopath
-[ 0x0D ]--------------------------------------------------------------------
-[ DISECCION DEL 8086 ]------------------------------------------------------
-[ by Sir Willy the Psikopath ]---------------------------------------SET-13-

[Comentarios por el buenazo de Rufus T. Firefly]

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
FUNCIONAMIENTO DE LOS PROCESADORES 80X86:
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

                               BY
                               ___    _              _     _ ___
<_ ||_>   \  /\  /||  |  \ /    | |_||_   |_><_ ||/ | ||_>|_| | |_|
 _>|| \    \/  \/ ||__|__ |     | | ||_   |   _>|| \|_||  | | | | |

Hola amigos,

Este es el primer articulo que escribo para saqueadores y espero que,
aunque sea de nivel bastante bajo (casi elemental), le sirva a alguien
para entender como funcionan los procesadores 80x86. Tambien puede servir
para entender mejor como funciona el lenguaje ensamblador, ya que casi
es programar en lenguaje maquina. Bueno, manos a la obra. Para empezar,
presentaremos la estructura basica del procesador:

[[[
Saquedores con mayuscula, un poco mas de respeto.

Venga, hombre que hace tiempo que dejamos preescolar, pero seguro que
a mas de uno le viene bien. ;) Por poner un ejemplo, a algun tio de cierto
departamente de I+D le vendra cojonudo.

Lo que me temia, directo a los registros.
Hagamos una introduccion sobre un ordenador abstracto:
Cualquier ordenador se compone de CPU, Memoria y Periferia.
En el modelo basico solo la CPU puede hablar con los otros dos (luego
salio el DMA y nos jodio el esquema de Neuman, ese tan tipico y potito).
Y no digamos si empezamos con gestores, copros y otras cosas, el pobre Neuman
desaparece entre tantos aditivos.

Internamente la CPU no son solo registros, incluye muchas partes, siendo
las basicas el decodificador-secuenciador, la ALU y los registros (ahora
si). El tema es que de la CPU como programadores solo vemos registros.

El decodificador se encarga de interpretar los bytes que se van cargando
en un registro destinado a tal fin, y luego mediante el secuenciador va
dando las microordenes a los otro elementos (los RISC no suelen necesitar
microordenes).
La ALU es la unidad matematica, encargada de todo lo que tenga que ver con
numeritos. (Arithmetic Logical Unit)
Y los registros son sitios donde guardar datos temporalmente. Facil, šno?

En modelos mas avanzados de CPUs se incluyen gestores de memoria virtual,
unidades de coma flotante, ALUs especializadas en algun tipo de operaciones,
caches internas, reordenadores de instrucciones, predictores de saltos, etc
hasta llegar a esos monstruos con millones de transitores, que hacen cosas
en paralelo.

De todos modos prefiero los RISC o los 68k, los x86 siempre me dieron cierto
repelus. Son autenticos parche sobre parche. Y cuando se vea segmentacion nos
volveremos locos de atar.
Sigamos... que el articulo promete.
]]]

    .-------------------------.
 AX |     AH     |     AL     |  REGISTRO ACUMULADOR
    |------------+------------|
 BX |     BH     |     BL     |  REGISTRO DE BASE
    |------------+------------|
 CX |     CH     |     CL     |  REGISTRO CONTADOR
    |------------+------------|
 DX |     DH     |     DL     |  REGISTRO DE DATOS
    `-------------------------'
    .-------------------------.
    |           SP            |  PUNTERO DE PILA
    |-------------------------|
    |           BP            |  PUNTERO DE BASE
    |-------------------------|
    |           SI            |  INDICE DE FUENTE
    |-------------------------|
    |           DI            |  INDICE DE DESTINO
    `-------------------------'
    .-------------------------.
    |           CS            |  SEGMENTO DE CODIGO
    |-------------------------| 
    |           DS            |  SEGMENTO DE DATOS
    |-------------------------|
    |           SS            |  SEGMENTO DE PILA
    |-------------------------|
    |           ES            |  SEGMENTO EXTRA DE DATOS
    `-------------------------'
    .-------------------------.
    |           PC            |  CONTADOR DE PROGRAMA
    `-------------------------'
    .-------------------------.
    |           SR            |  REGISTRO DE ESTADO
    `-------------------------'

Internamente el 8086 guarda toda la informacion necesaria para la
ejecucion de las instrucciones en un grupo de 14 registros de 16 bits.
El esquema de la arquitectura interna de la CPU del 8086 se muestra en
el diagrama de encima de estas lineas. En el se puede distinguir:

-REGISTROS GENERALES:
=====================
Son 4 registros de 16 bits denominados AX, BX, CX y DX. Cada uno de 
ellos puede usarse subdividido como dos registros de 8 bits denominados
AH-AL, BH-BL, CH-CL Y DH-DL. AH corresponde a los 8 bits de m s peso
(High) del registro AX y AL a los de menos peso (Low) del mismo registro
AX. Igualmente se puede aplicar todo esto a los demas bloques BX, CX y
DX. Estos cuatro registros de proposito general actuan como acumuladores
en instruciones de transferencia de datos, instrucciones logicas e
instrucciones aritmeticas. En general, por ser registros acumuladores,
pueden ser utilizados para guardar los operandos de las instrucciones,
asi como para guardar el resultado de la operacion. Solo BX se puede
emplear como registro base para los direccionamientos indirectos.

[[[
Los nombres del grafico son muy orientativos sobre que utilidad suele
tener cada uno. Aunque podemos usarlos como queramos, salvo lo de BX,
no esta mal hacer caso a los nombres.
]]]

-REGISTROS DE SEGMENTO:
=======================
Son cuatro registros de 16 bits indivisibles, que se utilizan para
acceder a una determinada zona de la memoria denominada segmento. El tema
de la organizacion y el acceso a la memoria en los sistemas basados en el
æP-8086 los explicare mas detalladamente al final con un grafico. El
contenido de cada uno de los registros indica un determinado segmento de
memoria dentro de la general del sistema. El nombre y la funcion
especifica de estos registros es la siguiente:

-CS: segmento de codigo, apunta a la zona de memoria en donde se almacenan
     los codigos binarios en leguaje maquina de las instrucciones del
     programa.
-DS: segmento de datos, se€ala la zona de memoria en donde se almacenaran
     los datos en binario que van a ser utilizados o generados por el
     programa.
-SS: segmento de pila, identifica la zona de memoria que va a ser utilizada
     por el programa como la pila del sistema para almacenar datos
     intermedios durante la ejecucion de un programa.
-ES: segmento extra, permite definir un nuevo segmento para datos.

-REGISTROS PUNTEROS:
====================
Son cinco registros indivisibles todos ellos de 16 bits. Junto con uno de
los registros de segmento sirve para acceder a una determinada posicion de
memoria. El contenido de un registro puntero se denomina desplazamiento u
offset. Con el contenido de este registro se obtiene el desplazamiento
dentro del segmento definido por el correspondiente registro de segmento.
Los cuatro registros punteros son:

SI y DI: contienen el offset para la busqueda de direcciones para datos,
         utilizando como registro de segmento DS o ES.

SP y BP: se utilizan para contener los desplazamientos asociados a la pila
         del programa, por tanto, utilizan como registro de segmento el SS.

IP: denominado registro contador de programa, contiene el valor del
    desplazamiento, que, unido al registro de segmento de codigo, indicado
    por el registro CS, permite obtener la direccion de memoria donde se
    encuentra almacenado el codigo de la instruccion que va a ser ejecutada.

[[[
Proxima posicion de donde leer una instruccion, para ser exactos.
Cuando se lee byte a byte (por ejemplo en una tartana 8088), se usa IP para
saber donde esta el proximo byte a leer (de la instruccion, no datos).
En cuanto se lee, se incrementa IP, para saber que ya hemos leido.

Cuando se hacen llamadas a rutinas, se guarda automaticamente IP y si es
necesario tambien CS (que justo al poco de empezar la orden de llamada ya no
vale la posicion de dicha orden, sino la siguiente), para que cuando se haga
el retorno se lea el primer byte de la instruccion siguiente:

0011 llamada fulanito -> al comenzar IP vale 0011, segun se ejecuta
                         IP vale 0012, luego se guarda y se salta.
0012 suma             -> al volver de fulanito, se empieza aqui
                         porque el IP que se guardo es 0012.
]]]

-REGISTRO DE ESTADO O DE BANDERAS:
==================================
Es un registro indivisible de 16 bits que guarda informacion sobre el
estado del microprocesador despues de la ejecucion de ciertas instrucciones
especificas, generalmente aritmeticas. Por ejemplo, si al realizar una
instruccion de suma, el resultado es de cero, un bit de este registro,
denominado bandera Z, se pone a 1. Si el resultado de la suma hubiese sido
diferente de cero, la bandera Z se habria puesto en 0. En las instrucciones
de salto o bifurcacion condicional, el estado de algun bit de este registro
determina la realizacion o no del salto solicitado.


ORGANIZACION Y ACCESO A MEMORIA DE SISTEMAS BASADOS EN EL æP-8086:
==================================================================
El æP-8086 es capaz de direccionar 1Mbyte de memoria. Para tener acceso a
1Mb, el sistema dispone de 20 lineas en el bus de direcciones. Sin embargo,
los registros internos del æP-8086 son como maximo de 16 bits. šComo con
un registro de 16 bits se puede indicar una direccion de memoria de hasta
1Mb, para lo cual se necesitaria emplear 20 bits? El æP-8086 utiliza la
combinacion de dos registros internos de 16 bits para obtener una direccion
real de 20 bits. El valor almacenado en un registro de segmento especifica
un determinado segmento de memoria. Un registro puntero guarda un valor
denominado DESPLAZAMIENTO u OFFSET relativo a un determinado segmento. El
segmento i el offset se combinan para obtener una direccion real de 20 bits
como sigue: el valor contenido en el registro segmento se desplaza a la
izquierda 4 bits (equivale a multiplicar x16 en hexadecimal), al resultado
obtenido se le suma el contenido del registro puntero u offset tal como se
muestra en el siguiente diagrama:

15                    0
.--------------------------------. NUMERO
| REGISTRO DE SEGMENTO | 0 0 0 0 | SEGMENTO
`--------------------------------'
15              |     0
.---------------+------.           OFFSET
|               |      |
`---------------+------'
           |    |
           V    V
          --------- 
          \   +   /                SUMADOR
            --+-- 
              |
19            V                 0
.--------------------------------. DIRECCION
|                                | EFECTIVA
`--------------------------------'
Por ejemplo, supongamos que el valor almacenado en el registro de segmento
DS es, en hexadecimal, 1000h, i en el registro puntero SI el valor, en
hexadecimal, es 201h. Si en un programa se accede a la posicion de memoria
representada como DS:SI(1000h:201h), la direccion real de memoria a la que
se esta accediendo se obtiene ralizando la operacion siguiente:

            (DSx16)+SI, en el ejemplo (1000hx16)+201h=1020h

En resumen, la memoria de estos sistemas se encuentra dividida a nivel
logico en bloques de memoria denominados SEGMENTOS. Desde el punto de vista
del programador, una posicion de memoria se representa por un segmento y un
desplazamiento. El valor del segmento debe estar almacenado en uno de los
registros de segmento. El valor de desplazamiento se encuentra en un registro
puntero o bien se indica en la propia instruccion.

Para acceder a una posicion de memoria, el microprocesador calcula la
direccion real, multiplicando el contenido del registro segmento implicado
por 16. A este se le suma el offset o desplazamiento.

Normalmente, en un programa las instrucciones deben estar guardadas en un
segmento (de codigo), los datos en uno o dos segmentos (de datos) distintos
al anterior y la zona de memoria dedicada a la pila en otro segmento (de
pila).

Antes de ejecutar un programa se deben cargar los registros de segmento CS,
DS y SS, con los valores de los segmentos respectivos. Esta operacion la
realiza automaticamente el sistema operativo, excepto para el registro DS.
Como cada segmento tiene un tama€o maximo de 64Kbytes (2 elevado a 16), en
cada fase del programa, el 8086 solo es capaz de direccionar 4 x 64 Kbytes,
del Mbyte de memoria maxima total.

Para acceder al resto de la memoria se deben cambiar los valores de
los registros de segmento. Hay programas en los que se definen varios
segmentos con instrucciones y/o varios segmentos de datos, e incluso varios
segmentos dedicados a la pila. En estos casos, debe ser el propio programa el
que se encargue de modificar los registros de segmento actuales 
direccionandolos hacia el segmento adecuado.

Bueno, aqui acaba mi articulo, espero que le sirva a alguien para algo. Si
quereis, en proximos articulos comentare algo de los programas en lenguaje
ensamblador, aunque creo que la gente que domina el tema de los virus ya
tendra un extenso dominio de este lenguaje ya que es imprescindible a la
hora de programarlos. Para la gente que no domine este leguaje, hay
programas en la red para fabricarlos, aunque no son mas potentes que los
de cosecha propia.

Hasta aluego, lucas. HARLLLLLLL!!!!!

[[[
Venga, que seguro que la gente quiere mas... madera, que es la guerra!!!
šAlguien se anima con los 68k? šO los PPC?
]]]