Introducción a Ensamblador (2013)

Apunte Español
Universidad Universidad Politécnica de Cataluña (UPC)
Grado Ingeniería de Sistemas Audiovisuales - 1º curso
Asignatura FO
Año del apunte 2013
Páginas 8
Fecha de subida 30/06/2014
Descargas 3
Subido por

Vista previa del texto

Tema 5: Arquitectura de un Computador (Introducción a Ensamblador) Ciencia de los computadores: niveles de abstracción Física, química, electrónica: proveen los procesos básicos para crear los componentes básicos de un ordenador (transistores, condensadores, cableado, integración...) Arquitectura de computadores: diseña la lógica digital que hay dentro de un procesador.
La lógica digital es capaz de interpretar programas en lenguaje máquina: conjunto de instrucci ones muy sencillas, dependientes de la máquina, que el ordenador interpreta en orden. No se programa directamente en lenguaje máquina: se usa una representación simbólica llamada en samblador.
El sistema operativo es un programa que tiene unos privilegios especiales sobre el hardware.
Proporciona un conjunto de interfaces gráficas para el usuario, gestiona recursos de memoria y CPU, gestiona el uso del hardware, etc...
Los programasde uso común funcionan sobre del sistema operativo. No tienen acceso directo al hardware, sino que lo usan según los permisos que el sistema operativo le pueda dar (por ra zones de seguridad). Se suelen programar en lenguajes de alto nivel, que un compilador tradu ce a código máquina.
El usuariomaneja los programas. No tiene por qué conocer nada acerca de programación, electrónica, o sistemas operativos.
Arquitectura básica de un computador • Tres elementos básicos Procesador CPU: parte programable de un ordenador. Interpreta y ejecuta instruccion es en lenguaje máquina para automatizar tareas.
Memoria: guarda los valores de los datos que el procesador le indica (variables...) Entrada/Salida: comunica al procesador con el exterior ( Pantalla, teclado, impresora, sonido...) • Los tres elementos usan un BUS para intercambiar datos Memoria Almacena información de forma temporal – Datos y programas indistintamente – Véase como una inmensa fila de bytes (8 bits ‐ 256 valores) – Cada byte tiene asociada una "dirección" ‐‐> Un número único que la identifica Procesador • Unidad de control(CU) – Interpreta instrucciones que hay en la memoria – Busca datos en la memoria – Maneja la Unidad Aritmético‐Lógica • Unidad Aritmético‐ Lógica (ALU) – Realiza operaciones matemáticas y lógicas • Registros – Pequeñas porciones de memoria que guardan operandos y resultados de la ALU Programa • Secuencia de instrucciones en que resuelve un problema • Instrucción: tira de bits (0s y 1s) que especifica: – CO: código de la operación (suma, resta, cargar datos, guardar datos...) – OP1 y OP2: Dónde están los operandos (en memoria, en un registro...) – DEST: dónde dejar el resultado (memoria, registro...) • No hay distinciones entre los tipos de datos que puede almacenar una posición de memoria – El sistema los ve como bytes: ‐128..127, 0..255, caracteres alfanuméricos...
Ejecución de una instrucción • El procesador sigue los siguientes pasos para ejecutar una instrucción – Fetch: va a buscar a la memoria la instrucción a ejecutar (Un registro, llamado EIP (Extended Instruction Pointer) contiene la dirección de memoria donde se encuentra) – Decodificación: determina el tipo de operación, y dónde se encuentran los operandos (en un registro, en memoria...) – Lectura operandos fuente: guarda los operandos en un registro específico – Ejecución – Escritura de los resultados: en el destino Ejecución de un programa • El Sistema Operativo carga un programa en la memoria, apunta EIP hacia la primera instrucción a ejecutar, y "cede" la CPU al programa • CPU ejecuta todas las instrucciones en orden – Fetch ‐‐> Decode ‐‐> Lectura ‐‐> Ejecución ‐‐> Escritura – Ejecución Secuencial implícita: Incrementa EIP (apunta a la siguiente instrucción) y vuelve a repetir el proceso.
– Hay instrucciones que pueden romper el secuenciamiento implícito: saltos, llamadas a subrutinas (funciones...) • El programa finaliza con unas instrucciones especiales que devuelven el control al Sistema Operativo Registros • Pequeña memoria interna en el procesador • IA32 dispone de 16 registros accesibles desde el lenguaje máquina • En este curso, veremos 10 – 8 registros de propósito general, de 32 bits • %eax, %ebx, %ecx, %edx • %esi, %edi • %ebp • %esp – 2 registros especiales, de 32 bits • %eip • %eflags Registros generales • Pueden guardar operandos de instrucciones lógicas y aritméticas, también la dirección donde se encuentran los operandos (excepto %esp) ·Se puede usar la parte baja (16 bits) mediante elnombre del registro sin la "e": %ax, %bx, %cx – %ax, %bx, %cx y %dx también se pueden dividir en trozos (high y low) de 8 bits: %ah‐ %al, %bh‐%bl...
Registros especiales • %eip : Extended Instruction Pointer Contador del programa: indica la dirección de la siguiente instrucción a ejecutar.
No puede ser modificado directamente, sino mediante instrucciones de control de flujo: saltos, llamadas a subrutinas, etc...
• %eflags: Extended Flags (banderas) – Cada bit de éste proporciona información sobre el estado y control de la ejecución.
• CF (carry flag): se activa (es decir, su valor se vuelve 1) si la última operación binaria realizada ha dado acarreo (ej. 00001001+00001010 para operac iones de un byte) • ZF (zero flag): se activa si el resultado de la última operación es 0 • SF (sign flag): se activa si el resultado de la última operación es negativo • OF (overflow flag): se activa si hay desbordamiento (el resultado no cabe en N bits) Tipos de datos básicos • Tamaño de los datos en IA32 – Byte: 8 bits – Word: 16 bits – Long: 32 bits • ¿Cómo se guardan words y longs en memoria, si ésta está dividida en "trozos" de 8 bits? Formato little endian: los bytes de mayor peso se guardan en la posición más alta de memoria.
Ejemplo (en hexadecimal) • ¿Qué valor tiene la variable del tipo word en la dirección 2 de la memoria? La variable de tipo word enla dirección 2 tiene valor:0x647D Si fuera del tipo long (4 bytes)la variable tendría valor:0xFF28647D Tipos de datos que soporta IA32 • Carácteres: 1 byte (8 bits) • Se representan en binario puro según el correspondiente código ASCII 'A' ‐‐> 65 ‐‐> 0100 0001 '0' ‐‐> 48 ‐‐> 0011 0000 • Punteros: 32 bits (a cualquier tipo de dato) • Números enteros: 8/16/32 bits – Representación en complemento a 2 – Rango: [‐2n‐1 , 2n‐1 ‐1] (n ‐número de bits) Conversión CA2↔ decimal •El complemento a 2 se utiliza para poder representar números con signo solo a partir de núm eros binarios • Ejemplo: CA2 del número ‐46 para números de 8 bits 1. Calcular +46 en binario: 00101110 2. Calcular el complementario: 11010001 (intercambiamos 0s por 1s y vice‐versa) 3. Sumar 1 al resultado anterior: 11010010 • Ejemplo 2: Pasar a entero el número de 8 bits en CA2: 10010011 1. Convertir a entero positivo: 147 2. Si el bit de más a la izquierda es 1, restar 2n (si es de 8 bits, n=8): 147 ‐ 28 = 147 ‐ 256 = ‐109 Modos de direccionamiento • El "direccionamiento" especifica dónde se encuentran los operandos de las instrucciones • Cada operando puede tener su propio modo de direccionamiento • En IA32, un operando puede estar localizado – En el mismo código de la instrucción (inmediato) – En un registro – En la memoria: son los accesos más lentos.
Direccionamiento inmediato • El operando está en la misma instrucción – Se especifica usando un $ delante del valor – Puede ser de 8, 16 o 32 bits • Ejemplos: mediante nuestra primera instrucción de ensamblador movb, movw, movl ‐‐> Mueve entre la memoria y los registros un dato de 8, 16 o 32 bits movl $3,%eax Mueve un 3 al registro %eax movb $'A',%bl Mueve una 'A' al registro %bl movl $0xF,%eax Mueve un 15 (hexadecimal) a %eax movs $0b101,%ax Mueve un 5 (en binario) a %ax Direccionamiento en registro • El operando está guardado en un registro especificado en la instrucción – 32 bits (%eax, %ebx, %ecx...) – 16 bits (%ax, %bx, %cx...) – 8 bits (%ah, %al, %bh, %bl...) • Ejemplo movl %ebx, %eax ‐‐> copia el contenido del registro %ebx en el registro %eax Operando en memoria • El operando está guardado en la dirección de memoria especificada según la sintaxis: D(Rb,Ri,Fe)‐‐> Operando en dirección D+Rb+Ri*Fe • Donde: – D: desplazamiento. Constante o dirección base de un vector (8 o 32 bits) – Rb: registro base ‐‐> cualquier registro – Ri: registro índice ‐‐> Cualquier registro menos %esp – Fe: factor de escala ‐‐> Puede valor 1, 2, 4 u 8 • No es necesario especificar todos los valores.
– Por defecto, D=0, Rb=0, Ri=0, Fe=1 Ejemplos • movb 4, %eax Copia el contenido de la dirección 4 en %eax • movl var, %eax Copia el contenido de la variable 'var' en %eax • movl 4(%ebx), %eax Copia el contenido de la dirección 4+%ebx en %eax • movl 5(%ebp,%ebx), %eax Copia el contenido de la dirección 5+%ebp+%ebx en %eax • movl 7(%ebp,%ebx,2), %eax Copia el contenido en 7+%ebp+%ebx*2 en %eax Combinando direccionamientos •No todas las combinaciones de modos de direccionamiento son válidas – Inmediato no puede ser un operador destino – Solo uno de los operadores puede ser memoria Instrucciones • IA32 dispone de más de 100 instrucciones diferentes. Nosotros solo veremos 20: – Transferencia de datos: MOV, MOVS, PUSH, POP – Aritméticas enteras: ADD, INC, DEC, SUB, NEG, CMP, IMUL – Control de flujo: CALL, RET, JMP, Jxx • Sintaxis general: nombre[b, w, ó l] opfuente opdestino Transferencia de datos mov[b|w|l] op1, op2 – copia byte, word o long desde op1 a op2 movl $4, %ebx movs[bw|bl|wl] op1, op2 – Copia de op1 a op2, extendiendo su signo de byte a word (bw) o long (bl), y de word a long (wl) – Se usa para conservar el signo en los complementos a 2 de diferente tamaño movsbl %al, %ebx Valores vs Punteros • Lenguaje C var retorna/modifica el valor de la variable 'var' &var retorna la dirección de memoria (puntero) de la variable 'var' *p retorna/modifica lo que hay en la dirección apuntada por el puntero 'p' • Ensamblador var retorna/modifica el valor de la variable 'var' $var retorna la dirección de memoria de 'var' %ebx retorna/modifica el valor de un registro (%ebx) (%ebx) retorna/modifica el dato que hay en la dirección cuya dirección es el valor de %ebx – Ejemplo movl $10, %ebx #Guarda el valor 0 en la dirección 10 de la memoria movw $0, (%ebx) Instrucciones aritméticas Estructura de un Programa en Ensamblador # Comentarios precedidos por un ‘#’ # Definición de constantes: nombre_const = valor N = 20 # decimal M = 0x4A # hexadecimal B = 0b010011 # binario C = ‘J’ # caracter # Sección de datos: declaración variables sin inicializar .bss # variables que serán visibles desde ficheros externos .global i #variables locales: .comm nom_var, tamaño_bytes, alineación .comm i, 4, 4 # long. Equivale a C: int i; .comm s, 2, 2 # word. Equivale a C: short s; .comm c, 1, 1 # byte. Equivale a C: char c; # Sección de codigo .text .global main #Hace visible el main a fitxeros externos main: # Código # Código...
# Finalizar el programa en linux movl $0, %ebx # %ebx: valor de salida al S.O. En este caso: return 0; movl $1, %eax # %eax: función sys_exit del S.O.
int $0x80 # Llama al S.O. i ejecuta llamada de sistema especificada Flujo del programa • Las instrucciones se ejecutan en orden, según su posición en memoria 1. Se ejecuta la instrucción que hay en la dirección indicada por %eip 2. Se incrementa %eip hasta apuntar a la siguiente instrucción • El nº de bytes que ocupa cada instrucción puede variar.
3. Se vuelve al paso 1 • podemos "romper" esta secuenciación mediante saltos con la instrucción de salto Jmp <etiqueta> – %eip <‐‐ dirección de memoria donde esté la etiqueta Ejemplo de jmp <etiqueta> movl $0, %eax movw $1, %bx repite: incl %eax imulw $2, %bx jmp repite Etiquetas en el código • Delante de alguna instrucción de nuestro código, podemos poner una etiqueta (con el nombre que nosotros elijamos) • Más adelante, podremos referirnos a esa parte del código mediante su etiqueta – Por ejemplo, en un salto salto1: movl $0,%eax jmp salto2 movl $1, %eax salto2: incl %eax jmp salto1 Activación de "flags" • Las instrucciones aritméticas pueden activar "flags" del registro %eflags • Ejemplo movl $10, %eax cmpl $10, %eax #Activará el ZF (zefo flag) ¿Para qué sirven los "flags"? • Los flags (Carry, Zero, Sign,Overflow, etc...)se pueden utilizar para controlar el flujo del programa.
• En C teníamos instrucciones de control de flujo, tales como if, for, while...
• En Ensamblador, solo tenemos saltos condicionales ‐ Si el flag que queremos comprobar está activo, el programa "saltará" (es decir, se actualizará su registro %eip) a la instrucción que le indiquemos (mediante una etiqueta que pondremos en el código) Instrucciones de salto condicional • Se usan después de operaciones que alteran los flags, por ejemplo cmp op1, op2 • Significado de las letras: j : jump (salta) n: not (no) e : equal (igual) g : greather than (mayor que) l : less than (menor que) ...