Repaso:
Arquitectura 8086
Instituto de Computación
Facultad de Ingeniería
Universidad de la República
2020
Arquitectura de Computadoras
Arquitectura 8086
Características:
– Procesador de 16 bits.
• 8088 con bus de memoria de 8 bits.
– Memoria segmentada.
– 12 registros visibles, con personalidad.
– Little Endian.
– Diseño CISC, incluyendo instrucciones de multiplicación y
división enteras.
– Stack por Hardware.
Arquitectura 8086
Características:
– Formato de instrucción de dos operandos.
• Uno es origen y destino.
– 12 Registros visibles: CS, DS, SS, ES, AX, BX, CX, DX, SI,
DI, SP y BP.
– Registros parcialmente visibles: IP, FLAGS.
– Los registros son personalizados, es decir no se pueden
intercambiar libremente en su utilización.
Arquitectura 8086
Registros:
– CS, DS, SS, ES: Registros de segmento. Code, Data, Stack
y Extra Segment.
– AX, BX, CX, DX: Registros de uso general. Acumulator,
Base, Counter y Data.
– Variantes de 8 bits, por ejemplo AX -> AH, AL.
– SP y BP: Registros Stack y Base Pointer. Implementación
de stack.
– SI y DI: Registros Source y Destination Index.
Arquitectura 8086
Registro FLAGS:
Arquitectura 8086
Memoria Segmentada:
– Con direcciones de 16 bits, se pueden direccionar
únicamente 64 KB.
– Para direccionar 1 MB recurren a un direccionamiento
basado en segmentos de memoria de 64 KB.
– Se disponen 4 registros de segmento (CS, DS, SS y ES)
que se utilizan exclusivamente para el acceso a memoria.
– Dirección Final [20] = Registro de segmento * 24 +
Desplazamiento (Dirección Indicada)
Arquitectura 8086
Memoria Segmentada:
Arquitectura 8086
Modos de Direccionamiento:
– Inmediato
– Directo (a Registro / a Memoria)
– Indirecto (por Registro)
– Indizado (combinación de Indirecto y Directo a Memoria)
– Hay restricciones para los modos indirecto e indizado
{BX | BP} [+ {SI | DI}] [+ desplazamiento]
{SI | DI} [+ desplazamiento] | desplazamiento
Arquitectura 8086
Ejemplos de Modos de Direccionamiento:
– MOV AX, 1234
– ADD BX, [1234]
– ADD CX, [0x1234]
– CMP DL, [BX]
– SUB DI, [BP]
– SUB DI, [BP + DI]
– SUB DI, [BP + DI + 0x1234]
Arquitectura 8086
Segmentos por defecto:
– MOV ES:[BX], AX
– MOV DX, SS:[DI]
Arquitectura 8086
Soporte de Stack por hardware:
– Registros SS, SP y BP
– Instrucciones PUSH y POP
– Estructura de 16 bits (no maneja bytes)
Arquitectura 8086
Soporte de Stack por hardware:
Arquitectura 8086
Set de Instrucciones:
– Aritméticas (ADD, SUB, INC, MUL, DIV)
– Lógicas (AND, OR, XOR)
– Control (JMP, Jxx)
– Transferencia de datos (MOV, IN, OUT, PUSH, POP)
– Control de funcionamiento (STI, CLI)
– Largo variable
– Dos operandos, de los cuales solo uno puede ser memoria
Arquitectura 8086
Lenguaje Ensamblador:
– Es una forma sencilla de escribir programas en lenguaje de
máquina (usando las instrucciones de la CPU)
– Consta de los siguientes elementos:
• Comentarios
• Constantes
• Instrucciones
• Etiquetas
• Directivas
Arquitectura 8086
Lenguaje Ensamblador:
– Comentario es cualquier texto luego de ; y hasta el final de
la línea.
– Constantes
• Numéricas
– 001101b (Binario)
– 664o (Octal)
– FE53h o 0xFE53 (Hexadecimal)
– 120 (Decimal positivo)
– -120 (Decimal negativo)
Arquitectura 8086
Lenguaje Ensamblador:
– Constantes
• Texto
– ‘c’ (Carácter)
– “Hola mundo!” (String)
– Instrucciones
• ADD op1, op2
• INC op1
• PUSH op1
Arquitectura 8086
Lenguaje Ensamblador:
– Etiquetas
• Formadas por letras y números
• Referencia la posición de la instrucción o estructura de memoria
que esté definida a continuación
Arquitectura 8086
Lenguaje Ensamblador:
– Directivas
• Utilizadas para indicar datos constantes y datos iniciales
• EQU
• DB, DW, DDW (con el operador DUP)
• PROC y ENDP
Arquitectura 8086
Lenguaje Ensamblador:
– Programando el control del flujo del programa
• Se utilizan los saltos, tanto incondicionales como condicionados a
valores de las banderas de condición (C, O, S, Z)
• Existe un set de saltos condicionales “con signo” o “sin signo”
• El ensamblador no es un lenguaje estructurado (en realidad no es
un lenguaje estrictamente hablando)
• Las sentencias de control de flujo de los lenguajes de alto nivel
deben traducirse utilizando saltos
• La instrucción CMP es muy útil en estos casos
Arquitectura 8086
Lenguaje Ensamblador:
– If-then
Arquitectura 8086
Lenguaje Ensamblador:
– If-then-else
Arquitectura 8086
Lenguaje Ensamblador:
– While
Arquitectura 8086
Lenguaje Ensamblador:
– Anidadas
Arquitectura 8086
Lenguaje Ensamblador:
– Estructuras de memoria
• Por definición, una variable es un espacio en memoria con un
nombre asignado.
• En ensamblador esto se mapea a posiciones de memoria
identificadas con una etiqueta.
• El ensamblador usa un modelo de memoria estático.
• No existen funciones como “new” o “delete”
• Las variables también pueden almacenarse en registros
Arquitectura 8086
Lenguaje Ensamblador:
Arquitectura 8086
Lenguaje Ensamblador:
– Estructuras de memoria
• Arreglos
Arquitectura 8086
Lenguaje Ensamblador:
– Estructuras de memoria
• Structs
Arquitectura 8086
Lenguaje Ensamblador:
– Estructuras de memoria
• Structs
Arquitectura 8086
Lenguaje Ensamblador:
– Invocación de funciones
• Pasaje de parámetros por registros o por stack
• Mismas alternativas para el resultado
• El llamado utiliza el stack para guardar el punto al cual retornar al
finalizar la función
• Instrucciones CALL y RET
• Atributos NEAR y FAR
• El stack se utiliza para salvar el contexto (valor de registros)
Arquitectura 8086
Lenguaje Ensamblador:
– Preservación de Contexto (salvar registros)
Arquitectura 8086
Lenguaje Ensamblador:
– Pasaje de Argumentos y Resultados por stack
• Para acceder a los argumentos se puede hacer POP en el código
de la función, recordando que el primer POP trae del stack la
dirección de retorno.
• Una alternativa es utilizar BP para direccionar dentro del stack:
PUSH BP ; salvo valor actual de BP
MOV BP, SP ; BP apunta al tope del stack
; [BP] -> valor salvado de BP
; [BP + 2] -> dirección de retorno
; [BP + 4] -> argumento
Arquitectura 8086
Lenguaje Ensamblador:
– Ajuste de stack para el (los) resultado(s)
• Cuando la cantidad de palabras de resultado no coincide con la de
los argumentos, no alcanza con escribir los resultados en los
lugares ocupados por los argumentos y es necesario ajustar el
stack.
• Para el caso en que haya menos resultados es necesario reducir el
stack y para el caso contrario hay que agrandarlo.
• En ambas situaciones es necesario mover la dirección de retorno,
para que ocupe el lugar correcto.
Arquitectura 8086
Lenguaje Ensamblador:
– Ejemplo de 2 argumentos y 1 resultado:
PUSH BP
MOV BP, SP
MOV BX, [BP + 4] ; argumento 2
MOV AX, [BP + 6] ; argumento 1
--------- ; código de procesamiento
MOV AX, [BP + 2] ; AX <- dirección de retorno
MOV [BP + 4], AX ; acomodo dirección de retorno
MOV [BP + 6], resultado
POP BP
ADD SP, 2 ; “achico” el stack
RET
Arquitectura 8086
Lenguaje Ensamblador:
– Ejemplo de 1 argumento y 2 resultados:
SUB SP, 2 ; “agrando” el stack
PUSH BP
MOV BP, SP
MOV AX, [BP + 4] ; AX <- dirección de retorno
MOV [BP + 2], AX ; acomodo dirección de retorno
MOV AX, [BP + 6] ; argumento 1
--------- ; código de procesamiento
MOV [BP + 6], resultado2
MOV [BP + 4], resultado1
POP BP
RET
Arquitectura 8086
Lenguaje Ensamblador:
– Rutinas Recursivas 1
Arquitectura 8086
Lenguaje Ensamblador:
– Rutinas Recursivas 1
• En este caso solo se guarda la dirección de retorno en el stack
Paso base: consumo(0) = 2
Paso recursivo: consumo(n) = 2 + consumo(n - 1)
Total: consumo(n) = 2 * n + 2
Arquitectura 8086
Lenguaje Ensamblador:
– Rutinas Recursivas 2
Arquitectura 8086
Lenguaje Ensamblador:
– Rutinas Recursivas 2
• En este caso solo se guarda la dirección de retorno en el stack
Paso base: consumo(0) = 2
Paso recursivo: consumo(n) = 4 + consumo(n - 1)
Total: consumo(n) = 4 * n + 2
Arquitectura 8086
Lenguaje Ensamblador:
– Rutinas Recursivas 3
Arquitectura 8086
Lenguaje Ensamblador:
– Rutinas Recursivas 3
• En este caso solo se guarda la dirección de retorno en el stack
Paso base: consumo(0) = 4
Paso recursivo: consumo(n) = 6 + consumo(n - 1)
Total: consumo(n) = 6 * n + 4
Arquitectura 8086
Lenguaje Ensamblador:
– Rutinas Recursivas 4
Arquitectura 8086
Lenguaje Ensamblador:
– Rutinas Recursivas 4
• En este caso solo se guarda la dirección de retorno en el stack
Paso base: consumo(0) = 10
Paso recursivo: consumo(n) = 10 + consumo(n - 1)
Total: consumo(n) = 10 * n + 10