Introducción: x86

Intel 4004 de 2.300 transistores en una superficie de 10 micrómetros, producción 1971 — 1981

Intel 4004

Intel 8080 de 6000 transistores en una superficie de 6 micrómetros, producción 1974

Intel 8080

Intel 8086 de 20,000 transistores activos en una superficide de 3 micrómetros, producción 1978

intel 8086

Intel 80286 de 134,000 transistores en una superficie de 1.5 micrómetros, producción 1982

Intel 80386

Intel 80386 de 275,000 de transistores de 1.5 micrómetro de superficie, producción 1985

Intel 80386

Intel 80486 de 1,180,235 de transistores de 1 micrómetro de superficie, producción 1985

Intel 80486

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”

Ley de Moore

Hoy el Intel Core i7 6700k está en litografía de 14 nm

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.

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:

_images/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

void MyFunction(){
 int a, b, c;

}

siguiendo lo anteriormente dicho:

_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:

eso en assembler se transforma en:

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??

Esto produce el siguiente código:

_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:

Esta llamada genera el siguiente código assembler:

Tener en cuenta que la instrucción call equivale a:

Resumiendo quedaria :

; 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)