Logo Studenta

UNIVERSIDAD DE ALCALA _ INGENIERIA INFORMÁTICA _ asignatura_ Estructura y organización de los computadoers _ EEOOCC_zip

Esta es una vista previa del archivo. Inicie sesión para ver el archivo original

laboratorio/Prácticas/Práctica DEBUG.pdf
LABORATORIO DE 
PROGRAMACIÓN EN LENGUAJE ENSAMBLADOR x86-16bits
Programa DEBUG: ensamblado y trazado de instrucciones
Objetivo
El primer objetivo de esta práctica es familiarizarse con el potente programa DEBUG. Entre las numerosas
facilidades que nos ofrece esta aplicación se encuentra la de ensamblar una secuencia de instrucciones y la
posibilidad de ejecutar dicha secuencia paso a paso permitiéndonos examinar todo el contexto (registros, banderas
de estado y memoria) en cada parada.
El segundo objetivo es comprender la diferencia entre un programa y una secuencia de instrucciones
ensamblada. Efectivamente, el código máquina de una secuencia de instrucciones no constituye por sí solo una
imagen válida de un ejecutable.
El programa DEBUG
El programa DEBUG es un depurador, una herramienta destinada a facilitarnos encontrar errores o
ayudarnos a mejorar el funcionamiento de una aplicación durante su desarrollo. Para ello, un depurador muestra el
contenido de la memoria y de los registros en cualquier instante de la ejecución de un programa. Además, nos
permite modificar el contenido de secciones completas de memoria o dar valor a variables o registros.
El depurador DEBUG cuenta con la capacidad adicional de permitirnos ensamblar secuencias de
instrucciones. Luego, ese código ensamblado, podemos depurarlo, ejecutarlo e incluso salvarlo en un fichero.
Las funciones que puede realizar DEBUG se enumeran a continuación:
 cargar la imagen de un ejecutable
 mostrar el código fuente de un programa junto con su código máquina y la dirección de cada instrucción
 mostrar el contenido de los registros y las banderas de estado
 ejecutar o trazar paso a paso programas o secuencias de instrucciones
 introducir valores en memoria o en registros
 buscar valores binarios o ASCII en memoria
 mover bloques de memoria de un lugar a otro
 rellenar bloques de memoria
 acceder en lectura y escritura tanto a ficheros como a sectores de disco
 ensamblar secuencias de instrucciones
 admite scripts
Depuración de un programa
Para depurar un programa existente, invocamos DEBUG pasándole como argumento el nombre del
programa:
C:>debug programa.exe
Hay que indicar que DEBUG es un depurador a nivel de ensamblador. Esto significa que el código fuente
que muestra es siempre lenguaje ensamblador independientemente del lenguaje con el que se haya escrito el código
fuente original. Es decir, lo que hace es desensamblar el código de la imagen del ejecutable.
Para ver la memoria y los registros del procesador o para ensamblar una secuencia de instrucciones,
invocamos DEBUG sin argumentos.
C:>debug
PROGRAMA DEBUG: ENSAMBLADO Y TRAZADO DE INSTRUCCIONES
Comando ?
El comando ? (ayuda) muestra el listado completo de comandos disponibles y un recordatorio de los
argumentos que admiten tal y como se puede ver a continuación.
-?
assemble A [dirección]
compare C intervalo de direcciones
dump D [intervalo]
enter E dirección [lista]
fill F lista de rango
go G [=dirección] [direcciones]
hex H valor1 valor2
input I puerto
load L [dirección] [unidad] [primer sector] [número]
move M intervalo de direcciones
name N [ruta] [lista de argumentos]
output O byte de puerto
proceed P [=dirección] [número]
quit Q
register R [registro]
search S lista de rango
trace T [=dirección] [valor]
unassemble U [intervalo]
write W [dirección] [unidad] [primer sector] [número]
allocate expanded memory XA [N.páginas]
deallocate expanded memory XD [identificador]
map expanded memory pages XM [páginaL] [páginaP] [identificador]
display expanded memory status XS
Seguidamente, veremos algunos de ellos con más detalle.
Comando Q
El comando Q (quit) cierra el depurador DEBUG y devuelve el control al DOS.
Comando A
El comando A (assemble) sirve para ensamblar las instrucciones que se le pasen seguidamente.
Opcionalmente se le puede pasar una dirección como argumento. La dirección se puede pasar como una base y un
desplazamiento explícitos, un registro de segmento y un desplazamiento o sólo un desplazamiento que tomará como
base implícita el valor de CS. Para dejar de ensamblar hay que pulsar ‘enter’ en una línea vacía.
Ejemplos:
-A ensambla a partir de la posición actual
-A 100 ensambla a partir de CS:0100h
-A DS:500 ensambla a partir de DS:0500h
-A 05FB:0100 ensambla a partir de 05FB:0100h
05FB:0100 mov ax, 10
05FB:0103 mov bx, 20
05FB:0106 add ax, bx
05FB:0108
-
Comando D
El comando D (dump) presenta el contenido de la memoria. Muestra los bytes de cada posición tanto en
hexadecimal como en ASCII. La base por defecto, usada cuando no se especifica explicitamente, es DS.
Ejemplos:
-D muestra a partir de la posición actual o DS:0 si es la primera vez
-D 100 muestra a partir de DS:0100h
-D ES:500 muestra a partir de ES:0500h
-D 05FB:0100 muestra a partir de 05FB:0100h
-D 100 110 muestra desde DS:0100h hasta DS:0110h (rango)
-D 100 L 20 muestra 20h bytes desde DS:0100h (lista)
2
LABORATORIO DE PROGRAMACIÓN EN ENSAMBLADOR X86-16BITS
Comando F
El comando F (fill) rellena un rango de memoria con un valor o con una lista de valores.
Ejemplos:
-F 100 400, 0 rellena el rango entre 100 y 400 con ‘0’
-F 100 110, CF rellena el rango entre 100 y 110 con 0CFh
-F 100 L20 ‘A’ rellena 20 bytes a partir de 100 con el carácter ‘A’
-F 100 110 ‘AB’ rellena el rango entre 100 y 110 con ‘AB’
Comando G
El comando G (go) ejecuta el programa que se está depurando o bien ejecuta lo que hay en memoria a partir
de una posición dada. También se pueden insertar hasta 10 puntos de ruptura.
Ejemplos:
-G ejecuta el programa desde la posición en curso hasta el final
-G 200 ejecuta desde la posición en curso hasta la de desplazamiento 200
-G=100 ejecuta desde la posición CS:100
-G=100 400 ejecuta desde la posición CS:100 hasta la de desplazamiento 400
Comando L
El comando L (load) carga un fichero si ha sido declarado con el comando N o sectores del disco en caso
contrario, en la posición de memoria indicada. Si no se indica dirección, se asume la CS:100. El número total de
bytes leídos se expresa en BX:CX.
Ejemplos:
-L carga el fichero declarado con N en la posición CS:100
-L DS:100 carga el fichero declarado con N en la posición DS:100
-L 300 2 A 4 carga 4 sectores del disco C (2) a partir del 0Ah en la posición CS:300
Comando N
El comando N (name) declara el fichero que se va a utilizar en combinación con los comandos L y W.
Ejemplos:
-N c:\codigo.bin declara el fichero de la ruta indicada
Comando R
El comando R (register) muestra el contenido de los registros así como la siguiente instrucción a ejecutar.
También puede mostrar el contenido de un registro individual y, en ese caso, permite cambiar su valor.
Ejemplos:
-R muestra el contenido de todos los registros
-R BX muestra el contenido del registro BX y espera por un nuevo valor
-R IP muestra el contenido del registro IP y espera por un nuevo valor
-R F muestra el contenido de los flags y espera por un nuevo valor
La tabla siguiente muestra los códigos nominales que identifican los valores que adoptan los flags.
flag a 1 flag a 0
OV = desbordamiento NV = no desbordamiento
DN = dirección decreciente UP = dirección creciente
EI = interrupción habilitada DI = interrupción deshabilitada
NG = signo negativo PL = signo positivo
ZR = cero NZ = no cero
AC = acarreo auxiliar NA = no acarreo auxiliar
PO = paridad impar PE = paridad par
CY = acarreo NC = no acarreo
3
PROGRAMA DEBUG: ENSAMBLADO Y TRAZADO DE INSTRUCCIONES
Comando T
El comando T (trace) ejecuta las instrucciones en modo paso a paso mostrando en pantalla el contenido de
los registros después de la ejecución de cada una. A partir de la dirección en curso, puede ejecutar
una sola
instrucción o un conjunto de ellas.
Ejemplos:
-T ejecuta la siguiente instrucción
-T 10 ejecuta las 16 instrucciones siguientes
-T=200 10 ejecuta las 16 instrucciones que se encuentran a partir de CS:200
Comando U
El comando U (unassemble) desensambla el contenido de memoria escribiendo los mnemónicos
correspondientes. Si no se le pasa ninguna dirección, comienza en CS:100 o en la última posición en la que se usó.
Ejemplos:
-U desensambla a partir de CS:100 (si es la primera vez que se invoca)
-U 500 desensambla a partir de CS:500
-U 200 500 desensambla entre CS:200 y CS:500
Comando W
El comando W (write) escribe un bloque de memoria en un fichero si ha sido declarado con el comando N
o en sectores del disco en caso contrario. El tamaño del bloque de memoria se ha de expresar en BX:CX. La
dirección de comienzo es CS:100 si no se expresa explícitamente.
Ejemplos:
-N c:\codigo.bin declara “codigo.bin” como fichero por defecto
-R BX (0)
-R CX (100) establece como tamaño 256 bytes (BX:CX=0:100h)
-W escribe en “c:\codigo.bin” los 256 bytes a partir de CS:100
-W 300 2 A 4 escribe 4 sectores del disco C (2) a partir del sector 0Ah con el
contenido de la memoria a partir de la posición CS:300
La escritura directa en sectores es extremadamente peligrosa si no se hace cuidadosamente ya que
podría borrar el disco completo.
Procesando scripts
El programa DEBUG admite secuencias de comandos escritos en ficheros de texto (ficheros de script) que
se le pasan mediante comandos de redireccionamiento (<). Por ejemplo, supongamos que queremos ensamblar a
partir de la dirección CS:100 una serie de instrucciones. Escribiríamos el fichero de script miscript.txt de esta
manera:
A 100
mov ax, 10
mov bx, 20
add ax, bx
Q
Obsérvese como finalizamos la secuencia de comandos con el comando Q (quit) para devolver el control al
DOS. Véase también como, tras la serie de instrucciones, se añade un retorno de carro para que finalice el
ensamblado. Para pasar el script al DEBUG haremos lo siguiente:
C:>debug < miscript.txt
4
LABORATORIO DE PROGRAMACIÓN EN ENSAMBLADOR X86-16BITS
Prácticas
A) Creación de una secuencia de código con DEBUG
Utilizando el depurador DEBUG vamos a crear una secuencia de código. La secuencia de código dispondrá
de una pequeña área de datos en la cabecera (posiciones bajas de memoria) y ejecutará algunas operaciones de
proceso y de transferencia. La secuencia se salvará como un fichero de nombre ‘codigo.bin’. Hay que recordar que
ese fichero no es un ejecutable ya que no cuenta con una cabecera reconocible por parte del sistema operativo.
Realizaremos las siguientes tareas:
 Comenzamos invocando el comando R y observando el estado de los registros.
-R
 Declaramos un fichero por defecto para las transferencias con el sistema de ficheros utilizando el
comando N
-N c:\codigo.bin
 Volcamos el contenido de 16 bytes de memoria a partir de DS:100 invocando el comando D.
-D 100 L 10
 Rellenamos los 16 bytes de memoria a partir de DS:100 con 0 invocando el comando F. Estos 16 bytes
serán la cabecera de la secuencia de código.
-F 100 L 10 0
 Comprobamos que la memoria se ha rellenado como queríamos usando el comando D de nuevo.
-D 100 L 10
 Ensamblamos con el comando A el siguiente código a partir de CS:110:
-A 110
CS:0110 mov ax, cs 1
CS:0112 add ax, 10
CS:0115 mov ds, ax
CS:0117 mov al, 11
CS:0119 mov bl, 22
CS:011B xchg bh, bl
CS:011D add ax, bx
CS:011F mov [0000], al
CS:0122 mov [0001], ax
CS:0125 neg cx
CS:0127 sub cx, [0003]
CS:012B push cx
CS:012C pop dx
CS:012D mov si, 4
CS:0130 inc si
CS:0131 mov [si], ch
CS:0133 dec dx
CS:0134 mov di, 6161
CS:0137 mov [si+1], di
CS:013A dec si
CS:013B mov ax, [si]
CS:013D
 Cargamos BX con 0 usando el comando R.
-R BX
BX 0000
:0
 Cargamos CX con 3D (tamaño del código y la cabecera de datos) usando el comando R.
-R CX
CX 0000
:3D
 Escribimos el bloque de memoria definido como secuencia de código en el fichero ‘codigo.bin’
utilizando el comando W. El comando sin argumentos toma como comienzo CS:100.
-W
1 El comando A presenta en cada línea la dirección CS:desplazamiento con los valores que tenga en cada caso.
5
PROGRAMA DEBUG: ENSAMBLADO Y TRAZADO DE INSTRUCCIONES
 Desensamblamos el contenido de memoria a partir de CS:100 y a partir de CS:110 con el comando U.
Veremos que el área de código, rellena con 0, también admite una interpretación como código.
-U 100
…
-U 110
La secuencia de comandos se puede escribir en un fichero de script para pasársela a DEBUG
posteriormente. La salida del depurador se puede salvar en un fichero de texto. Este sistema puede ser más cómodo
que usar DEBUG directamente ya que, en caso de error, no hay que volver a empezar el ensamblado completo del
código.
B) Trazado de la secuencia de código generada
Utilizando nuevamente DEBUG, se pide trazar la secuencia de código generada anteriormente. Entendemos
por trazar el hecho de ejecutar paso a paso una serie de instrucciones teniendo acceso en cada detención a los
registros del procesador, a su estado y a la memoria del proceso.
La ejecución paso a paso nos permite depurar los programas así como alcanzar una comprensión más
profunda del funcionamiento de una determinada tarea con el objetivo, por ejemplo, de conseguir un mayor
rendimiento del código.
Para trazar el código con DEBUG utilizaremos el comando T. Cargaremos, primero, la secuencia de código
utilizando los comandos N y L. Una vez en memoria, pasaremos a ejecutarla paso a paso observando cada vez las
modificaciones que se hayan llevado a cabo en registros, estado y memoria.
-N c:\codigo.bin
-L
-R IP
IP 0100
:0110
-R
AX=0000 BX=0000 CX=003D DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=0CB8 ES=0CB8 SS=0CB8 CS=0CB8 IP=0110 NV UP EI PL NZ NA PO NC
0CB8:0110 8CC8 MOV AX,CS
-T
6
Hago que IP apunte a la primera 
instrucción de la secuencia de código.
laboratorio/Prácticas/Práctica DEL PROGRAMA AL PROCESO_v3.pdf
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
Los ficheros ejecutables tienen extensión .EXE y se ajustan al formato MZ, es decir, la cabecera del fichero
se ajusta a dicho formato MZ. El binario representa todos los segmentos declarados incluyendo la pila. Dependiendo
del tipo de declaración, los segmentos pueden estar solapados parcial o totalmente o no estar solapados en absoluto.
El tamaño del ejecutable no está limitado a 64KB.
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 enalza
(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 21h – servicio 4Ch
ASSUME CS:codigo, DS:datos, SS:pila
;--------------------------------------------
; segmento de datos
datos SEGMENT
 // DECLARACIÓN DE DATOS //
datos ENDS
;--------------------------------------------
; segmento de pila
pila SEGMENT STACK
 // DECLARACIÓN DEL TAMAÑO DE LA PILA //
 DB 256 DUP(?) ; pila de 256 bytes
pila ENDS
;--------------------------------------------
; segmento de código
codigo SEGMENT
 inicio: MOV AX, DATOS ;inicializamos el 
 MOV DS, AX ;segmento de datos
 // CÓDIGO DEL PROGRAMA //
MOV AX, 4C00h ;devolver el control
 INT 21h ;al MS-DOS
codigo ENDS
;--------------------------------------------
; indicamos al programa ensamblador dónde
; comienza el código del programa
; sirve para dar valor a CS:IP
END inicio
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 (inicio en este ejemplo). Esto sirve
para que CS:IP apunte a la dirección de arranque.
El segmento de código contiene la
secuencia de instrucciones. Es muy importante que
comience asignando valor al segmento de datos ya
que si no se hace, no podrán referenciarse los datos.
Existen otras maneras de realizar la declaración completa de segmentos, por ejemplo, solapando los
segmentos con el fin de minimizar el tamaño de los ejecutables.
4
LABORATORIO DE PROGRAMACIÓN EN ENSAMBLADOR X86-16BITS
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
 // DECLARACIÓN DE DATOS //
.code
inicio:
 mov ax, @data
 mov ds, ax
 // CÓDIGO DEL PROGRAMA //
 mov ah, 4Ch
 int 21h
end inicio
dosseg
.model small
.stack 100h
.code
inicio:
 jmp ppio
 // DECLARACIÓN DE DATOS //
ppio:
 mov ax, @code ;ojo, no @data
 mov ds, ax
 // CÓDIGO DEL PROGRAMA //
 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.
Como se ha indicado, para cargar los ficheros .EXE el sistema operativo debe actualizar las direcciones absolutas
anotadas en la tabla de realocación sumando a cada valor de la tabla la dirección de comienzo del proceso.
En el momento en el que el sistema transfiere el control del proceso, los punteros adoptan estos valores:
 DS y ES apuntan al PSP
 CS e IP toman el valor especificado por la directiva END
 SS apunta al segmento de pila
 SP toma el valor del tamaño de la pila
Puesto que el sistema operativo asigna a DS y ES el puntero del PSP, es responsabilidad del programador
comenzar el código asignando a DS (y ES si se usa) el valor correcto.
Para finalizar el proceso se utiliza el servicio 4Ch de la interrupción 21h, tal y como podemos observar en
los ejemplos de declaración de segmentos.
cargador
rango de memoria libre
disponible
PSP
programa
memoria
en
cabecera
.EXE .COM
5
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 un programa que incorporen este código usando el “esqueleto” propuesto en esta práctica para
desarrollar ejecutables usando la definición completa de segmentos. Una vez creado, pásaselo a DEBUG y
comprueba que realiza las tareas correctamente trazando la ejecución del código.
B) Creación de un ejecutable .EXE siguiendo la definición simplificada de segmentos.
Crea 2 programas usando los dos “esqueletos” propuestos en esta práctica para desarrollar ejecutables
usando la definición simplificada de segmentos.
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 mensaje
 MOV BX, 1
 MOV AH, 40h
 INT 21h
6
laboratorio/Prácticas/Práctica SERVICIOS INT 21h - E-S CARACTERES.pdf
 
 
LABORATORIO DE 
PROGRAMACIÓN EN LENGUAJE ENSAMBLADOR x86-16bits 
 
 
Interrupciones del sistema. Servicios de entrada/salida de caracteres (INT 21h) 
 
Objetivo 
 
El objetivo de esta práctica es conocer y aprender a utilizar los servicios de entrada/salida de caracteres que 
ofrece la interrupción del sistema operativo INT 21h. Estos servicios toman como entrada el teclado y como salida 
la pantalla. Existen servicios diferenciados para trabajar sobre caracteres individuales o sobre cadenas de caracteres. 
 
 
Funciones de entrada de caracteres de la INT 21h 
 
La entrada se realiza desde el teclado. Disponemos de varios servicios para hacer la lectura de un carácter. Se 
diferencian en función de si la entrada es bloqueante o no y de si se atiende o no la combinación de teclas Ctrl-Break. 
 
 
Entrada bloqueante 
 
Una entrada/salida es bloqueante si el proceso principal se detiene hasta que se satisfaga alguna condición 
(normalmente hasta que los datos se hayan leído o escrito). Será no bloqueante si el proceso principal no se detiene. 
 
En el caso que nos ocupa, un servicio de lectura de carácter es bloqueante si espera hasta que se lea algún 
carácter. Será no bloqueante si lee el buffer de teclado devolviendo o un código de carácter o 0 si no hay carácter. 
 
El uso de un servicio bloqueante o no bloqueante depende de lo que necesite el programador en cada caso. 
En ocasiones será conveniente detener la ejecución del programa en tanto no haya un carácter de entrada mientras 
que en otros momentos bastará con comprobar si hay o no un carácter disponible. 
 
 
Combinación Ctrl-Break 
 
La combinación de teclas Ctrl-Break (Ctrl-C) se puede usar para invocar una interrupción especial 
conocida como break de teclado (interrupción BIOS INT 1Bh) que sirve para terminar el proceso en curso. La rutina 
de atención a la INT 1Bh por defecto sólo contiene una instrucción IRET, es decir, que no realiza ninguna tarea. Sin 
embargo, se puede cambiar dicha rutina para que realice otra tarea. Existen servicios de entrada de carácter que 
atienden la interrupción de break de teclado y otros que no. 
 
 
Servicio 01h – entrada bloqueante con eco y atención a Ctrl-Break 
 
El servicio 01h de la INT 21h espera a que se pulse una tecla y la escribe en la pantalla (lectura con eco) 
comprobando si es Ctrl-Break en cuyo caso dispara la interrupción de break de teclado que suele finalizar el 
programa en curso. El código ASCII del carácter se devuelve en el registro AL. 
 
argumentos: ah = 01h valores devueltos: al = código ASCII leído 
 
 
Servicio 06h – DL = FFH – entrada no bloqueante sin eco y omisión de Ctrl-Break 
 
El servicio 06h de la INT 21h puede ser de entrada o salida. Si DL es igual a FFh, lee un carácter
del buffer 
del teclado sin eco y omitiendo un posible Ctrl-Break. 
 
argumentos valores devueltos 
ah = 06h 
dl = FFh (lectura de consola) 
zf = 0 si hay carácter y 1 si no hay carácter disponible 
al = código ASCII leído 
 
 
Servicio 07h – entrada bloqueante sin eco y omisión de Ctrl-Break 
 
El servicio 07h de la INT 21h espera a que se pulse una tecla sin eco y omitiendo un posible Ctrl-Break. El 
código ASCII del carácter se devuelve en el registro AL. 
 
argumentos: ah = 07h valores devueltos: al = código ASCII leído 
 
 
Servicio 08h – entrada bloqueante sin eco y atención a Ctrl-Break 
 
El servicio 08h de la INT 21h espera a que se pulse una tecla sin eco y comprobando si es Ctrl-Break en 
cuyo caso dispara la interrupción de break de teclado. El código ASCII del carácter se devuelve en el registro AL. 
 
argumentos: ah = 08h valores devueltos: al = código ASCII leído 
 
INTERRUPCIONES DEL SISTEMA. SERVICIOS DE ENTRADA/SALIDA DE CARACTERES (INT 21H) 
2 
 
Servicio 0Bh – lee el estado del teclado con atención a Ctrl-Break 
 
El servicio 0Bh lee el estado del teclado con atención a Ctrl-Break. El registro AL devuelve el estado. 
 
argumentos: ah = 0Bh valores devueltos: al = FFh si hay carácter; 0 en caso contrario 
 
 
Servicio 0Ch – borra el buffer del teclado e invoca un servicio de entrada de carácter 
 
El servicio 0Ch de la INT 21h borra el buffer del teclado e invoca un servicio de entrada de carácter de los 
explicados más arriba (01h, 06h, 07h, 08h) o de entrada de cadenas que se verá seguidamente (0Ah). El registro AL 
se utiliza para seleccionar el servicio a invocar y devuelve el valor propio de dicho servicio. 
 
argumentos valores devueltos 
ah = 0Ch 
al = número de servicio a invocar 
al = valor devuelto por el servicio invocado 
 
 
Funciones de salida de caracteres de la INT 21h 
 
Como hemos indicado, la salida se realiza sobre la pantalla. Disponemos de un único servicio para escribir 
un carácter en la pantalla con la INT 21h. Es el siguiente: 
 
 
Servicio 02h – salida de carácter 
 
El servicio 02h presenta un carácter en pantalla. El registro DL contiene el ASCII del carácter a escribir: 
 
argumentos valores devueltos 
ah = 02h 
dl = código ASCII del carácter a escribir 
al = código ASCII escrito 
 
 
Servicio 06h – DL ≠≠≠≠ FFH – salida de carácter 
 
Este servicio puede ser de entrada o salida. Si DL es distinto de FFh, escribe el carácter codificado en DL. 
 
argumentos valores devueltos 
ah = 06h 
dl = código ASCII del carácter a escribir (≠FFh) 
al = código ASCII escrito 
 
 
Funciones de entrada/salida de cadenas de caracteres de la INT 21h 
 
Una cadena de caracteres (string en inglés) es una secuencia ordenada de longitud arbitraria de códigos 
alfanuméricos. El sistema de codificación puede ser ASCII, EBCDIC o UNICODE. 
 
Físicamente las cadenas se pueden almacenar colocando cada código en posiciones consecutivas de 
memoria o enlazando carácter a carácter. El primer sistema es el más habitual y eficiente. 
 
Para diferenciar una cadena de otra, podemos reservar espacio en memoria de tamaño fijo, pero este 
método es ineficiente ya que desaprovecha espacio de almacenamiento. Habitualmente, lo más eficiente es manejar 
espacios de almacenamiento de longitud variable utilizando alguno de estos métodos: 
• indicando el comienzo y final de cada cadena mediante un carácter separador 
• indicando la longitud de la cadena antes de la misma 
• indicando el final de la cadena mediante un carácter terminador 
 
En el caso de los servicios de entrada/salida de cadenas de la interrupción del sistema operativo INT 21h se 
utiliza el almacenamiento consecutivo en memoria de los códigos alfanuméricos y se permite la longitud arbitraria 
de la cadena gracias al carácter terminador ‘enter’ para entrada de cadena y ‘$’ para salida de cadena. 
 
 
Servicio 0Ah – entrada de cadena de caracteres 
 
El servicio 0Ah de la INT 21h lee una secuencia de caracteres desde el teclado y los almacena en memoria 
hasta que se pulse la tecla ‘enter’. El área de memoria es una estructura de datos con 3 campos: el primer byte es el 
tamaño máximo permitido de la cadena incluido el código de la tecla ‘enter’, el segundo byte recibirá el número de 
caracteres leídos sin contar el ‘enter’ y el tercer campo es el buffer de memoria en el que se almacenará la cadena 
incluyendo el ‘enter’. Evidentemente, el tamaño del buffer deberá coincidir con el valor del primer campo. El 
puntero del área de memoria se pasa como parámetro en DS:DX. 
 
 LABORATORIO DE PROGRAMACIÓN EN ENSAMBLADOR X86-16BITS 
 3 
argumentos valores devueltos 
ah = 0Ah 
ds:dx = puntero del área de memoria 
- número de caracteres leídos 
- cadena 
 
 
Ejemplo: 
.data
cadena DB 11,?,11 DUP(?) ;reserva para una cadena de 10 caracteres
.code
mov ax, @DATA
mov ds, ax
lea dx, cadena
mov ah, 0Ah
int 21h
 
 
Servicio 09h – salida de cadena de caracteres 
 
El servicio 09h de la INT 21h escribe en la pantalla una cadena de caracteres almacenada en memoria y 
finalizada con el carácter ‘$’. El puntero del área de memoria se pasa como parámetro en DS:DX. 
 
argumentos valores devueltos 
ah = 09h 
ds:dx = puntero de la cadena 
al = 24h 
 
Ejemplo: 
.data
cadena DB ‘Hola mundo$’
.code
mov ax, @DATA
mov ds, ax
lea dx, cadena
mov ah, 09h
int 21h
 
 
Funciones de entrada/salida de dispositivos de la INT 21h 
 
El sistema operativo proporciona una serie de servicios a través de la INT 21h para hacer transferencias de 
caracteres con dispositivos que bien pueden ser ficheros o la consola. Por consola entendemos la entrada y salida 
estándar, es decir, la entrada por teclado o stdin y la salida por pantalla o stdout. 
 
Estos servicios permiten crear, borrar, abrir, cerrar, leer, escribir y realizar otras acciones, sobre ficheros. 
En este momento sólo estamos interesados en la entrada/salida por consola: 
• leer fichero o consola: servicio 3Fh 
• escribir fichero o consola: servicio 40h 
 
Estos servicios representan una alternativa a los de entrada/salida de cadenas ya que no utilizan carácter 
terminador en las cadenas sino que trabajan con el número de caracteres a transferir como argumento. 
 
 
Servicio 3Fh – lectura de dispositivo 
 
El servicio 3Fh de la INT 21h lee caracteres de un dispositivo. Si el dispositivo es un fichero, se le pasa el 
manejador del fichero (handler) y el número de caracteres a leer. Si el dispositivo es la consola, el número de 
manejador es el 1 y se lee el teclado hasta que aparezca el carácter CR (Carriage Return) al pulsar la tecla ‘enter’. 
 
argumentos valores devueltos 
ah = 3Fh 
bx = manejador del dispositivo (1 si consola) 
cx = número de caracteres a leer 
ds:dx = puntero del área de memoria 
cf = 0 si no hay error y 1 si se produce error 
ax = número de caracteres leídos o código de error en su caso 
 
 
 
INTERRUPCIONES DEL SISTEMA. SERVICIOS DE ENTRADA/SALIDA DE CARACTERES (INT 21H) 
4 
Servicio 40h – escritura en dispositivo 
 
El servicio 40h de la INT 21h escribe un número de caracteres especificado como argumento en un 
dispositivo. Si el dispositivo es la consola, el número de manejador es el 1 y se escribe en pantalla. El puntero del 
área de memoria se pasa como parámetro en DS:DX. 
 
argumentos valores devueltos 
ah = 40h 
bx = manejador del dispositivo (1 si consola) 
cx = número de caracteres a escribir 
ds:dx = puntero del área de memoria 
cf = 0 si no hay error y 1 si se produce error 
ax = número de caracteres escritos o código de error en su caso 
 
 
 
 
Prácticas 
 
A) Realiza un programa que capture 4 caracteres numéricos y almacene el valor numérico en una 
variable de tipo word. 
 
Los caracteres numéricos del 0 al 9 se codifican en ASCII del 30h al 39h (véase tabla ASCII más abajo). 
Esto hace que sea muy sencillo su detección y conversión a entero. Cada vez que no se introduzca un carácter 
numérico,
el programa emitirá un mensaje de error y volverá a comenzar. 
 
Para calcular el valor numérico, acumularemos los resultados parciales sobre el registro DX inicialmente a 
cero. Por cada carácter, multiplicamos DX por 10 y le sumamos la nueva cifra. Una vez finalizado la captura de las 
4 cifras ABCD, tendremos: 
 
DX = ((((DX * 10 + A) *10 + B) * 10) + C *10) + D 
 
 
B) Realiza un programa que emita un mensaje por pantalla en función de la tecla que se pulse. 
 
Programa un bucle que emita un mensaje en pantalla de manera indefinida. El mensaje cambiará en función 
de la tecla que se pulse. Si se pulsa ‘F’ el programa finaliza. La lectura del teclado será no bloqueante. 
 
 
C) Realiza un programa lea 2 caracteres hexadecimales y almacene su valor entero en una 
variable de tipo byte. Sólo se hará eco de los caracteres hexadecimales. 
 
La entrada se programará sin eco. Una vez validado el carácter leído, se hará eco. Si no corresponde a un 
carácter hexadecimal se seguirá esperando un nuevo carácter. Una vez almacenada la variable, se mostrará en 
pantalla tomándola como ASCII. Son caracteres hexadecimales: ‘0’ – ‘9’, ‘a’ – ‘f’ y ‘A’ – ‘F’. 
 
Para obtener el valor numérico de un carácter hexadecimal codificado en mayúsculas ASCII basta con 
restar ‘A’ – 10, es decir, restarle su código ASCII y sumar su valor numérico en decimal. 
 
 
D) Realiza un programa que pida una cadena de un máximo de 10 caracteres, convierta las 
mayúsculas a minúsculas y viceversa, y presente la nueva cadena en pantalla. 
 
En la tabla ASCII vemos que los caracteres de las mayúsculas y de las minúsculas sólo se diferencias en el 
bit del peso 25. Basta con complementar dicho bit para que el carácter cambie de tamaño. Usaremos el servicio 0Ah 
para leer la cadena y el servicio 09h o el 40h para presentar la nueva cadena. 
 
 
 
laboratorio/Teoría de laboratorio/01 - Arquitectura software x86-16bits.pdf
1
Arquitectura software x86-16bits
1/47©
R
af
ae
l R
ic
o 
Ló
pe
z
Índice
1. Organización interna
2. Segmentación de memoria
3. Modos de direccionamiento
4. Formato de instrucciones
Arquitectura software x86-16bits
2/47©
R
af
ae
l R
ic
o 
Ló
pe
z
¿Qué es arquitectura software?
• Es el conjunto de atributos que ve el programador
� …o que ve el compilador, como generador 
automático de código
• Es el “contrato” entre en fabricante del procesador y 
el programador
• No requiere correspondencia real con la capa física
• La arquitectura software x86-16bits data de 1978
� Típico repertorio CISC
2
Arquitectura software x86-16bits
3/47©
R
af
ae
l R
ic
o 
Ló
pe
z
1. Organización interna
PROPÓSITO GENERAL015
Puntero a la cima de la pilaSPPuntero de pila
Destino en manejo de cadenasDIÍndice destino
Fuente en manejo de cadenasSIÍndice fuente
Puntero a dirección base (pila)BPPuntero base
Producto, división y E/SDLDHDatos
Contador de bucles, desplazamientos, 
rotaciones y repetición de cadenasCLCHContador
Puntero a dirección base (datos)BLBHBase
Producto, división, E/S y transferencias 
optimizadasALAHAcumulador
AX
BX
CX
DX
Arquitectura software x86-16bits
4/47©
R
af
ae
l R
ic
o 
Ló
pe
z
1. Organización interna
Registros de propósito general:
• Almacenamiento temporal de datos
• Algunos se acceden como palabra (16 bits) o como byte
� Registro X
� Registro L y H
• Usos dedicados y limitaciones
• Modelo híbrido (acumulador y banco de registros)
� Heredado de arquitecturas anteriores
3
Arquitectura software x86-16bits
5/47©
R
af
ae
l R
ic
o 
Ló
pe
z
1. Organización interna
REGISTROS DE SEGMENTO015
ESSegmento extra (datos)
SSSegmento de pila
DSSegmento de datos
CSSegmento de código
• Los programas manejan 
diferentes áreas de 
memoria:
�Código (texto)
�Datos
�Pila
�Heap
• Estos registros apuntan a 
dichas áreas de memoria
Arquitectura software x86-16bits
6/47©
R
af
ae
l R
ic
o 
Ló
pe
z
1. Organización interna
Registros de segmento:
• Todas las direcciones son relativas a alguno de los 
registros de segmento (por defecto)
• CS: la memoria de este segmento contiene instrucciones
• DS: datos declarados por el programa
• SS: es la pila
• ES: datos extra; datos de cadenas
4
Arquitectura software x86-16bits
7/47©
R
af
ae
l R
ic
o 
Ló
pe
z
1. Organización interna
OTROS REGISTROS015
IPPuntero de instrucción
FlagsEstado
Arquitectura software x86-16bits
8/47©
R
af
ae
l R
ic
o 
Ló
pe
z
1. Organización interna
15
paridad
acarreo
REGISTRO DE ESTADO
acarreo auxiliar
cero
signo
trap (paso a paso)
interrupción
dirección
desbordamiento
CPAZSTIDO
0
5
Arquitectura software x86-16bits
9/47©
R
af
ae
l R
ic
o 
Ló
pe
z
1. Organización interna
• Acarreo:
� Es 1 si el resultado de una operación genera acarreo
• Paridad:
� Es 1 si el resultado contiene un número par de bits a 1
• Acarreo auxiliar:
� Es 1 si el resultado genera un acarreo en los 4 bits de 
menor peso. Se usa en aritmética BCD
• Cero:
� Es 1 si el resultado es cero
• Signo:
� Copia el bit de mayor peso del resultado
�(independientemente de la interpretación del resultado)
Arquitectura software x86-16bits
10/47©
R
af
ae
l R
ic
o 
Ló
pe
z
1. Organización interna
• Trap:
� Si es 1 el procesador genera una interrupción de paso a 
paso después de ejecutar cada instrucción
• Interrupción:
� Si es 1 las interrupciones serán reconocidas
• Dirección:
� Si es 1 las operaciones con cadenas se realizan de las 
posiciones altas a las bajas
6
Arquitectura software x86-16bits
11/47©
R
af
ae
l R
ic
o 
Ló
pe
z
1. Organización interna
• Desbordamiento:
� Es 1 si el resultado es demasiado grande (o pequeño) 
para los límites de representación con signo (en C-2)
21 −− ⊕= nn ccOF
Arquitectura software x86-16bits
12/47©
R
af
ae
l R
ic
o 
Ló
pe
z
1. Organización interna
• Flags de estado
� Acarreo, paridad, acarreo auxiliar, cero, signo y 
desbordamiento
�Describen el resultado
�Se aplican a operaciones de tamaño byte (n=8) –ya sea 
la parte alta o la baja– o palabra (n=16)
�Proporcionan códigos de condición por separado o en 
conjunto
• Flags de control
� Trap, interrupción y dirección
�Afectan al modo de funcionamiento del procesador
7
Arquitectura software x86-16bits
13/47©
R
af
ae
l R
ic
o 
Ló
pe
z
1. Organización interna
Arquitectura software x86-16bits
14/47©
R
af
ae
l R
ic
o 
Ló
pe
z
2. Segmentación de memoria
• El mapa de memoria que “ve” el x86-16bits NO es “plano”
• Los registros de 16 bits sólo pueden direccionar
216 posiciones de memoria (65.636 posiciones = 64K)
• ¿Cómo alcanzar un espacio de direcciones mayor?
• El acceso a memoria se realiza en segmentos de 64K
8
Arquitectura software x86-16bits
15/47©
R
af
ae
l R
ic
o 
Ló
pe
z
2. Segmentación de memoria
• La memoria está organizada en bytes (B)
• La capacidad de direccionamiento es de 1MB (220 B)
• La dirección completa se consigue mediante la 
combinación de dos punteros: base y desplazamiento 
(offset):
base:desplazamiento
• La dirección física se calcula:
base x 16 + desplazamiento
Arquitectura software x86-16bits
16/47©
R
af
ae
l R
ic
o 
Ló
pe
z
2. Segmentación de memoria
Ejemplos:
• La dirección 53C2:107A es:
53C20 h x16 (x10 h)
+107A h
54C9A h dirección física
• La dirección B100:046C es:
B1000 h x16 (x10 h)
+046C h
B146C h dirección física
9
Arquitectura software x86-16bits
17/47©
R
af
ae
l R
ic
o 
Ló
pe
z
2. Segmentación de memoria
• La misma dirección física puede ser accedida con 
diferentes combinaciones base:desplazamiento
Ejemplo:
• La dirección física 7A26B h puede ser:
�7A26:000B
�7A00:026B
�751C:50AB
• Problemas de seguridad
• La base (segmento) apunta a párrafos (de 16 posiciones)
Arquitectura software x86-16bits
18/47©
R
af
ae
l R
ic
o 
Ló
pe
z
2. Segmentación de memoria
• En ensamblador no se representan las direcciones 
como base:desplazamiento aunque si lo admiten los 
depuradores
• Los desplazamientos llevan asociada una base por 
defecto
• Cuando es necesario especificar la base se hace de 
manera simbólica (usando el nombre del registro de 
segmento como prefijo de la instrucción)
10
Arquitectura software x86-16bits
19/47©
R
af
ae
l R
ic
o 
Ló
pe
z por defectopor defectoprefijoprefijoDI
SI
BX
BP
SP
IP
base
offset
prefijopor defectoprefijoprefijo
prefijopor defectoprefijoprefijo
prefijoprefijopor defectoprefijo
nonosíno
nononosí
ESDSSSCS
2. Segmentación de memoria
Arquitectura software x86-16bits
20/47©
R
af
ae
l R
ic
o 
Ló
pe
z
2. Segmentación de memoria
• Las direcciones pueden ser:
� Near
� Far
• Near : sólo el desplazamiento; la base toma el valor 
en curso de la dada por defecto
• Far : se requiere la especificación de la base y del 
desplazamiento
11
Arquitectura software x86-16bits
21/47©
R
af
ae
l R
ic
o 
Ló
pe
z
2. Segmentación de memoria
Arquitectura software x86-16bits
22/47©
R
af
ae
l R
ic
o 
Ló
pe
z
2. Segmentación de memoria
12
Arquitectura software x86-16bits
23/47©
R
af
ae
l R
ic
o 
Ló
pe
z
3. Modos de direccionamiento
• Determinan la ubicación de los operandos
• Tres posibles ubicaciones:
�Inmediatos (en la propia instrucción)
�En registros
�En memoria
�(Implícitos) � no se identifican, son sobreentendidos
Arquitectura software x86-16bits
24/47©
R
af
ae
l R
ic
o 
Ló
pe
z
3. Modos de direccionamiento
• Momento en el que se actualiza el modo de 
direccionamiento:
�Inmediatos � tiempo de ensamblado
�En registros � tiempo de programación o compilación
�En memoria
• Absolutos � tiempo de carga
• Relativos � tiempo de ejecución
interviene el SO
13
Arquitectura software x86-16bits
25/47©
R
af
ae
l R
ic
o 
Ló
pe
z
3. Modos de direccionamiento
• Clasificación de estructura de computadores:
a registro
base + desplazamiento
base + índice + desplazamiento 
contador de programa
puntero de pila
relativo
implícito
indirecto
a registro
a memoria
a página base
absolutodirecto
inmediato
Arquitectura software x86-16bits
26/47©
R
af
ae
l R
ic
o 
Ló
pe
z
3. Modos de direccionamiento
3.1. Inmediato
� Ejemplo: MOV AL,15h
8088/86
IP
CS
SS
ES
DS
AX
BX
CX
DX
SI
DI
BP
SP
MEMORIA INSTRUCCIÓNDIRECCIÓN
siguiente instrucciónXX
Antes de ejecutar la instrucción
0000
0100
XX
80
15
MOV AL,15h01000
01001
01002
01003
8088/86
IP
CS
SS
ES
DS
AX
BX
CX
DX
SI
DI
BP
SP
MEMORIA INSTRUCCIÓNDIRECCIÓN
siguiente instrucciónXX
Después de ejecutar la instrucción
0002
0100
01000
01001
01002
01003
80
15
MOV AL,15h
15
14
Arquitectura software x86-16bits
27/47©
R
af
ae
l R
ic
o 
Ló
pe
z
3. Modos de direccionamiento
3.2. Directo absoluto a registro
� Ejemplo: MOV AX,BX
8088/86
IP
CS
SS
ES
DS
AX
BX
CX
DX
SI
DI
BP
SP
MEMORIA INSTRUCCIÓNDIRECCIÓN
siguiente instrucciónXX
Antes de ejecutar la instrucción
0000
0100
XXXX
8B
C3
MOV AX,BX01000
01001
01002
01003
7FA6
8088/86
IP
CS
SS
ES
DS
AX
BX
CX
DX
SI
DI
BP
SP
MEMORIA INSTRUCCIÓNDIRECCIÓN
siguiente instrucciónXX
Después de ejecutar la instrucción
0002
0100
01000
01001
01002
01003
8B
C3
MOV AX,BX
7FA6
7FA6
Arquitectura software x86-16bits
28/47©
R
af
ae
l R
ic
o 
Ló
pe
z
3. Modos de direccionamiento
3.3. Directo absoluto a memoria (nombre INTEL: directo a memoria)
� Ejemplo: MOV CX,ETIQUETA
8088/86
IP
CS
SS
ES
DS
AX
BX
CX
DX
SI
DI
BP
SP
MEMORIA INSTRUCCIÓNDIRECCIÓN
siguiente instrucciónXX
Antes de ejecutar la instrucción
0000
0100
XXXX
8B
0E
MOV CX,ETIQUETA01000
01001
01002
01003
0200 01004
03234
03235
34
12
(ETIQUETA = 1234h)
ED
BE
operando fuente
8088/86
IP
CS
SS
ES
DS
AX
BX
CX
DX
SI
DI
BP
SP
MEMORIA INSTRUCCIÓNDIRECCIÓN
Después de ejecutar la instrucción
0004
0100
siguiente instrucciónXX
8B
0E
MOV CX,ETIQUETA01000
01001
01002
01003
01004
03234
03235
34
12
ED
BE
0200
BEED
15
Arquitectura software x86-16bits
29/47©
R
af
ae
l R
ic
o 
Ló
pe
z
3. Modos de direccionamiento
3.4. Directo relativo a registro (nombre INTEL: indirecto a memoria)
� Ejemplo: MOV[BX]+ARTICULO,AL
registro base
8086/88
IP
CS
SS
ES
DS
AX
BX
CX
DX
SI
DI
BP
SP
MEMORIA INSTRUCCIÓNDIRECCIÓN
siguiente instrucciónXX
Antes de ejecutar la instrucción
0000
0100
1000
88
87
MOV [BX]+ARTICULO, AL01000
01001
01002
01003
0500 01004
0B000
0B001
00
50
(ARTICULO = 5000h)
XX
operando destino
XX FC
XX
8086/88
IP
CS
SS
ES
DS
AX
BX
CX
DX
SI
DI
BP
SP
MEMORIA INSTRUCCIÓNDIRECCIÓN
Después de ejecutar la instrucción
0004
0100
siguiente instrucciónXX
88
87
01000
01001
01002
01003
01004
0B000
00
50
FC
0500
MOV [BX]+ARTICULO, AL
1000
XX
XX0B001
FC
Arquitectura software x86-16bits
30/47©
R
af
ae
l R
ic
o 
Ló
pe
z
3. Modos de direccionamiento
3.4. Directo relativo a registro (nombre INTEL: indirecto a memoria)
� Ejemplo: MOV DL,VECTOR[SI]
registro índice
8086/88
IP
CS
SS
ES
DS
AX
BX
CX
DX
SI
DI
BP
SP
MEMORIA INSTRUCCIÓNDIRECCIÓN
siguiente instrucciónXX
Antes de ejecutar la instrucción
0000
0100
8A
94
MOV DL,VECTOR[SI]01000
01001
01002
01003
B000 01004
BA000
00
A0
(VECTOR = A000h)
ED operando fuente
XX XX
0000
8086/88
IP
CS
SS
ES
DS
AX
BX
CX
DX
SI
DI
BP
SP
MEMORIA INSTRUCCIÓNDIRECCIÓN
Después de ejecutar la instrucción
0004
0100
siguiente instrucciónXX
8A
94
01000
01001
01002
01003
01004
BA000
00
A0
ED
B000
MOV DL,VECTOR[SI]
EDXX
0000
16
Arquitectura software x86-16bits
31/47©
R
af
ae
l R
ic
o 
Ló
pe
z
3. Modos de direccionamiento
3.4. Directo relativo a registro (nombre INTEL: indirecto a memoria)
� Ejemplo: MOV AH,[BX][SI]+ARRAY
8088/86
IP
CS
SS
ES
DS
AX
BX
CX
DX
SI
DI
BP
SP
MEMORIA INSTRUCCIÓNDIRECCIÓN
siguiente instrucciónXX
Antes de ejecutar la instrucción
0000
0100
1000
8A
20
MOV AH,[BX][SI]+ARRAY01000
01001
01002
01003
0200 01004
06234
06235
34
12
(ARRAY = 1234h)
ED
XX
operando fuente
XX XX
2000
8088/86
IP
CS
SS
ES
DS
AX
BX
CX
DX
SI
DI
BP
SP
MEMORIA INSTRUCCIÓNDIRECCIÓN
j
Después de ejecutar la instrucción
0004
0100
siguiente instrucciónXX
8A
20
01000
01001
01002
01003
01004
06234
34
12
ED
0200
MOV AH,[BX][SI]+ARRAY
1000
ED XX
2000
registro índice y base
Arquitectura software x86-16bits
32/47©
R
af
ae
l R
ic
o 
Ló
pe
z
4. Formato de instrucciones
• Es la codificación binaria de las instrucciones
• Debe proporcionar información acerca de:
� Operación a realizar
� Operandos y resultado
� Siguiente instrucción (secuencia implícita)
• El x86-16bits cuenta con dos formatos:
� Formato general
� Formato especial (campo de extensión y/o prefijo)
• Está diseñado para minimizar el espacio de 
representación
17
Arquitectura software x86-16bits
33/47©
R
af
ae
l R
ic
o 
Ló
pe
z
4. Formato de instrucciones
4.1. Formato general
d w mod reg r/m
desplazamiento o dato inmediato
especifica un operando registro
especifica un operando registro o memori
determina el tamaño de los operandos
determina el operando fuente y destino
código de
operación
código
byte 1 byte 2 byte 4byte 3
Arquitectura software x86-16bits
34/47©
R
af
ae
l R
ic
o 
Ló
pe
z
4. Formato de instrucciones
4.1. Formato general
• El primer byte contiene 3 clases de información:
� Código de operación: los 6 primeros bits contienen el 
código de la operación a realizar
� El bit de dirección de registro (D): especifica si el 
operando dado por el
campo de registro operando REG 
en el segundo byte es el operando fuente o destino:
• si D = 1 tengo que REG = operando destino
• si D = 0 tengo que REG = operando fuente
� El bit de tamaño del dato (W): especifica si la operación 
será realizada sobre datos de 8 o de 16 bits:
• si w = 0 los datos son de 8 bits
• si w = 1 los datos son de 16 bits
18
Arquitectura software x86-16bits
35/47©
R
af
ae
l R
ic
o 
Ló
pe
z
4. Formato de instrucciones
4.1. Formato general
• El segundo byte contiene los operandos:
� Uno siempre es un registro
�Viene dado por REG
� El otro puede ser registro o memoria
�Viene dado por MOD y R/M
� NO se admiten las operaciones entre dos operandos
ubicados en memoria
Arquitectura software x86-16bits
36/47©
R
af
ae
l R
ic
o 
Ló
pe
z
4. Formato de instrucciones
4.1. Formato general
• Campo REG:
DIBH111
SIDH110
BPCH101
SPAH100
BXBL011
DXDL010
CXCL001
AXAL000
w = 1w = 0REG
19
Arquitectura software x86-16bits
37/47©
R
af
ae
l R
ic
o 
Ló
pe
z
4. Formato de instrucciones
4.1. Formato general
• Campo MOD y R/M:
MOD = 11 Cálculo de la dirección efectiva
[BX]+D16
[BP]+D16
[DI]+D16
[SI]+D16
[BP]+[DI]+D16
[BP]+[SI]+D16
[BX]+[DI]+D16
[BX]+[SI]+D16
MOD = 10
[BX]+D8
[BP]+D8
[DI]+D8
[SI]+D8
[BP]+[DI]+D8
[BP]+[SI]+D8
[BX]+[DI]+D8
[BX]+[SI]+D8
MOD = 01
[BX]
dirección
[DI]
[SI]
[BP]+[DI]
[BP]+[SI]
[BX]+[DI]
[BX]+[SI]
MOD = 00
DIBH111
SIDH110
BPCH101
SPAH100
BXBL011
DXDL010
CXCL001
AXAL000
w = 1w = 0R/M
Arquitectura software x86-16bits
38/47©
R
af
ae
l R
ic
o 
Ló
pe
z
4. Formato de instrucciones
4.1. Formato general
� Registros implicados en el cálculo de direcciones (se 
incluye el registro de segmento por defecto):
DS
SS
DS
SS
DS
Reg. de segmento
DSx16+[BX]111
SSx16+[BP]110
DSx16+[DI]101
DSx16+[SI]100
SSx16+[BP]+[DI]011
SSx16+[BP]+[SI]010
DSx16+[BX]+[DI]001
DSx16+[BX]+[SI]000
Dirección efectivaR/M
20
Arquitectura software x86-16bits
39/47©
R
af
ae
l R
ic
o 
Ló
pe
z
4. Formato de instrucciones
4.
1.
 F
or
m
at
o 
ge
ne
ra
l
Arquitectura software x86-16bits
40/47©
R
af
ae
l R
ic
o 
Ló
pe
z
4. Formato de instrucciones
4.
1.
 F
or
m
at
o 
ge
ne
ra
l
21
Arquitectura software x86-16bits
41/47©
R
af
ae
l R
ic
o 
Ló
pe
z
4. Formato de instrucciones
• Leyenda:
� reg8, reg16: registros de tamaño byte o palabra
� inm8, inm16: inmediatos de tamaño byte o palabra
� r/m: operando registro o memoria
� m: operando memoria
� d8, d16: desplazamiento
� b: base
� b:d16 es una dirección completa de memoria
� ‘→→→→’: se escribe
� ‘:’: no se escribe
Arquitectura software x86-16bits
42/47©
R
af
ae
l R
ic
o 
Ló
pe
z
4. Formato de instrucciones
4.2. Formato especial con campo de extensión
• Se necesitan 2 bytes para determinar la operación
no determina la operación
desplazamiento y/o dato inmediato
(determina la operación)campo de
extensión
byte 1 byte 2 byte 4byte 3 byte 6byte 5
operando registro o memoria
código de operación
22
Arquitectura software x86-16bits
43/47©
R
af
ae
l R
ic
o 
Ló
pe
z
4. Formato de instrucciones
4.2. Formato especial con campo de extensión
� Los campos MOD y R/M dan lugar al operando
� El campo REG da el código de operación completando 
el campo de extensión
Grupo IIFE, FF
Grupo IF6, F7
DesplazamientosD0, D1, D2, D3
Inmediatos80, 81, 82, 83
GRUPOCAMPO DE EXTENSIÓN
Arquitectura software x86-16bits
44/47©
R
af
ae
l R
ic
o 
Ló
pe
z
4. Formato de instrucciones
4.3. Formato especial con prefijo
byte 1 byte 2byte 0
prefijo
Sincronización con coprocesadorLOCK
REPNZ/REPNE
REPZ/REPE Repetición de instrucción de cadena
REP
ES
SS
DS
Modifican la base por defecto
CS
EfectoPrefijo
23
Arquitectura software x86-16bits
45/47©
R
af
ae
l R
ic
o 
Ló
pe
z
4. Formato de instrucciones
• Ejemplo:
� MOV AX,[BX][SI]
�DSx16+[BX][SI]
� CS:MOV AX,[BX][SI]
�CSx16+[BX][SI]
Arquitectura software x86-16bits
46/47©
R
af
ae
l R
ic
o 
Ló
pe
z
4. Formato de instrucciones
• EJEMPLO: La instrucción MOV BL,AL mueve el byte
contenido en el registro fuente AL al registro destino BL. 
¿Cuál es el código máquina de la instrucción sabiendo 
que el código de operación es 1000102?
� SOLUCION: En el primer byte los primeros 6 bits 
especifican la operación y deben ser:
CODIGO DE OPERACION = 1000102
� El bit D indica si el registro que señala el campo REG del 
2º byte es el operando fuente o el destino. Codificaremos 
el registro AL en el campo REG y, por tanto, D será 0
� El bit W será 0 para indicar una operación de tamaño byte
� PRIMER BYTE = 1000 10002 = 88h
24
Arquitectura software x86-16bits
47/47©
R
af
ae
l R
ic
o 
Ló
pe
z
4. Formato de instrucciones
� En el segundo byte, REG indica el operando fuente que 
es AL. Su código es: REG = 000
� Como el segundo operando es también un registro, 
MOD debe valer 11. El campo R/M debe especificar que 
el registro destino es BL y su códificación es 011. Esto 
da:
MOD = 11 R/M = 011
� SEGUNDO BYTE = 1100 00112 = C3h
� Y el código hexadecimal completo para la instrucción 
es:
MOV BL,AL = 88 C3h
laboratorio/Teoría de laboratorio/02 - Repertorio de instrucciones x86-16bits.pdf
1
Repertorio de instrucciones x86-16bits
1/145©
R
af
ae
l R
ic
o 
Ló
pe
z
Índice
1. Generalidades
2. Instrucciones de transferencia
3. Instrucciones de proceso
4. Instrucciones de bifurcación
5. Otras instrucciones
Repertorio de instrucciones x86-16bits
2/145©
R
af
ae
l R
ic
o 
Ló
pe
z
1. Generalidades
• No se pueden realizar operaciones donde ambos 
operandos residan en memoria
• Las instrucciones de transferencia NO ACCEDEN al 
registro de estado
• Las instrucciones de proceso ESCRIBEN el registro 
de estado
• Las instrucciones de salto LEEN el registro de estado
2
Repertorio de instrucciones x86-16bits
3/145©
R
af
ae
l R
ic
o 
Ló
pe
z
1. Generalidades
• Existen 2 tipos de sintaxis
� INTEL
� ATT
• Nosotros usaremos la sintaxis INTEL
� El primer operando es el DESTINO
� El segundo operando es el FUENTE
• En las operaciones de proceso, el operando DESTINO 
pierde su valor inicial siendo reemplazado por el 
resultado
Repertorio de instrucciones x86-16bits
4/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2. Instrucciones de transferencia
2. Instrucciones de transferencia
Índice
1. Movimiento de datos
2. Extensión de signo
3. Transfiriendo punteros
4. Transferencias con la pila
5. Entrada/salida
3
Repertorio de instrucciones x86-16bits
5/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.1. Movimiento de datos
MOV {reg/mem},{reg/mem/inmediato}
• Trasfiere un byte o una palabra desde el operando 
fuente al destino
op. destino ←←←← op. fuente
• El operando fuente no se destruye
• Ambos operandos deben ser del mismo tamaño
Repertorio de instrucciones x86-16bits
6/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.1. Movimiento de datos
• Ejemplo:
MOV AX,FFFF ; AX = FFFF h
MOV BX,1234 ; BX = 1234 h
MOV AX,BX ; AX = 1234 h
; BX = 1234 h
4
Repertorio de instrucciones x86-16bits
7/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.1. Movimiento de datos
• Restricciones:
� No se pueden mover datos entre dos elementos de 
memoria; hay que utilizar un registro intermedio
MOV AX, mem1
MOV mem2, AX
� No se puede mover un inmediato a un registro de 
segmento; hay que usar un registro intermedio
MOV AX, 1234h ; AX = 1234h
MOV DS, AX ; DS = 1234h
� El registro de segmento CS no puede ser destino
Repertorio de instrucciones x86-16bits
8/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.1. Movimiento de datos
XCHG {reg/mem},{reg/mem}
• Intercambia el contenido de los operandos
• Es útil para evitar el uso de una variable temporal
• Ejemplo:
MOV AX,FFFF ; AX = FFFF h
MOV BX,0 ; BX = 0000
h
XCHG AX,BX ; AX = 0000 h
; BX = FFFF h
5
Repertorio de instrucciones x86-16bits
9/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.1. Movimiento de datos
XLAT memoria
• Memoria es un desplazamiento sobre DS. El puntero 
a memoria será:
DS:memoria
prefijo: XLAT memoria
• Ahora el segmento viene dado por el prefijo.
El puntero a memoria será:
prefijo:memoria
Repertorio de instrucciones x86-16bits
10/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.1. Movimiento de datos
• La instrucción XLAT carga en AL el valor de una tabla 
de memoria
• Es útil para traducir entre sistemas de codificación
• La tabla debe ser de bytes y no puede tener más de 
256 bytes; el primero tiene desplazamiento 0
• La base de la tabla se coloca en BX y el puntero en AL
AL ←←←← [BX+AL]
6
Repertorio de instrucciones x86-16bits
11/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.1. Movimiento de datos
• Ejemplo:
.DATA
TABLA DB 1,2,3,4,5,6,7 ;declaración
.CODE
MOV BX,OFFSET TABLA ;carga BX
MOV AL,4 ;5º valor
XLAT TABLA ;AL = 5
• Esto es equivalente a:
MOV AL,TABLA[4]
Repertorio de instrucciones x86-16bits
12/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.1. Movimiento de datos
• Ejemplo:
� Esta tabla permite traducir
códigos ASCII a EBCDIC
� El código ASCII sirve de
índice
�Por ejemplo, el índice 32
apunta al “2” en EBCDIC
F5TABLA[35]
F4TABLA[34]
F3TABLA[33]
F2TABLA[32]
F1TABLA[31]
F0TABLA[30]
XXTABLA[1]
XXTABLA[0]
valordirección
7
Repertorio de instrucciones x86-16bits
13/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.1. Movimiento de datos
LAHF
• Carga los 8 bits más bajos del registro de estado 
(banderas de estado) en AH
AH ←←←← banderas de estado (bits 0, 2, 4, 6, 7)
SAHF
• Recupera las banderas de estado desde AH
banderas de estado ←←←← AH
Repertorio de instrucciones x86-16bits
14/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.1. Movimiento de datos
• Las instrucciones de transferencia de las banderas de 
estado se suelen usar para mover el estado entre 
coprocesadores
• Para manejar el conjunto completo del registro de 
estado se deben usar instrucciones de transferencia 
con la pila
�PUSHF
�POPF
8
Repertorio de instrucciones x86-16bits
15/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.2. Extensión de signo
• Antes de poder mover datos de diferente tamaño es 
necesario extender adecuadamente el signo
• El procedimiento es distinto si el número es 
considerado con signo o sin él, pero es el 
programador el que debe tenerlo en cuenta ya que la 
máquina no advierte la diferencia
� Cuando el valor tiene signo se usa CBW o CWD
� Cuando el valor es sin signo se rellena con ceros
Repertorio de instrucciones x86-16bits
16/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.2. Extensión de signo
CBW
• Convertir byte en palabra
• Copia el bit 7 del registro AL en todo el registro AH
CWD
• Convertir palabra en doble palabra
• Copia el bit 15 del registro AX en el registro DX
� Doble palabra ���� DX:AX
9
Repertorio de instrucciones x86-16bits
17/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.2. Extensión de signo
• Ejemplo con signo:
.DATA
mem8 DB –5 ;declaración
mem16 DW –5 ;declaración
.CODE
MOV AL, mem8 ;carga AL = FBh
CBW ;AX = FFFBh (-5)
MOV AX, mem16 ;carga AX = FFFBh
CWD ;DX = FFFFh
;DX:AX = (-5)
Repertorio de instrucciones x86-16bits
18/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.2. Extensión de signo
• Ejemplo sin signo:
.DATA
mem8 DB 251 ;declaración (FBh)
mem16 DW 65531 ;declaración (FFFBh)
.CODE
MOV AL, mem8 ;carga AL = FBh(251)
XOR AH, AH ;AX = 00FBh (251)
MOV AX, mem16 ;carga AX = FFFBh
XOR DX, DX ;DX:AX = 0000 FFFBh
10
Repertorio de instrucciones x86-16bits
19/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.3. Transfiriendo punteros
• Instrucciones para cargar punteros en registros
• Los punteros pueden ser
� Near ���� dentro de un segmento; no exceden los 64KB
• LEA
� Far ���� entre segmentos; exceden los límites del 
segmento y se requiere una base y un desplazamiento
• LES
• LDS
Repertorio de instrucciones x86-16bits
20/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.3. Transfiriendo punteros
LEA {reg},{mem}
• Carga un puntero near en un registro; el puntero es la 
dirección efectiva de la posición de memoria 
especificada en el operando fuente
� El operando destino puede ser cualquier registro de 
propósito general
� No están permitidos los registros de segmento
� El operando fuente es una posición de memoria 
especificada por cualquier modo de direccionamiento
11
Repertorio de instrucciones x86-16bits
21/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.3. Transfiriendo punteros
• Ejemplo:
• Transfiere el desplazamiento del operando fuente al 
registro destino
LEA AX, 1234[SI] ;si SI = 1000h
;AX = 1234 + 1000
;AX = 2234h
Repertorio de instrucciones x86-16bits
22/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.3. Transfiriendo punteros
• Advertencias respecto a LEA:
LEA DX,cadena
MOV DX,OFFSET cadena
• Dan el mismo resultado pero es más rápida la 
segunda ya que la posición de cadena en el área de 
datos es conocida en tiempo de ensamblado
• Usaremos LEA cuando queramos transferir un 
desplazamiento no conocido en tiempo de diseño:
LEA DX,cadena[SI]
MOV DX,OFFSET cadena[SI] ;no funciona
12
Repertorio de instrucciones x86-16bits
23/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.3. Transfiriendo punteros
LES {reg},{mem}
• Copia un puntero far (32 bits) guardado en el 
operando fuente al registro especificado en el 
operando destino y al registro ES
�ES ���� salva la base
� Registro destino ���� salva el desplazamiento (no se 
aceptan los registros de segmento)
• El operando fuente es una posición de memoria de 
tamaño doble palabra (32 bits)
Repertorio de instrucciones x86-16bits
24/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.3. Transfiriendo punteros
• Los punteros en memoria se salvan por este orden
� Palabra de menor peso ���� desplazamiento
� Palabra de mayor peso ���� base
• Ejemplo:
PTR ���� 1234:5678
LES DI,PTR ;DI = 5678h
;ES = 1234h
12PTR[3]
34PTR[2]
56PTR[1]
78PTR[0]
valordirección
13
Repertorio de instrucciones x86-16bits
25/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.3. Transfiriendo punteros
LDS {reg},{mem}
• Copia un puntero far (32 bits) guardado en el 
operando fuente al registro especificado en el 
operando destino y al registro DS
� DS ���� salva la base
� Registro destino ���� salva el desplazamiento (no se 
aceptan los registros de segmento)
• El operando fuente es una posición de memoria de 
tamaño doble palabra (32 bits)
Repertorio de instrucciones x86-16bits
26/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.3. Transfiriendo punteros
• Ejemplo:
PTR ���� 1234:5678
LDS SI,PTR ;SI = 5678h
;DS = 1234h
12PTR[3]
34PTR[2]
56PTR[1]
78PTR[0]
valordirección
14
Repertorio de instrucciones x86-16bits
27/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.3. Transfiriendo punteros
• Ejemplo:
.DATA
cadena DB “Hola mundo” ;cadena
pcadena DD cadena ;salvo el puntero
array DB 100 DUP(?) ;reservo array
parray DD array
.CODE
LES DI,pcadena ;ES:DI����cadena
LDS SI,parray ;DS:SI����array
Repertorio de instrucciones x86-16bits
28/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.4. Transferencias con la pila
• La pila es un área de memoria de acceso secuencial 
tipo LIFO gobernada por el puntero SP y usada para 
almacenar datos temporalmente:
� Paso de parámetros a procedimientos
� Variables locales a procedimientos
� Salvaguarda de registros cuando deben ser utilizados 
por otra variable
• En el x86-16bits el SP comienza en las posiciones más 
altas y avanza hacia las más bajas
15
Repertorio de instrucciones x86-16bits
29/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.4. Transferencias con la pila
• Las instrucciones que trabajan con la pila sólo 
especifican un operando ya que el otro es implícito
(la 
cima de la pila referenciada por SP)
• Estas instrucciones también actúan de manera 
implícita sobre el puntero de pila (SP)
� Decrementándolo cuando introducen datos
� Incrementándolo cuando sacan datos
• Las transferencias son de tamaño palabra (16 bits)
� El SP se actualiza de 2 en 2
Repertorio de instrucciones x86-16bits
30/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.4. Transferencias con la pila
PUSH {reg/mem}
• Poner palabra en la pila
• Decrementa el SP en 2 y coloca el operando en la pila
� El operando nunca puede ser CS
SP ←←←← SP – 2
SS:SP ←←←← operando
bajas
posiciones
altas
AL
←←←← SPAH
←←←← SP
después de
PUSH AX
antes de
PUSH AX
16
Repertorio de instrucciones x86-16bits
31/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.4. Transferencias con la pila
• Ejemplo:
PUSH AX ;pone AX en la cima de la pila
• Es equivalente a:
SUB SP,2 ; SP ←←←← SP - 2
MOV [SP],AX ; SS:SP ←←←← AX
Repertorio de instrucciones x86-16bits
32/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.4. Transferencias con la pila
POP {reg/mem}
• Sacar palabra de la pila
• Copia el dato de la pila en el operando especificado e 
incrementa el SP en 2
� El operando nunca puede ser CS
operando ←←←← SS:SP
SP ←←←← SP + 2
bajas
posiciones
altas
Byte L
←←←← SPByte H
←←←← SP
después de
POP AX
antes de
POP AX
17
Repertorio de instrucciones x86-16bits
33/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.4. Transferencias con la pila
• Ejemplo:
POP AX ;AX ���� valor cima de la pila
• Es equivalente a:
MOV AX,[SP] ; AX ←←←← SS:SP
ADD SP,2 ; SP ←←←← SP + 2
Repertorio de instrucciones x86-16bits
34/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.4. Transferencias con la pila
PUSHF
• Transfiere el registro de estado completo a la pila
SP ←←←← SP - 2
SS:SP ←←←← reg. estado
POPF
• Carga el registro de estado completo con el contenido 
de la cima de la pila
reg. estado ←←←← SS:SP
SP ←←←← SP + 2
18
Repertorio de instrucciones x86-16bits
35/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.5. Entrada/salida
• Los mapas de memoria y de entrada/salida en máquinas 
x86-16bits son disjuntos
• Cuando se emite una dirección en el bus de direcciones 
es necesario especificar si es de memoria o de E/S
• Por esto contamos con instrucciones específicas de E/S
�IN ���� señal IO/M = 1 ���� señal RD activa
�OUT ���� señal IO/M = 1 ���� señal WR activa
También tenemos INS y 
OUTS que mueven 
áreas de memoria
Repertorio de instrucciones x86-16bits
36/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.5. Entrada/salida
IN Acc,{puerto/DX}
• Carga el acumulador con un valor leído en un puerto 
de E/S especificado por el operando fuente
� El puerto puede ser un inmediato de tamaño byte
(puertos 0 – 255)
� Por encima de este puerto hay que darlo como DX
• El tamaño de la transferencia viene dado por Acc:
� Si es AX ���� tamaño palabra
� Si es AL ���� tamaño byte
19
Repertorio de instrucciones x86-16bits
37/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.5. Entrada/salida
OUT {puerto/DX},Acc
• Escribe el contenido del acumulador en el puerto 
especificado
� El puerto puede ser un inmediato de tamaño byte
(puertos 0 – 255)
� Por encima de este puerto hay que darlo como DX
• El tamaño de la transferencia viene dado por Acc:
� Si es AX ���� tamaño palabra
� Si es AL ���� tamaño byte
Repertorio de instrucciones x86-16bits
38/145©
R
af
ae
l R
ic
o 
Ló
pe
z
2.5. Entrada/salida
• Normalmente las E/S se realizan mediante llamadas al 
S.O. (que a su vez realiza llamadas al BIOS)
� INT 21h ���� bajo D.O.S.
� API ���� bajo Windows
• Sin embargo, las instrucciones de E/S proporcionan 
un método para hacer E/S directamente
� ¡OJO! pueden provocar problemas de portabilidad
20
Repertorio de instrucciones x86-16bits
39/145©
R
af
ae
l R
ic
o 
Ló
pe
z
3. Instrucciones de proceso
3. Instrucciones de proceso
Índice
1. Operaciones lógicas
2. Desplazamientos y rotaciones
3. Suma
4. Resta
5. Multiplicación
6. División
7. Operaciones en BCD
Repertorio de instrucciones x86-16bits
40/145©
R
af
ae
l R
ic
o 
Ló
pe
z
3.1. Operaciones lógicas
• Las instrucciones lógicas realizan operaciones 
booleanas sobre bits individuales
� Cada resultado en el bit i-ésimo sólo depende de los 
bits i-ésimos de los operandos de entrada
�Son las más rápidas
� No conllevan propagaciones de acarreos, etc.
�No son función del peso (≠f(peso))
21
Repertorio de instrucciones x86-16bits
41/145©
R
af
ae
l R
ic
o 
Ló
pe
z
3.1. Operaciones lógicas
• El repertorio del x86-16bits da soporte a las 
operaciones lógicas AND, OR, XOR entre dos 
operandos (diádicas) y a la NOT de un operando 
(monádica)
001111
011001
111010
100000
NOT XX XOR YX OR YX AND YYX
monádicadiádicas
Repertorio de instrucciones x86-16bits
42/145©
R
af
ae
l R
ic
o 
Ló
pe
z
3.1. Operaciones lógicas
• Se suelen usar combinando un operando con una 
“máscara”
� La “máscara” tiene diferentes formas dependiendo de la 
operación
� Se utiliza para modificar o extraer información de unos 
bits y obviar la de otros
• Las instrucciones no han de confundirse con los 
operadores
� Las primeras operan en tiempo de ejecución
� Los segundos son órdenes para el ensamblador
� Se distinguen por el contexto
22
Repertorio de instrucciones x86-16bits
43/145©
R
af
ae
l R
ic
o 
Ló
pe
z
3.1. Operaciones lógicas
AND {reg/mem},{reg/mem/inmediato}
• Realiza la operación lógica AND
• Se puede usar para poner a cero un bit
independientemente de su valor actual
� La máscara contendrá un 0 allá donde queramos 
colocar un cero y un 1 donde queremos dejar intacto el 
bit original
Repertorio de instrucciones x86-16bits
44/145©
R
af
ae
l R
ic
o 
Ló
pe
z
3.1. Operaciones lógicas
• Ejemplo:
MOV AL, 035h ; 0011 0101
AND AL, 0FBh ;and 1111 1011
; 0011 0001
; 0011 0001
AND AL, 0F8h ;and 1111 1000
; 0011 0000
MOV AH, 7 ;servicio 7 de INT 21h
INT 21h ;entrada carácter sin eco
AND AL, 1101 1111b ;convierte a Mayúsculas
CMP AL, ‘Y’ ;¿es ‘Y’?
JE YES ;si es ‘Y’ salta a la rutina
;si no es ‘Y’ continúa
YES: : : : ;rutina
23
Repertorio de instrucciones x86-16bits
45/145©
R
af
ae
l R
ic
o 
Ló
pe
z
3.1. Operaciones lógicas
OR {reg/mem}, {reg/mem/inmediato}
• Realiza la operación lógica OR
• Se puede usar para poner a uno un bit
independientemente de su valor actual
� La máscara contendrá un 1 allá donde queramos 
colocar un 1 y un 0 donde queremos dejar intacto el bit
original
• También se usa para comparar con 0
Repertorio de instrucciones x86-16bits
46/145©
R
af
ae
l R
ic
o 
Ló
pe
z
3.1. Operaciones lógicas
• Ejemplo:
MOV AL, 035h ; 0011 0101
OR AL, 08h ;or 0000 1000
; 0011 1101
; 0011 1101
OR AL, 07h ;or 0000 0111
; 0011 1111
OR BX, BX ;¿es BX=0?
;ocupa 2B tarda 2 ciclos
JG ;BX positivo
JL ;BX negativo
;BX cero
CMP BX, 0 ;¿es BX=0?
;ocupa 3B tarda 3 ciclos
es una resta que no salva el 
resultado
24
Repertorio de instrucciones x86-16bits
47/145©
R
af
ae
l R
ic
o 
Ló
pe
z
3.1. Operaciones lógicas
XOR {reg/mem},{reg/mem/inmediato}
• Realiza la operación lógica XOR
• Se puede usar para conmutar el valor de bits 
específicos
� La máscara tendrá 1 allá donde quieras conmutar
• También se usa para poner a cero un registro
Repertorio de instrucciones x86-16bits
48/145©
R
af
ae
l R
ic
o 
Ló
pe
z
3.1. Operaciones lógicas
• Ejemplo:
MOV AL, 035h ; 0011 0101
XOR AL, 08h ;xor 0000 1000
; 0011 1101
; 0011 1101
XOR AL, 07h ;or 0000 0111
; 0011 1010
XOR CX, CX ;ocupa 2B tarda 3 ciclos
;actualiza el estado
MOV CX, 0 ;ocupa 3B tarda 4 ciclos
;NO actualiza el estado
SUB CX, CX ;ocupa 2B tarda 3 ciclos
;actualiza el estado
25
Repertorio de instrucciones x86-16bits
49/145©
R
af
ae
l R
ic
o 
Ló
pe
z
3.1. Operaciones lógicas
NOT {reg/mem}
• Complementa todos los bits del operando

Continuar navegando