Introducción: x86
*****************
Intel 4004 de 2.300 transistores en una superficie de 10 micrómetros, producción 1971 — 1981
.. image:: /images/x86/4004.jpg
:alt: Intel 4004
Intel 8080 de 6000 transistores en una superficie de 6 micrómetros, producción 1974
.. image:: /images/x86/8080.jpg
:alt: Intel 8080
:scale: 20 %
Intel 8086 de 20,000 transistores activos en una superficide de 3 micrómetros, producción 1978
.. image:: /images/x86/8086.jpg
:alt: intel 8086
:scale: 30 %
Intel 80286 de 134,000 transistores en una superficie de 1.5 micrómetros, producción 1982
.. image:: /images/x86/80286.jpg
:alt: Intel 80386
:scale: 3 %
Intel 80386 de 275,000 de transistores de 1.5 micrómetro de superficie, producción 1985
.. image:: /images/x86/80386.jpg
:alt: Intel 80386
:scale: 15 %
Intel 80486 de 1,180,235 de transistores de 1 micrómetro de superficie, producción 1985
.. image:: /images/x86/8086.jpg
:alt: Intel 80486
:scale: 10 %
Si un coche hubiera seguido el mismo proceso **hoy un Rolls Royce ahora costaría 1 dólar y con 5 litros de nafta harían mil millones de millas**.
Ley de Moore
------------
En 1965 Gordon Moore, cofundador de Intel formuló una ley empírica que se ha podido constatar hasta nuestros días que dice:
>“Aproximadamente cada dos años se duplica el número de transistores en un microprocesador por unidad de área”
.. image:: /images/x86/moore_law.jpg
:alt: Ley de Moore
Hoy el Intel Core i7 6700k está en litografía de 14 nm
.. image:: /images/x86/moore1.jpg
:alt: Core i7 litography
Bell's Law
----------
Aproximadamente cada diez años (una década) una forma nueva de computadoras basadas en una nueva forma de programación, networking e interface se establece como nuevo uso de la industria.
.. image:: /images/x86/bell_law.png
:alt: Ley de Bell
En los 60 una computadora / Varias Personas
En la actualidad varias CPU / una persona
Arquitectura x86: Hardware
==========================
El modelo de programación desde el 8086 hasta Core2 se denomina **program visible (de programa visible)** porque sus registros son utilizados durante la ejecución del programa y son especificados por las intrrucciones
``ADD dx,cs``
Existen otros tipos de registros que son **program invisible ( invisibles al programa)** ya que no son direccionables directamente en tiempo de ejecución del programa. Únicamente a partir del 80286 existen registros program-invisible, utilizados exclusivamente para control y para operar con memoria protegida, entre otras cosas.
A continuación pueden verse el conjunto de registros de lo microprocesadores desde el 8086 hasta el core2:
.. image:: /images/x86/registros.jpg
* Los modelos 8086, 8088 y 80286 poseían una arquitectura interna de 16 bits.
* Los modelos desde el 80386 hasta Core2 contiene una arquitectura completa de 32 bits.
* Los modelos Pentium 4 y Core2 tambieén contienen una arquitectura de 64 bits cuando operan en modo 64 bits.
El modelo de programacion permite:
* modo -8 bits: AH, AL, BH, BL, CH, CL, DH y DL.
* modo -16 bits: AX, BX, CX, DX, SP, BP, DI, SI, IP, FLAGS, CS, DS, ES, SS, FS Y GS.
* modo -32 bits: EAX, EBX, ECX, EDX, ESP, EBP, EDI, ESI, EIP y EFLAGS .
* modo -64 bits: RAX, RBX, RCX, RDX, RBP, RSI, RDI, RDP, RIP y RFLAGS.
Algunos de estos registros son de proposito genereal como EAX, EBX, ECX, EDX, ESP, EBP, EDI, ESI en 32 bits y sus correspondientes versiones en 64 bits.
Hay que tener en cuenta que en 64 bits existen nuevos registros R8 - R15, además de que la capacidad de los registros se multiplicó por 8, y estos registros adicionales solo pueden ser accedidos en modo 64 bits sin tener un nombre especial para las arquitecturas de 8, 16 y 32. Accediendo a esas partes del registro como:
* MOV R9B,R10B bits de 0-7
* MOV R10W,AX bits de 15-0
* MOV R14D,R15D bits de 31-0
* MOV R13,R12 bits de 63-0
Los Registros de x86
--------------------
Registros multiproposito
------------------------
* **RAX** Return value
* **RBX** callee saved
* **RCX** 4th
* **RDX** 3th
* **RBP** callee saved
* **RSI** 2nd
* **RDI** 1st
* **RDP**
Registros de proposito especial
-------------------------------
* **RIP** Instruction Pointer
* **RSP** Stack Pointer
* **RFLAGS**
Registros de Segmento
---------------------
* **CS (code)**
* **DS (data)**
* **ES (extra)**
* **SS (stack)**
* **FS Y GS**
El Stack
========
Es muy importante entender la estructura del stack dado que esta sigue la pista de de las funciones que se están ejecutando en un programa. Más precisamente la ejecución de un programa se basa practicamente en pusher
Estructura del Stack Frame
--------------------------
En la arquitectura x86 los programas utilizan el stack del programa para soportar la llamada a funciones (o procedimientos). La máquina utiliza el stack para:
* pasar la información de los parámetros,
* almacenar la información de retorno,
* almacenar los valores de ciertos registros para su posterior utilización,y
* para almacenamiento local.
La porción del stack para realizar estas operaciones se denomina **stack frame**. La estructura del stack frame está delimitada por dos valores el *stack frame pointer* registro ``%EBP`` y el *stack pointer* el registro ``%ESP``. El stack pointer puede moverse durante la ejecución de la función pero además toda la información es accedida en forma relativa al stack frame pointer.
Un ejemplo
----------
.. code-block:: c
void MyFunction(){
int a, b, c;
}
siguiendo lo anteriormente dicho:
.. code-block:: asm
_MiFuncion:
push ebp ; save the value of ebp
mov ebp, esp ; ebp now points to the top of the stack
sub esp, 12 ; space allocated on the stack for the local variables
Si en la función se realizan asignaciones a las variables locales:
.. highlight:: c
a = 10;
b = 5;
c = 2;
eso en assembler se transforma en:
.. code-block:: asm
mov [ebp - 4], 10 ; location of variable a
mov [ebp - 8], 5 ; location of b
mov [ebp - 12], 2 ; location of c
Para que se guarda el valor de ebp??
.. highlight:: c
void MyFunction2(int x, int y, int z){
...
}
Esto produce el siguiente código:
.. code-block:: asm
_MyFunction2:
push ebp
mov ebp, esp
sub esp, 0 ; no local variables, most compilers will omit this line
Al realizar la siguiente llamada, por ejemplo:
.. highlight:: c
MyFunction2(10, 5, 2);
Esta llamada genera el siguiente código assembler:
.. code-block:: asm
push 2
push 5
push 10
call _MyFunction2
Tener en cuenta que la instrucción **call** equivale a:
.. code-block:: asm
push eip + 2 ; return address is current address + size of two instructions
jmp _MyFunction2
Resumiendo quedaria :
.. code-block:: asm
; MyFunction2(10, 5, 2);
push 2
push 5
push 10
;call _MyFunction2
push eip + 2 ; return address is current address + size of two instructions
jmp _MyFunction2
...
...
_MyFunction2:
push ebp
mov ebp, esp
sub esp, 0 ; no local variables, most compilers will omit this line
...
...
mov esp, ebp ; exit
pop ebp
ret
El stack quedaria así
::
: :
| 2 | [ebp + 16] (3rd function argument)
| 5 | [ebp + 12] (2nd argument)
| 10 | [ebp + 8] (1st argument)
| RA | [ebp + 4] (return address)
| FP | [ebp] (old ebp value)
| | [ebp - 4] (1st local variable)
: :
: :
| | [ebp - X] (esp - the current stack pointer. The use of push / pop is valid now)
Convencion de llamadas
======================
El conjunto de registros de un procesador es una fuente limitada derecursos, estos son compartidos por las distintas funciones que se estén ejecutando. Si bien en un determinado tiempo t_{0} una única funcion se está ejecutando, en ese lapso, se debe asegurar que cuando una funcion que llama (**caller**) a otra función (**callee**), esta última no sobreescriba todos los valores de los registros, ya que algunos de estos van a ser necesitados por la función llamadora.
Para ellos se define una convensión en el uso de los registros en la arquitectura x86, que **todas** las funciones deben respetar:
* Los registros %EAX, %EDX y %ECX son denominados **caller-save**, es decir, cuando Q es llamado por P, el llamador puede sobreescribir esos registros sin miedo de destruir datos de P.
* Los registros %EBX, %ESI y %EDI son denominados **Callee-save**, esto significa que Q debe guardar los valores de estos registros en la pila antes de sobreeescribirlos y restaurarlos antes de retornar
# [Arquitectura x86: software](/sisop_asm/asm.md)
.. Modo Real de Direccionamiento de Memoria
Únicamente los procesadores 8086 y 8088 operan exclusivamente en modo real, que no existe en el modo de 64 bits de Pentium4 y Core2.
El **Modo Real de Operaciones** permite direccionar al procesador solo los primeros 1 Mbytes de la memoria de una computadora [^1].
Windows no utiliza el modo real.
El **Modo Real** permite a las aplicaciones escritas para 8086 y 888 correr en los procesadores 80286 hacia arriba, _por ello en cualquier caso los procesadores arrancan en modo real_.
La familia de procesadores de Pentium 4 y Core2 en modo de 64 bits no pueden correr modo real, por ello las aplicaciones DOS no son compatibles.
### Segmentos y offsets
Una combinacion de segmento y offset permiten determinar una posicion de memoria en modo real. Una dirección de memoria en modo real consiste en un segmento de memoria y un offset.
La **segment address** se encuentra en uno de los registros de segmentolos cuales apuntan a un segmento de memoria de 64 KB. La **offset address** apunta a cualquier dirección de memoria dentro de un segmento de 64 kb. Los segmentos en Modo Real siempre tiene una longitud de 64Kb, ver imagen

en este modo puede mapearse toda la memoria de la siguiente forma: inicio de la memoria es 00000xh ---> una direccón de memoria en modo real es de 20 bits, por ende el primer segmento se encuentra en 00000xh+64kb = 00000xh+ffffxh.

Si por ejemplo se tiene el segmento 10000xh la dirección de inicio de ese segmento es 10000xh y la dirección de fin de ese segmento es 1ffffxh. el fin de la memoria direccionable en **Modo Real** es facilmente calculabre pues es 2 20 que es exactamente 1MB de memoria.
Algunas veces una dirección de memoria en **Modo Real** puede ser escrito como segmento:offset, por ejemplo 10000:f000.
### Combinaciones Especiales
En modo real existen una serie de reglas que aplican a los registros de segmentos y offsets. Estas reglas son:
1. **CS:IP** localiza la próxima instruccion a aser ejecutada en modo real.
2. **SS:SP** localiza la dirección del puntero al stack, a veces tambien puede ser **SS:BP**.
3. **DS: BX,DI,SI** localizan el puntero a una dirección de memoria dentro del data addres.
4. **ES:DI** puntero al extra data adress donde van los strings.
esta distribucioón es para 16 bits. La misma distribuciòn para 32 bits es la siguiente:
1. **CS:EIP** intruction address.
2. **SS:ESP** o **SS:EBP** stack addres.
3. **DS: EAX,EBX,ECX,EDI,ESI** data address.
4. **ES:EDI** Estring destination addres.
5. **FS:no default** general addres.
6. **GS:no default** general address.
## Modo Protegido
El **modo protegido** permite direccionar a datos y programas más alla de 1 Mb de memoria física, así como también dentro del primer mega de memoria física.
este es el modo donde Windows opera, este modo require por ende un cambion en el escquema utilizado en el **modo real** segmento y desplazamiento u offset para direccionar memoria.
Cuando los programas y los datos son alojados o direccionados a la **memoria extendida**, el **offset address** todavia es utilizado para acceder dentro de un segmento de memoria.
La diferencia es que el segmento de memoria, como el que se presenta en el ++modo real++ ya no está resente como tal en **modo protegido**. En lugar de la dirección del segmento, el **segment register** contiene un valor llamado **selector** que representa un descriptor de una tabla llamada **tabla de descriptores o descriptor table**
Este descriptor posee la informacion la hubicación del segmento de memoria , la longitud y los derechos de acceso. debido a que el **registro de segmento** y el **offset** todabia son un acceso a memoria, las instrucciones de modo protegido son identicas a las intrucciones de modo real.
La diferencia entre los modelos es **la forma en la cual el registro de segmento es interpretado** por el microprocesador para acceder a la memoria.
Otra diferencia es que en procesadores a partir de el 80386 el offset puede ser un número de 32bits, en vez de 16bits. lo que permite al micro porcesador acceder a posiciones de memoria hasta 4GBytes.
### Selectores y Descriptores
* El **selector**, que se encuentra en el registro de segmento , selecciona una de los 8192 descriptores de una de las dos tablas de descriptores.

* El **descriptor** describe el lugar, la longitud y los derechos de acceso del segmento de memoria, y tiene una longitud de 4 bytes.
Por ejemplo, en **modo real** si CS=0008xh esto significaba que apuntaba a la direccion 00008xh de la memoria fisica de la computadora. Ahora en modo protegido el tema es así:
* Existen tablas de descriptores usadas con los registros de segmento:
Una contiene los **descriptores globales**: contiene las definiciones de los segmentos que pueden ser accedidos por totos los programas.
Otra contiene los **descriptores locales**: contienen definiciones de segmento que pertenencesn unicamente a una determinada aplicación.
Cada descriptor ocupa 4 bytes de memoria, ver imagen.También pueden verse escritos como System descriptors y application descriptors.
* Cada tabla tiene 8192 entradas, por un total de 16384 descriptores que estan disponibles para cualquier aplicacions en cualquier momento, entonces como se dijo que los offset pueden ser de 32 bits es decir 4gb de offset, la cantidad total de memoria física direcionable es 232* 16384 = 64 TBytes de memoria.
Notar que cada entrada en la tabla de descriptores es de 8 bytes, la dirección base o base address es de 24 bits y los segmentos son de 16 Mbytes o sea 224

* El **segment limit** el offset de la última dirección, en un procesador 80286 la base address es f00000xh y el limite es 00ffxh, para el 80386 en adelante la base address es 00f00000xh y el limite es 000ffxh. por ende:
*80286 tiene 16 bit de limite lo que hace que pueda acceder entre 1 y 64 kb de largo
*80386 - Pentium 4 tiene 20bits de limite, lo que hace que los segmentos de memoria esten entre 1 y 1 Mb o 4k y 4 Gb de longitud.

En el gráfico a continuación se muestra un ejemplo concreto:

## Paginación de memoria
El mecanismo de paginación de memoria que aparece a partir de los porcesadores intel 80386 y sus subsiguientes modelos. Permite que cualquier **lugar de la memoria física o physical address** sea asignada a cualquier **dirección lineal o lineal address**.
Una **dirección lineal** (a) se define como una dirección de memoria generada por un programa.
Una **dirección física** (b) es el lugar actual de la memoria al que accede un programa.

Con la unidad de paginación de memoria es posible que cualquier **lineal address** sea asignada a una determinade **physical address**, lo que permite que un programa escrito para funcionar en una determinada dirección sea rehubicada por el mecanismo de paginación de forma transparente.
###Los Registros de Paginación
La unidad de paginacipón es controlada por el contenido de los registros de control de microprocesador.

Estos registros se encuentran a partir del microprocesador intel 80386 hasta Core2. A partir del Pentium4 un registro llamado CR4 extiende la arquitectura x86, por ejemplo haciendo que las páginas de memoria sean en vez de 2MBytes de 4Mbytes ( esto lo controla el CR4).
Los registrs importantes para la paginacion son: CR0 y CR3.
* El bit mas a la izquierda de el registro CR0 si está en 0 determina que la lineal address se conviete directamente en physical address para acceder a la memorai. Si PG está en 1 la lineal addres debe ser convertida en physical address a través del mecanismo de paginación.
* CR3 continen **page directory base** que contiene 1024 entradas de 4 bytes cada una, cada entrada en el **page directory** ocupa 4 bytes y direcciona a una **page table** que contiene 1024 entradas.
Una **linear address** generada dentro del espacio de memoria de un proceso está compuesta de tres partes:
1. Page Directory bits 31-22 (10 bits)
2. Page Table Entry bits 21-12 (10 bits)
3. Memory Page offset address bits 11-0 (12 bits)

Cada entrada en el page directory representan 4 MBytes de memoria del sistema, esto significa que 00000000xh-00000fffxh selecciona la page directory entry 0, la page table entry 0 y un rango de 4kBytes de offset. Entonces, si por ejemplo si la entrada 0 page table contiene la dirección 00100000xh entonces significa que la dirección fisica 00100000xh-00100ffffxh corresponden a las linear address 00000000xh-0000ffffxh

ttener en cuenta que en procesadores desde Pentium a Core2 las páginas pueden ser de 4kBytes, 2Mbytes o 4 Mbytes

.....That's all Folks!!!!! .....
[^1]:Notar que el primer Mb de memoria es llamado **memoria real**, **memoria convencional** o **memoria DOS**.
{ % include footnotes.html % }