Introducción: x86¶
Intel 4004 de 2.300 transistores en una superficie de 10 micrómetros, producción 1971 — 1981
Intel 8080 de 6000 transistores en una superficie de 6 micrómetros, producción 1974
Intel 8086 de 20,000 transistores activos en una superficide de 3 micrómetros, producción 1978
Intel 80286 de 134,000 transistores en una superficie de 1.5 micrómetros, producción 1982
Intel 80386 de 275,000 de transistores de 1.5 micrómetro de superficie, producción 1985
Intel 80486 de 1,180,235 de transistores de 1 micrómetro de superficie, producción 1985
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”
Hoy el Intel Core i7 6700k está en litografía de 14 nm
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.
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:
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)