LABORATORIO DE PROGRAMACIÓN EN LENGUAJE ENSAMBLADOR x86-16bits

Documentos relacionados
ENSAMBLADOR DE ARCHIVO TASM MASM NASM GAS. Características de un Ensamblador de Archivo

Estructura de Computadores: Tema 1. Introducción. Índice. Arquitectura del i8086

Tema 1. Fundamentos del lenguaje ensamblador

Sobre cómo dividir un programa ensamblador x86 (modo Real) en módulos compilables por separado.

ARQUITECTURA INTERNA DEL µp8086

Conceptos de Arquitectura de Computadoras Curso 2015

Tema 5: La pila, las macros y los procedimientos

Examen de teoría (5 puntos)

Tema 4. La pila, los procedimientos y las macros

8.4. El software en los μprocesadores

UNIVERSIDAD TECNOLÓGICA NACIONAL FACULTAD REGIONAL SAN NICOLÁS INGENIERIA EN ELECTRÓNICA

SISTEMAS BASADOS EN MICROPROCESADORES

Todos los comandos de DEBUG se invocan usando una sola letra y son los siguientes:

(4) Unidad 4. Recursos de Programación SISTEMAS BASADOS EN MICROPROCESADORES. Grado en Ingeniería Informática EPS - UAM

SISTEMAS BASADOS EN MICROPROCESADORES

Arquitectura Interna del 8088

DIRECTIVAS DEL ASM86

Nombre del estudiante: Gustavo Antonio González Morales. Nombre del trabajo: Tarea 2. Investigación sobre Paginación y Segmentacion.

Examen de teoría (5 puntos)

Ingeniería en Sistemas. Sistemas Operativos. Trabajo Práctico: Repaso de Interrupciones, direccionamiento de memoria y registros del procesador.

Intel Departamento de Arquitectura 1. Facultad de Ingeniería Universidad de la República. Arquitectura de Computadoras, 2016

Un. VIII. Generación de Código Objeto

5 - Lenguaje Ensamblador

Qué es un programa informático?

(2) Unidad 2. Modelo de Programación del 80x86 de Intel SISTEMAS BASADOS EN MICROPROCESADORES. Grado en Ingeniería Informática EPS - UAM

Diseño de compiladores. Organización de memoria. Organización de memoria. Organización de memoria. Zona de código 04/05/2014 ORGANIZACIÓN DE MEMORIA

Tema 4. Lenguaje máquina y lenguaje ensamblador

Cruz García Karen Ilzette González Mendoza María del Rosario Hernández Castañeda Alan Eliseo Sánchez Quiroz Sheila Mariana Varela García Tania

Arquitectura de Computadores II 8086 Parte II

Tema 6 Organización y gestión de la memoria

Es un lenguaje estructurado, tiene una abundante cantidad de operadores y tipos de datos.

INT 21H Función 02H Salida de Carácter LLAMADA: AH = 02H DL = Código ASCII a enviar al dispositivo de salida. DEVUELVE: NADA.

Ensamblador. Introducción. Dpto. Física y Arquitectura de Computadores. Universidad Miguel Hernandez

62/8&,21(6$/(;$0(1'( /$%25$725,2'((6758&785$6'(/26&20387$'25(6 &8562)(%5(52

Todo programa en 'C' consta de una o más funciones, una de las cuales se llama main.

Construyendo Programas más Complejos

Arquitectura (Procesador familia 80 x 86 )

Tema 8 Gestión de la memoria en tiempo de ejecución.

Ejercicios del Tema 3. Fundamentos de la programación en ensamblador

Sistema electrónico digital (binario) que procesa datos siguiendo unas instrucciones almacenadas en su memoria

05 Funciones en lenguaje C. Diego Andrés Alvarez Marín Profesor Asociado Universidad Nacional de Colombia Sede Manizales

Diferentes Perspectivas de un Ordenador

LABORATORIO DE PROGRAMACIÓN EN LENGUAJE ENSAMBLADOR x86-16bits

PRACTICA #1. Aprender a programar una interrupción software empleando C y/o Ensamblador.

TEMA 7: Ficheros. TEMA 7: Ficheros Concepto de fichero

RESEÑA DE LENGUAJE C

Universidad Nacional de Ingeniería Arquitectura de Maquinas I. Unidad I: Arquitectura y Programación de un Microprocesador (8086)

Programas Residentes En Lenguaje Ensamblador

Sistema Operativo. Repaso de Estructura de Computadores. Componentes Hardware. Elementos Básicos

ESTRUCTURA DE DATOS. Memoria estática Memoria dinámica Tipo puntero Declaración de punteros Gestión de memoria dinámica Resumen ejemplo

Tema 2. Administración de procesos

Memoria Estática Punteros, Vectores y Matrices

Punteros. 1.- Paso de parámetros por referencia. Ya hablamos de ésto en funciones. 2.- Declaración de arreglos dinámicos.

MÓDULO III PROGRAMACIÓN DEL MICROPROCESADOR

Examen de teoría (5 puntos)

Curso de Programación en C. Licenciatura, FCQeI. APUNTADORES.

Tema 5. Formato de instrucciones. Directivas, instrucciones de cadena y programas de varios módulos

Universidad Nacional de Ingeniería Arquitectura de Maquinas I. Unidad II: Arquitectura y Programacion de un Microprocesador (80X86)

Arquitectura del CPU. Organización del Computador 1 Verano 2016

Instrucciones de Control de Flujo y Usos de la Pila

Objetivo. Introducción. Tema: GENERACION DE CODIGO. Compiladores, Guía 11 1

Tema 3 SUBRUTINAS. Estructura de Computadores OCW_2015 Nekane Azkona Estefanía

EJEMPLOS EN ENSAMBLADOR

INTRODUCCIóN A LA PROGRAMACIóN APUNTES DE JAVA APUNTES DE JAVA

Introducción al EMU8086

Alternativas de programación

Acceso Directo a Memoria

Arquitectura de Computadoras

Tema: Lenguaje ensamblador embebido

USO DE MEMORIA Y PERIFÉRICOS CON EMU8086. Kervin Sánchez Herrera.

TEMA 3. CONCEPTOS FUNDAMENTALES DEL NIVEL DEL SISTEMA OPERATIVO. Definición y objetivos de un S.O

Asignatura: ASSEMBLER INF-153 LABORATORIO 1

APUNTES DE LENGUAJE ENSAMBLADOR. Lenguaje ensamblador

RELACIÓN DE PROBLEMAS DE LÓGICA PROGRAMADA (TEMA 4)

Pregunta correcta= 0,3 Pregunta no contestada= 0 Pregunta incorrecta (tipo test)= -0,15

ESTRUCTURA Y ORGANIZACIÓN DE COMPUTADORES

Facultad de Ingeniería Industrial y de Sistemas v1.1 MA781U CONCEPTOS INICIALES CASOS DE USO

APUNTES DE LENGUAJE ENSAMBLADOR APÉNDICE B DEBUG

Estructura de los sistemas de cómputo

Práctica de Arquitectura de Computadores Sistemas de Entrada/Salida: Entrada/Salida Programada Curso 2016/2017

Ejercicios Práctica 4 Primer Cuatrimestre de de abril de 2008

EL EMU8086 Y EL MICROPROCESADOR 8086.

Ejercicios del Tema 3. Fundamentos de la programación en ensamblador

Tema 5.1: Presentación de datos en pantalla

Clases y Objetos en C++

Manual de referencia de C++ Parte IV Variables Punteros. Preparado por Prof. Luis A. Ortiz Ortiz

9. Lenguaje ensamblador

INSTITUTO TECNOLÓGICO DE CHIHUAHUA II ARQUITECTURA DE COMPUTADORAS MAESTRO: ERNESTO LEAL ALUMNOS: LUIS CARLOS BARRERA ORTIZ STHEPANIE FLORES GUILLEN

SISTEMAS BASADOS EN MICROPROCESADORES

LABORATORIO #1 INTRODUCCIÓN AL LENGUAJE DE PROGRAMACIÓN C++

Funcionamiento de las computadoras

Arquitectura de Computadores II Clase #3

Los números naturales y enteros en el 80X86 y en LAN

Desde los programas más simples escritos en un lenguaje de programación suelen realizar tres tareas en forma secuencial.

Punteros y aritmética de punteros. se almacena el operando

El operador contenido ( ) permite acceder al contenido de

CAPÍTULO IV: GESTIÓN DE ARCHIVOS. 1. Introducción a la Gestión de Archivos 2. Organización y acceso a los ficheros 3. Directorios

Examen de teoría (4 puntos)

TEMA 3: El proceso de compilación, del código fuente al código máquina

Relación de Problemas I

Transcripción:

LABORATORIO DE PROGRAMACIÓN EN LENGUAJE ENSAMBLADOR x86-16bits De la creación del programa al proceso en ejecución Objetivo El objetivo de esta práctica es conocer y diferenciar los conceptos de programa y proceso. Aprenderemos a desarrollar un programa en ensamblador y qué secciones lo componen. Programa Un programa no es un conjunto de instrucciones solamente. Un programa es un espacio de memoria organizado en secciones bien diferenciadas entre las que no pueden faltar la sección de código, la sección de datos y la sección de pila. El programa compilado se guarda en un fichero que tiene dos partes: el binario y una cabecera con información para el sistema operativo. Las secciones de un programa Un programa requiere de varias secciones de memoria. Evidentemente, una de ellas es la que contiene las instrucciones a ejecutar. Sin embargo, también necesitamos una sección que almacene los datos y una sección para la pila. Las secciones más habituales son: Sección de código La sección de código, sección de texto o simplemente texto, es la que contiene la secuencia de instrucciones a ejecutar. Normalmente es una sección de sólo lectura aunque algunos programas se automodifican o reservan pequeños espacios para datos en esta sección. Esta sección requiere de un puntero especial (puntero de instrucción o contador de programa) que señala la posición de la siguiente instrucción a ejecutar. Sección de datos La sección de datos contiene las variables globales (aquellas accesibles desde todo el programa) y las estáticas (su tiempo de vida abarca todo el tiempo de ejecución del programa) que contienen datos iniciales (inicializadas por el programador). Es una sección de lectura y escritura aunque si una variable se declara como constante se puede alojar en una zona de solo lectura. Sección de bss La sección bss (Block Started by Symbol) contiene variables estáticas no inicializadas, es decir, cuyo valor inicial es 0. Normalmente esta sección no se almacena en el fichero imagen del ejecutable sino que es el cargador del sistema operativo quien realiza la reserva de espacio en memoria principal y el relleno con 0. Sección de heap La sección heap se usa para hacer reservas dinámicas de memoria en tiempo de ejecución. La reserva de un bloque de memoria puede liberarse o incrementarse en tiempo de ejecución. Es una sección que puede crecer y, por tanto, no debe estar limitada por otras secciones. No aparece en el fichero imagen del ejecutable. Sección de pila La sección pila implementa un área de memoria con un tipo de acceso LIFO (Last Input First Output) utilizada en el manejo de procedimientos (subrutinas) que sirve para almacenar temporalmente los argumentos y variables locales. Esta sección requiere de un puntero especial (puntero de pila) que indica la posición de memoria de la cima de la pila. Adicionalmente, se suele utilizar otro puntero especial (puntero de marco de pila) que sirve para referenciar los argumentos y variables locales propios del procedimiento (subrutina) en curso. Es habitual que la sección de pila y la sección de heap crezcan la una contra la otra de manera que, si el programa no ha sido bien diseñado, una sección puede llegar a sobrescribir los datos de la otra.

DE LA CREACIÓN DEL PROGRAMA AL PROCESO EN EJECUCIÓN La cabecera de un programa La cabecera almacena información para el cargador del sistema operativo. Algunos de los datos que proporciona esta cabecera son: tamaño de la cabecera tamaño del fichero binario tabla de direcciones de memoria absolutas máxima y mínima cantidades de memoria requeridas valores iniciales de los punteros de instrucción y de pila Qué es la tabla de direcciones de memoria absolutas? La imagen de un ejecutable se implementa en forma de fichero reubicable, es decir, que ha de funcionar igual sea cual sea el rango de posiciones de memoria principal que se le asignen. Todas aquellas referencias a posiciones de memoria relativas a la posición en curso no tienen problema de ambigüedad. En cambio, todas aquellas referencias absolutas son desconocidas a priori. Por ejemplo, el comienzo de la sección de datos puede ubicarse en cualquier posición de memoria principal y no se conocerá con precisión hasta que el sistema operativo no asigne un mapa de memoria al proceso. Para solucionar este problema, lo que hacemos es referenciar las posiciones absolutas respecto al comienzo de la imagen del ejecutable y confeccionar una tabla con todas las posiciones de memoria absolutas que han de corregirse. Dicha tabla se guarda en la cabecera de la imagen del ejecutable. Una vez que el cargador conoce el rango del mapa de memoria asignado al proceso, modifica todos los valores de las direcciones absolutas de memoria sumando la posición de memoria inicial del proceso con la posición relativa que aparece en la imagen del ejecutable. Veamos un ejemplo. Supongamos que la sección de datos comienza en la posición 1.024B respecto al comienzo de la imagen del ejecutable y supongamos que dicha imagen se va a cargar en la posición de memoria principal 3.456B. En consecuencia, la sección de datos comienza en la posición 3.456B + 1.024B = 4.480B Lo mismo sucede con los punteros de instrucción y de pila. El cargador del sistema operativo calculará los valores efectivos de ambos punteros una vez se conoce el mapa de memoria asignado. Formatos de cabeceras Existen diferentes formatos para las cabeceras de las imágenes de los ejecutables. A continuación se presentan los más importantes: a.out (assembler output): formato original utilizado en entornos UNIX; obsoleto, evolucionó a COFF COFF (Common Object File Format): formato para ejecutables, código objeto y librerías compartidas en entorno UNIX; reemplazado UNIX por ELF sirvió de base para formatos del entorno Windows ELF (Executable & Linkable Format): formato para ejecutables, código objeto, librerías compartidas y volcado de memoria en entorno UNIX; admite una gran variedad de secciones en los ejecutables MZ (Mark Zbikowski): utilizado en el entorno DOS; evolucionó dando lugar a varias extensiones PE (Portable Executable): formato para ejecutables, código objeto, librerías compartidas (DLL), archivos de fuentes y otros usos en entorno Windows; es una evolución de COFF Proceso Un proceso es un programa en ejecución, es decir, una secuencia de instrucciones con una serie de recursos asociados y un estado. Los recursos asociados son el contador de programa, los datos de memoria, la pila y su puntero, los registros y operadores de la ruta de datos y los recursos de E/S (puertos, descriptores de ficheros, etc.). El estado guarda información del punto de ejecución, situación de procesamiento, propietario, privilegios, comunicaciones, mecanismo de devolución del control al sistema operativo, etc. El estado se almacena de diferentes maneras dependiendo de la arquitectura. Creación de un proceso El sistema operativo toma la imagen de un ejecutable, actualiza sus direcciones absolutas e inicializa los datos que lo requieran, copia la imagen actualizada en memoria principal, asigna recursos y transfiere el control a la primera instrucción. 2

LABORATORIO DE PROGRAMACIÓN EN ENSAMBLADOR X86-16BITS Finalización de un proceso Un proceso puede terminar de manera normal devolviendo el control al sistema, puede ser abortado por otro proceso o puede finalizar por error. Estados de un proceso Un proceso puede estar en ejecución, bloqueado (a la espera de algún evento externo) o listo (esperando a disponer de los recursos de ejecución del procesador). Desarrollo de programas en ensamblador x86-16bits En este entorno existen 2 tipos de imágenes de ejecutables. Los ficheros.exe y los ficheros.com. Los ficheros.exe se ajustan al formato MZ mientras que los.com no tienen cabecera, sólo almacenan el binario de código y datos. Los.COM perviven por compatibilidad pero tienen el interés de ser muy pequeños y quizá útiles en el desarrollo de sistemas empotrados. A continuación presentamos una tabla con una comparativa de características de ambos tipos:.exe cabecera de formato MZ tamaño no limitado a 64KB la imagen representa todos los segmentos declarados (incluyendo la pila) los segmentos pueden estar solapados parcial o totalmente o no estar solapados en absoluto.com sin cabecera tamaño limitado a 64KB 256B la imagen sólo representa el binario de código y datos; la pila no aparece (la asigna el sistema al arrancar) todos los segmentos están totalmente solapados comenzando en la misma posición de memoria Hoy en día, para crear un fichero.com debemos partir de un fichero.exe que cumpla una serie de condiciones. Con él como entrada, podemos usar la utilidad EXE2BIN o bien utilizar el depurador DEBUG para convertir el.exe en.com. Las condiciones que debe cumplir un.exe para que sea convertible a.com son las siguientes: el tamaño total debe ser menor de 65.280B y estar organizado en un único segmento la primera instrucción ejecutable debe estar en el desplazamiento 100h (esto se consigue usando la directiva ORG 100h que desplaza el puntero de instrucción el valor especificado) El desarrollo de un programa.exe parte de un fichero de código fuente en ensamblador (programa.asm) que se ensambla con masm5.1 dando lugar a un fichero de módulo objeto (programa.obj) que finalmente se linka con link generando el fichero ejecutable (programa.exe). programa.asm programa.obj programa.exe MASM programa.asm LINK programa.obj Diseño de secciones en ensamblador x86-16bits El desarrollo de programas con lenguajes de alto nivel confía al compilador el diseño de las secciones de un programa. Por el contrario, el desarrollo de programas en ensamblador x86-16bits permite controlar totalmente este diseño si se considera necesario (definición completa de segmentos) o bien permitir que el programa ensamblador realice ese diseño de una manera transparente al programador (definición simplificada de segmentos). Definición completa de segmentos A continuación se muestra el esqueleto de varios programas que siguen la definición completa de segmentos. Se comenta cada uno de ellos al margen. 3

DE LA CREACIÓN DEL PROGRAMA AL PROCESO EN EJECUCIÓN 1 Definición completa de segmentos Segmentos separados Salida mediante INT 20h ASSUME CS:codigo, DS:datos, SS:pila ; segmento de datos datos SEGMENT datos ENDS // DECLARACIÓN DEL TAMAÑO DE LA PILA // DB 256 DUP(?) ; pila de 256 bytes main PROC FAR ; dirección de retorno a la pila ; apunta al PSP (DS:0) PUSH DS XOR AX, AX PUSH AX ; inicializamos el segmento de datos MOV AX, DATOS MOV DS, AX ; devolvemos el control al DOS RET main ENDP ; indicamos al programa ensamblador dónde ; comienza el código del programa ; sirve para dar valor a CS:IP END main La primera versión que presentamos es la más antigua por el método de salida (INT 20h). Se declara el comienzo de cada segmento mediante una etiqueta y la directiva SEGMENT. Se declara el final con la misma etiqueta seguida de ENDS. El orden en el que se declaren será el orden en el que aparezcan en la imagen del ejecutable. Siempre tiene que haber un segmento STACK (directiva SEGMENT seguida del operando STACK). En caso contrario el linker emitirá un error. La directiva ASSUME indica qué registro de segmento sirve para direccionar cada segmento. El de código necesariamente debe usar CS. El código fuente finaliza con la directiva END seguida de la etiqueta que marca el comienzo del código. Esto sirve para que CS:IP apunte a la dirección de arranque. En este caso, el código se ha organizado como un procedimiento (main). Cuando se crea el proceso, el sistema operativo salta a la primera instrucción del procedimiento. Lo primero que hace dicho procedimiento es salvar en la pila la dirección de retorno (DS:0). Dicha posición apunta al PSP (área de memoria que guarda el estado del proceso). El PSP comienza con la instrucción INT 20h que devuelve el control al sistema. La segunda tarea que realiza el procedimiento es cargar el registro DS con el valor de comienzo de la sección de DATOS. 2 Definición completa de segmentos Segmentos separados Salida mediante INT 21h servicio 4Ch ASSUME CS:codigo, DS:datos, SS:pila // RESTO DE SEGMENTOS // inicio: MOV AX, DATOS ;inicializamos el MOV DS, AX ;segmento de datos En este caso solamente cambia, respecto al anterior, el modo en el que se devuelve el control al sistema operativo. Ahora se utiliza el servicio 4Ch de la INT 21h prescindiendo del PSP. El segmento de código no adopta forma de procedimiento sino de secuencia de instrucciones. Al igual que en el caso anterior, el código debe comenzar asignando valor al segmento de datos ya que si no se hace, no podrán reverenciarse los datos. 4

LABORATORIO DE PROGRAMACIÓN EN ENSAMBLADOR X86-16BITS 3 Definición completa de segmentos Segmentos solapados Salida mediante INT 21h servicio 4Ch COMUN GROUP codigo, datos, pila ASSUME CS:COMUN, DS:COMUN, SS:COMUN ; segmento de datos datos SEGMENT datos ENDS DB 256 DUP(?) inicio: MOV AX, COMUN ;inicializamos el MOV DS, AX ;segmento de datos En este caso, los segmentos se solapan totalmente con la intención de que la imagen del ejecutable ocupe menos espacio. La directiva GROUP agrupa varios segmentos lógicos en uno físico bajo un único nombre. La carga del puntero del segmento de datos se realiza bajo el nombre común del grupo (COMUN en este ejemplo). Las referencias a datos se harán anteponiendo a la etiqueta del dato el nombre del grupo. En este caso, COMUN:nombre_dato. 4 Definición completa de segmentos Segmentos solapados Sin segmento de datos (datos en segmento de código) Salida mediante INT 21h servicio 4Ch COMUN GROUP codigo, pila ASSUME CS:COMUN, DS:COMUN, SS:COMUN DB 256 DUP(?) inicio: JMP ppio ppio: MOV AX, COMUN ;inicializamos el MOV DS, AX ;segmento de datos Con el fin de obtener una imagen de ejecutable aún más compacta, se puede evitar la declaración del segmento de datos. Ahora la reserva de espacio en memoria para los datos se realiza dentro del propio segmento de código. El código comienza con una instrucción de salto incondicional que pasa por encima de la declaración de los datos. 5

DE LA CREACIÓN DEL PROGRAMA AL PROCESO EN EJECUCIÓN Definición simplificada de segmentos La definición simplificada de segmentos deja al programa ensamblador la tarea de diseño de los segmentos. Se invoca con la directiva DOSSEG. Los segmentos se declaran con las directivas.data,.code,.stack (seguido del tamaño), etc. 1 Definición simplificada de segmentos 2 Definición simplificada de segmentos Sin segmento de datos (datos en código) dosseg.model small.stack 100h.data.code inicio: mov ax, @data mov ds, ax mov ah, 4Ch int 21h end inicio dosseg.model small.stack 100h.code inicio: jmp ppio ppio: mov ax, @data mov ds, ax mov ah, 4Ch int 21h end inicio Carga y finalización del proceso bajo MS-DOS Para que el programa se convierta en proceso es necesario que el sistema operativo tome la imagen ejecutable, calcule y escriba las direcciones absolutas (tabla de realocación en el entorno MS-DOS), asigne recursos y transfiera el control al proceso. El estado del proceso de salva en un área de memoria contigua al binario conocida como PSP (Program Segment Prefix). El PSP tiene un tamaño de 256B = 100hB. La carga depende del tipo de ejecutable. Los ficheros.com no tienen tabla de realocación, ya que todas las direcciones comparten el mismo segmento y sólo necesitamos el desplazamiento para referenciar posiciones de memoria. El binario del fichero.com y del proceso coinciden. Sin embargo, los ficheros.exe deben actualizar la tabla de realocación. En el momento en el que el sistema transfiere el control del proceso, los punteros DS y ES apuntan al PSP. El resto de punteros depende del tipo de ejecutable:.exe CS e IP toman el valor especificado por END SS apunta al segmento de pila SP toma el valor del tamaño de la pila.com CS y SS apuntan al PSP IP apunta a 0100h (justo después del PSP) SP apunta a FFFEh (al final del segmento) En el caso de los ejecutables del tipo.exe, lo primero que debe hacer el código es dar el valor correcto a DS (y ES). En el caso de los.com, no es necesario ya que hay un único segmento físico (CS = SS = DS = ES = PSP[0]) y para referenciar datos sólo necesitamos su desplazamiento. Para finalizar el proceso, ya hemos visto en los ejemplos de declaración de segmentos, que existen dos mecanismos disponibles: la llamada a la interrupción INT 20h y el servicio 4Ch de la interrupción 21h. cabecera.exe.com PSP cargador programa en memoria rango de memoria libre disponible 6

LABORATORIO DE PROGRAMACIÓN EN ENSAMBLADOR X86-16BITS ANEXO: Creación de ficheros.com a partir de.exe Generamos la imagen del ejecutable.exe (que no funcionará correctamente) con las reglas dadas a continuación. Luego, desde el depurador DEBUG, escribimos un fichero.com copiando sólo el área de código y datos. Utilizaremos los comandos N (name), R CX (para dar el tamaño en CX) y W DS:offset (write). 1 Definición completa de segmentos Segmentos solapados COMUN GROUP codigo, datos, pila ASSUME CS:COMUN, DS:COMUN, SS:COMUN ORG 100h ;hueco para alojar el PSP ;si concertimos a formato.com inicio: ;NO damos valor a DS ; segmento de datos datos SEGMENT datos ENDS DB 256 DUP(?) El primer segmento en declarar debe ser el de código ya que el formato.com espera que justo detrás del PSP esté el código. La directiva ORG sirva para desplazar el puntero de instrucción el tamaño especificado (100h = 256 bytes en este caso). De este modo el código comienza justo después del PSP. No se debe iniciar DS ya que apunta al comienzo del PSP como todos los segmentos. Para referenciar datos sólo necesitamos el desplazamiento. El tamaño asignado a la pila se obvia al convertir a PSP ya que el área de pila desaparece de la imagen del ejecutable y en ejecución el puntero de pila apunta al final del segmento (FFFEh). Por esta razón, el segmento de pila se podría declarar antes que el de código El segmento de datos no puede estar antes que el de código y debe seguir siempre a éste para no dejar huecos de memoria sin uso. 2 Definición completa de segmentos Segmentos solapados sin segmento de datos (datos en segmento de código) Salida mediante INT 21h servicio 4Ch COMUN GROUP codigo, pila ASSUME CS:COMUN, DS:COMUN, SS:COMUN ORG 100h ;hueco para alojar el PSP ;si concertimos a formato.com inicio: JMP ppio ppio: ;NO damos valor a DS DB 256 DUP(?) Este programa es igual al anterior pero con los datos declarados en el segmento de código. En general será aún más pequeño que el anterior ya que los segmentos se alinean a párrafos de 16B desperdiciando algo de espacio cosa que no sucede ahora. El segmento de pila se podría haber declarado antes que el de código pero es mejor situarlo después. 7

DE LA CREACIÓN DEL PROGRAMA AL PROCESO EN EJECUCIÓN Prácticas A) Creación de un ejecutable.exe siguiendo la definición completa de segmentos. Queremos crear un ejecutable que contenga la sencilla secuencia de operaciones aritméticas que se propone a continuación: xor ax, ax mov al, operando1 add al, operando2 mov resultado, ax La declaración de datos será la mostrada a continuación. Se declaran tres variables. Dos de tamaño byte para los operandos y una de tamaño word para el resultado. operando1 DB 10h operando2 DB 20h resultado DW 0000h Crea 4 programas que incorporen este código usando los 4 esqueletos propuestos en esta práctica para desarrollar ejecutables usando la definición completa de segmentos. Una vez creados, pásaselos a DEBUG y determina el mapa de memoria de cada uno de ellos. Haz un dibujo y anota la dirección base:desplazamiento donde comienza cada segmento. Toma nota de los valores de los registros de segmento y de IP y SP antes de comenzar la ejecución y después de terminarla. B) Creación de un ejecutable.exe siguiendo la definición simplificada de segmentos. Usando el mismo código propuesto en el apartado A, crea 2 programas usando los esqueletos propuestos en esta práctica para desarrollar ejecutables usando la definición simplificada de segmentos. Usando DEBUG, determina el mapa de memoria de cada uno. Haz un dibujo y anota la dirección base:desplazamiento donde comienza cada segmento. Existe alguna diferencia con los mapas de memoria encontrados en el apartado A?. C) Creación de un ejecutable.com. Queremos crear un ejecutable de tipo.com. Para ello usaremos los esqueletos propuestos en el ANEXO de esta práctica. A partir de uno de ellos, ensamblaremos un ejecutable de tipo.exe y se lo pasaremos como argumento a DEBUG para generar el fichero ejecutable.com. El fichero.exe no funcionará ya que le falta la inicialización del segmento de datos (DS). El fichero.com es el binario que comprende solamente las secciones de código y datos del fichero.exe. Por ello, una vez cargado el.exe en DEBUG, debemos encontrar su mapa de memoria. Calcularemos el tamaño conjunto del área de código más la de datos (que deberán ser adyacentes) y lo pasaremos al registro CX con el comando R. Seguidamente, daremos la ruta y el nombre del fichero.com con el comando N y finalmente, daremos la orden de escribir el fichero en el disco con el comando W. Así creado el nuevo ejecutable.com, podremos invocarlo. La tarea que vamos a programar es la escritura de un mensaje en la pantalla. Para ello declaramos los datos siguientes: mensaje DB "Hola a todos",13,10 ;Mensaje a escribir longitud EQU $ - mensaje ;No es declaración; es etiqueta de nº entero El código invocará al sistema operativo de la siguiente manera: MOV CX, longitud MOV DX, OFFSET COMUN:mensaje MOV BX, 1 MOV AH, 40h INT 21h En el caso de utilizar segmento de datos, hemos de colocar la etiqueta COMUN delante del nombre simbólico mensaje para que asigne el desplazamiento ya que si no se hace pondrá 0. 8