Top Banner
Fundamentos del lenguaje ensamblador 235 Fundamentos del lenguaje ensamblador 4.1.-El lenguaje ensamblador y el lenguaje de máquina. Al dar una definición, en pocas palabras, de una computadora, se puede decir que se trata de un equipo para interpretar y ejecutar una secuencia de elementos de información almacenados en la memoria y realizar una serie de operaciones que estarán determinadas por la secuencia de pasos ejecutados. Las operaciones efectuadas incluyen la transformación de datos por la unidad aritmética a partir de códigos en memoria, así como la especificación de la dirección de la siguiente instrucción a ser ejecutada. La interpretación de las sucesivas instrucciones en una secuencia y su realización, constituye lo que se llama ejecución de un programa. Aquellos programas que pueden ejecutarse directamente por el microprocesador, se dice que están en lenguaje de máquina. Los programas escritos en lenguaje de máquina son muy difíciles de implementar, ello se debe a que el usuario tiene que convertir el nemotécnico que representa a la instrucción en código binario, especificar la dirección de memoria donde se encuentre la instrucción y trabajar con las variables asociadas a una o varias direcciones de memoria. 4.2.-La puesta a punto de programas en ensamblador. Para poner a punto un programa en lenguaje ensamblador hay que pasar por diferentes etapas. En la fig. 4.1 se muestra un diagrama en bloques genérico de los pasos a seguir. Fig. 4.1.- Pasos para la puesta a punto de un programa en ensamblador. PROGRAMACION EDICION ENSAMBLAJE CARGA/ENLACE PUESTA A PUNTO
61

Ensamblador

Apr 12, 2017

Download

Engineering

Omar Sánchez
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Ensamblador

Fundamentos del lenguaje ensamblador

235

Fundamentos del

lenguaje ensamblador

4.1.-El lenguaje ensamblador y el lenguaje de máquina.

Al dar una definición, en pocas palabras, de una computadora, se puede decir que se trata de un equipo

para interpretar y ejecutar una secuencia de elementos de información almacenados en la memoria y

realizar una serie de operaciones que estarán determinadas por la secuencia de pasos ejecutados. Las

operaciones efectuadas incluyen la transformación de datos por la unidad aritmética a partir de códigos en

memoria, así como la especificación de la dirección de la siguiente instrucción a ser ejecutada.

La interpretación de las sucesivas instrucciones en una secuencia y su realización, constituye lo que se

llama ejecución de un programa. Aquellos programas que pueden ejecutarse directamente por el

microprocesador, se dice que están en lenguaje de máquina.

Los programas escritos en lenguaje de máquina son muy difíciles de implementar, ello se debe a que el

usuario tiene que convertir el nemotécnico que representa a la instrucción en código binario, especificar la

dirección de memoria donde se encuentre la instrucción y trabajar con las variables asociadas a una o

varias direcciones de memoria.

4.2.-La puesta a punto de programas en ensamblador.

Para poner a punto un programa en lenguaje ensamblador hay que pasar por diferentes etapas. En la fig.

4.1 se muestra un diagrama en bloques genérico de los pasos a seguir.

Fig. 4.1.- Pasos para la puesta a punto de un programa en ensamblador.

PROGRAMACION

EDICION

ENSAMBLAJE

CARGA/ENLACE

PUESTA A PUNTO

Page 2: Ensamblador

Fundamentos del lenguaje ensamblador

236

4.2.1.-La Programación.

La programación requiere de ejercitación, experimentación y de concentración. Generalmente el costo

para el desarrollo del software en un sistema basado en microprocesador es mucho mayor que el costo

para el desarrollo del hardware.

Para el programador de microprocesadores es importante conocer, además del repertorio de instrucciones,

la arquitectura interna del procesador.

Los pasos a seguir en la programación son:

a.-)Análisis del problema: En este primer paso el programador debe cerciorarse de la información de

entrada y el resultado que se quiere producir, se establece además una relación con el hardware basada en

la capacidad de RAM y ROM demandada, el procedimiento de entrada/salida, la capacidad de la pila

(stack), las condiciones de tiempo, etc.

b.-)Diseño: Se deben desarrollar varios objetos de datos (elementos), para cada objeto habrá un conjunto

de operaciones básicas a realizar. Considere que estas operaciones existen en forma de subrutinas y

escriba un algoritmo que resuelva el problema de acuerdo a los requerimientos.

Definición de algoritmo: Es un conjunto de instrucciones que llevan a cabo una tarea en particular y debe

satisfacer los criterios de: entrada, precisión, limitación y eficacia.

Los diagramas de flujo( equivalentes al algoritmo) pueden dividirse en tres niveles:

(1).-Conceptual: Se hace una descripción general del problema, independientemente del tipo de

microprocesador (grandes bloques).

(2).-Diagramas de flujo con los algoritmos para cada una de las operaciones básicas: También

independiente del microprocesador, cada bloque del diagrama conceptual es subdividido de acuerdo al

algoritmo necesario para desarrollarlo, pensando en las operaciones que tienen que ser desarrolladas en el

bloque, fijando las acciones y la secuencia en que se van a ejecutar.

(3).- Diagrama de flujo con las instrucciones: Dependiente del microprocesador, cada símbolo en este

diagrama debe representar de una a tres instrucciones. A partir de este diagrama el programa puede ser

escrito directamente.

c.-)Análisis: Se puede elaborar un algoritmo alternativo y compararlo con el anterior.

d.-)Escribir el programa fuente: Se escribe el programa fuente.

Los elementos que identifican las partes constituyentes de una línea en ensamblador son:

DIRECCIÓN CODIGOHEX ETIQUETAS OPERADOR OPERANDOS COMENTARIOS

4.2.2.-La Edición.

El programa elaborado se edita en cualquier editor de textos que exporte en formato ASCII, obteniéndose

el archivo fuente correspondiente (típicamente con extensión .ASM ó .SCR).

Page 3: Ensamblador

Fundamentos del lenguaje ensamblador

237

4.2.3.-El Ensamblaje.

A través del mismo se depuran los errores de sintaxis, el ensamblaje se realiza sobre el lenguaje fuente

previamente elaborado. Ante la presencia de errores se debe proceder a la corrección de los mismos a

través del proceso de edición.

4.2.4.-La carga-enlace.

Ejecutada a través del enlazador, permite al usuario escribir programas en ensamblador que estén

constituidos por varios módulos. El Enlazador resuelve referencias externas y realiza reubicaciones de

direcciones, además de generar diferentes formatos de archivos. Cuando se generen errores en la

carga/enlace, deben depurarse los mismos en el editor. Debe tenerse especial cuidado en que después de

corregirse los errores, el archivo fuente debe ser nuevamente ensamblado para que el enlazador ejecute su

acción sobre el archivo objeto corregido.

Como ejemplo, veamos los pasos a seguir en la sección de programa expuesto en algoritmo 4.1,

elaborado para un microcontrolador perteneciente a la serie MCS‟51.

INICIO: MOV DPTR,#3000H ; Se define un puntero

XRL A,A ; Coloca al acumulador en cero

MOV R1,10H ; Se define un contador

LAZO: MOVX @DPTR,A ; Se llena una zona de RAM

INC DPTR ; con ceros

DJNZ R1,LAZO

CONTINUA:

Algoritmo 4.1.- Ejemplo de un programa en ensamblador para la serie MCS’51.

Una vez escrito el programa, puede ensamblarse a mano, para ello debe establecerse una dirección de

memoria de partida; utilizada como referencia para ubicar las restantes instrucciones. Si la primera

instrucción se ubica en la dirección 0000H, la segunda (XRL A,A) será ubicada en la dirección 03h

puesto que la primera instrucción ocupa 3 bytes, así se le asigna a cada instrucción una posición, tal y

como se muestra en algoritmo 4.2.

Dirección PROGRAMA 0000 INICIO: MOV DPTR,#3000H

0003 XRL A,A

0005 MOV R1,10H

0007 LAZO: MOVX @DPTR,A

0008 INC DPTR

0009 DJNZ R1,LAZO

000B CONTINUA:

Algoritmo 4.2.- Ubicación de cada código en ensamblador en memoria.

Posteriormente se verifican las longitudes de las instrucciones y las direcciones asignadas, y se está en

condiciones de construir una tabla de nombres simbólicos. La tabla de nombres o tabla de símbolos tiene

tres entradas (INICIO, LAZO y CONTINUA). Por conveniencia, se colocan en orden alfabético:

Nombre Posición CONTINUA 000B

Page 4: Ensamblador

Fundamentos del lenguaje ensamblador

238

INICIO 0000

LAZO 0007

El paso que sigue es la sustitución del nemotécnico de la instrucción por el código binario que la

representa y posteriormente se introduce el valor de los operandos, que serán valores inmediatos,

números de registro o elementos de memoria. Cuando se haga una referencia simbólica se consulta la

tabla de nombres y el valor correspondiente al símbolo en cuestión se adosa a la instrucción. El resultado

se muestra en algoritmo 4.3.

Dirección Código Programa 1 0000 90 30 00 INICIO: MOV DPTR,#3000H

2 0003 65 E0 XRL A,A

3 0005 A9 10 MOV R1,10H

4 0007 F0 LAZO: MOVX @DPTR,A

5 0008 A3 INC DPTR

6 0009 D9 FC DJNZ R1,LAZO

7 000B CONTINUA:

Algoritmo 4.3.- Códigos de operación y bytes en memoria (lenguaje de máquina).

La dificultad de escribir un programa directamente en lenguaje de máquina radica en:

a)La complejidad de seguir la pista para la ubicación de las instrucciones durante la redacción del

programa.

b)La necesidad de reubicar la dirección de salto o transferencia cuando (ante la presencia de un error) hay

que añadir instrucciones al programa.

c)El colocar una dirección a cada instrucción (sin utilizar el lenguaje simbólico) implica que para que

dicho programa funcione a partir de otra dirección de memoria es necesario direccionarlo de nuevo por

parte del programador.

Por las dificultades anteriores han sido elaborados programas traductores, capaces de llevar formas o

símbolos más comprensibles por el hombre al lenguaje de máquina.

Los lenguajes de programación que constituyen entradas a los traductores reciben el nombre de lenguaje

fuente mientras que los lenguajes producto a la traducción de un lenguaje fuente, reciben el nombre de

lenguaje objeto.

Cuando el lenguaje fuente es sólo una mera representación simbólica de la secuencia de instrucciones del

lenguaje de máquina, la traducción a realizar es simple y se dice que sólo requiere de un ensamblaje. Al

programa que realiza esta traducción se le llama ensamblador. Usualmente cada instrucción en lenguaje

ensamblador genera una instrucción en lenguaje de máquina, como se muestra en la fig. 4.2.

Figura 4.2.- El ensamblador como traductor del lenguaje fuente.

Programa en

lenguaje fuente

Ensamblador Programa en

lenguaje de máquina

Page 5: Ensamblador

Fundamentos del lenguaje ensamblador

239

Cuando el lenguaje fuente es un lenguaje de alto nivel (PASCAL, C, etc.) y el lenguaje destino es el

código de máquina, al traductor se le llama compilador.

Un ensamblador típico consta de dos pasos: el primero calcula la longitud de cada instrucción y actualiza

un puntero de posición. La tabla de símbolos también se elabora en la primera fase, disponiendo todos los

nombres y referencias simbólicas en orden alfabético. Cada nombre se coloca en la tabla tal como se

encuentra; por consiguiente, un símbolo incluido en un campo de operandos entra en la tabla si antes no

ha aparecido como nombre. En este caso, el símbolo se encontrará más allá de la posición actual. Al final

de la primera fase todos los símbolos de la tabla deben haber recibido un número de identificación. Si un

símbolo no ha sido resuelto, constituirá una referencia no completada, lo que origina errores. El

ensamblador lee después las líneas de sentencias originales una vez más, construyendo esta vez el código

en lenguaje de máquina, convirtiendo las direcciones de referencia a la memoria y otros campos con los

valores tomados del campo de operandos de la línea original o con valores simbólicos extraídos de la

tabla de símbolos.

Existe una amplia variedad de ensambladores, de hecho pueden existir diferentes ensambladores para

trabajar en un mismo microprocesador o en un mismo sistema de cómputo. No obstante, las posibilidades

de diferentes ensambladores son muy similares por lo que se analiza la comprensión sobre los principios

básicos sin entrar en detalles particulares.

4.2.5.- Las directivas del ensamblador (Pseudo instrucciones).

Cualquier ensamblador posee determinadas instrucciones que son un conjunto de operaciones no

generativas que no producen código en lenguaje de máquina y cuya función fundamental es especificar,

como parte del programa en lenguaje ensamblador, donde deben localizarse las variables y diferentes

partes del programa en la memoria RAM y ROM. A tal grupo de instrucciones se les llama directivas del

ensamblador.

Las directivas del ensamblador se clasifican en las siguientes categorías:

(a).- Control de segmento: Permite definir segmentos donde se localiza código de programa y constantes

o variables en memoria de datos.

(b).- Definición de símbolos: Permite crear símbolos que pueden usarse para representar registros,

números y direcciones.

(c).- Inicialización de memoria: Permite inicializar zona de códigos o constantes, generalmente del tipo

byte o palabras.

(d).- Reserva de memoria: Reservan espacio en memoria (generalmente en memoria de datos).

(e).- Enlace de programas: Permite ensamblar módulos de programas independientes, de forma tal que

puedan intercambiarse referencias y variables entre ellas.

(f).- Control de direcciones: Permite definir determinada zona de direcciones, donde se coloca código o

datos.

Las directivas básicas del ensamblador son:

ORG: El operando asociado con esta directiva se interpreta como una dirección (típicamente de 16 bits).

Esta define una dirección a partir de la cual será colocado el código de operación de la instrucción que

siga a la directiva. Las instrucciones serán colocadas en direcciones sucesivas hasta que se defina la

Page 6: Ensamblador

Fundamentos del lenguaje ensamblador

240

próxima directiva. Si no se utiliza, queda implícita la instrucción ORG 00H. Es una directiva de control

de direcciones.

Ejemplo 4.1:

ORG 100H

ORG RESET ; RESET puede ser una expresión absoluta o relocalizable

DS: Se utiliza para reservar bytes en memoria RAM (variables). Viene acompañada de una etiqueta que

identifica una dirección en RAM y de un número a la derecha indicador del número de bytes de datos que

deben reservarse y en los cuales no se almacenan datos después de su definición ( la directiva DSW

reserva palabras de 16 bits).

Ejemplo 4.2:

Etiqueta: DS 20 ; Etiqueta identifica la dirección a partir de la cual se reservan los bytes

; en este caso se reservan 20 bytes.

DB: La directiva de definición de bytes es utilizada para almacenar cadenas y tablas. A través de ella se le

indica al ensamblador que interprete al operando como un dígito (menor o igual a 255) que debe ser

almacenado en un byte de memoria ROM. Algunos ensambladores permiten almacenar el equivalente

ASCII de una cadena de caracteres ( la directiva DW reserva palabras de 16 bits). Es una directiva de

inicialización de memoria.

Ejemplo 4.3:

Etiqueta: DB „CADENA‟ ; El ensamblador coloca en la posición el código ASCII equivalente a la

; cadena de caracteres CADENA.

Tabla: DB 0,1,‟A‟

EQU: Permite asignar un valor a determinada etiqueta o nombre de un símbolo. Puede ser usarse para

definir operandos, registros, expresiones o direcciones. Los nombres de símbolos definidos con esta

directiva no pueden redefinirse o cambiarse. Es una directiva de definición de símbolos.

Ejemplo 4.4:

Acumulador EQU A

Contador_Max EQU 100

CODE, DATA, XDATA: Permiten asignar direcciones a determinado símbolo. Los símbolos definidos con

esta directiva no pueden redefinirse. Son directivas de control de segmento.

Ejemplo 4.5:

Reset CODE 0000h ; La dirección en memoria de programa puede ser 0000H a FFFFH

Tabla_7seg DATA 20h ; La dirección en memoria de datos puede ser 00H a FFH

Datos_ext XDATA 1000h ; Define una dirección en memoria de datos externa, puede ser

; 0000H a FFFFH.

DSEG, CSEG: Definen segmentos absolutos en memoria de datos y programa respectivamente.

Page 7: Ensamblador

Fundamentos del lenguaje ensamblador

241

Ejemplo 4.6:

CSEG AT 3000H

DSEG AT 20H

SEGMENT: Permite definir segmentos relativos, cuya posición en memoria quedará finalmente

establecida por el enlazador.

Ejemplo 4.7:

PILA SEGMENT DATA ; declara segmento

RSEG PILA ; selecciona segmento

DS 10H ; reserva 16 bytes

END: Define el final de un programa o módulo.

4.2.6.- Sistema de desarrollo KEIL.

Un sistema de desarrollo está compuesto de varios programas de aplicación que se pueden usar para crear

aplicaciones en un microcontrolador. Se puede usar el ensamblador para ensamblar un programa, el

compilador para compilar un programa en código C a un archivo objeto, y se puede usar el enlazador para

crear un módulo objeto absoluto deseable, a partir de un emulador.

Cuando se usa el KEIL, el ciclo de desarrollo de un proyecto es el mismo que un proyecto de desarrollo

de cualquier software, el cual consta de los siguientes pasos:

1.- Crear los archivos en C o ensamblador.

2.- Compilar o ensamblar los archivos fuentes.

3.- Corregir los errores en el archivo fuente.

4.- Enlazar ficheros objeto del compilador y ensamblador.

5.- Probar la eficiencia de la aplicación.

El diagrama en bloques de la figura 4.3 muestra una herramienta de desarrollo para la serie MCS‟51.

Como se muestra, los archivos se crean con Vision/51 IDE y entonces pasan al compilador C51 o el

ensamblador A51. El compilador y el ensamblador procesan los archivos fuente y crean archivos objetos

relocalizables.

El archivo objeto creado por el compilador y el ensamblador puede usarse por LIB51 (controlador de

bibliotecas) para crear una biblioteca. Una biblioteca es un conjunto de programas ordenados,

especialmente formateados de módulos objeto, que el enlazador puede procesar. Cuando el enlazador

procesa una biblioteca, sólo se utilizan los módulos objetos necesarios para la creación del programa.

Los archivos objetos creados por el compilador y el ensamblador, y los archivos de biblioteca creados por

el controlador de bibliotecas se procesan por el enlazador para crear un módulo objeto absoluto. Un

archivo o módulo objeto absoluto es un archivo objeto cuyo código no es relocalizable, ello es, los

códigos residen en localizaciones fijas.

Page 8: Ensamblador

Fundamentos del lenguaje ensamblador

242

El archivo objeto absoluto creado por el enlazador se usa para programar la ROM u otros dispositivos de

memoria. Este puede usarse, adicionalmente, con el dScope-51 (depurador/ simulador) o con un

emulador.

El depurador/ simulador dScope-51 es un programa de alto nivel que permite una depuración rápida y

fiable. El depurador contiene un simulador y un target que permite simular el 8051, incluyendo

periféricos. Definiendo configuraciones específicas, se pueden simular los atributos y periféricos que

posee la serie MCS‟51.

El RTX-51 es un sistema multitarea en tiempo real que simplifica el diseño de un sistema, la

programación y depuración (utilizada para aplicaciones complejas).

Figura 4.3.- Estructura de la herramienta de desarrollo KEIL.

Vision/51

Compilador

C51

Macro

ensamblador

A51

Biblioteca

C Controlador

de biblioteca

LIB51

Sistema de

operación en

tiempo real

RTX51

Linker BL51 para banco de códigos.

Depurador (DScope-51)

Simulador de

periférico y CPU Monitor-51

Emulador y

programación de

EPROM

Page 9: Ensamblador

Fundamentos del lenguaje ensamblador

243

Para crear un proyecto con µVision2 (ver fig. 4.4) se ejecuta Project – New Project…. El cual solicita el

nombre del archivo de proyecto. Previamente se debe crear una nueva carpeta con el icono Create New

Folder.

Si el nombre del archivo es Projecto1, µVision2 crea un nuevo archivo de proyecto con el nombre

PROJECT1.UV2 el cual contiene un target implícito y un nombre de grupo de archivos. Estos se pueden

ver en Project Window – Files.

Posteriormente, en el menú Project – Select Device for Target se selecciona el CPU a utilizar. Si está

disponible, se puede seleccionar un manual aplicando Project Window – Books.

Para crear nuevos archivos fuente se ejecuta File – New. Este abre un editor donde se puede escribir el

código fuente. El código fuente que se crea se debe adicionar al proyecto usando Add Files en Project

Window – Files.

Se pueden definir los parámetros relevantes del hardware y los componentes internos del dispositivo

seleccionado usando el comando Options for Target ( es una de las opciones más importantes del

sistema de desarrollo), ello incluye:

- Frecuencia de reloj.

- Memoria interna.

- Memoria externa, etc.

El comando Option - Build Target traslada el archivo fuente a código hexadecimal, en caso de que

existan errores, en la ventana Output Window - Build aparecerán los errores de compilación.

Después de corregir los errores de sintaxis, se procede a la puesta a punto del sistema (debugger)

utilizando las herramientas de µVision2.

Una vez que se ha concluido la puesta a punto del proyecto, se debe crear el archivo INTEL HEX con el

que se programará la EPROM interna del microcontrolador (o simulador), para ello se debe habilitar la

opción Create HEX en Options for Target - Output.

Ejemplo 4.8:

Utilizando directivas, establezca un programa a partir de la dirección 0000H. Tal programa utilizará una

constante (VALOR_CONST) cuyo valor debe ser 10H. Establezca tres tablas, una a partir de la dirección

300H, una en segmento relativo y otra en 500H respectivamente, almacenando valores como bytes,

palabras y caracteres. Defina una subrutina a partir de la dirección 600H y reserve valores en RAM (a

partir de 20H) de la siguiente forma: una variable (VAR) de 1 byte de longitud y una cadena de 10 bytes.

Solución:

NAME EJEMPLO_48

VALOR_CONST EQU 10H ; se define una constante

RESET CODE 0000H ; define dirección de código de inicio

CSEG AT 300H ; en memoria de programa (300H)

Tabla_1: DB 04h ; Se definen bytes a partir de 300H

DB 05h

DB 0ffh

Page 10: Ensamblador

Fundamentos del lenguaje ensamblador

244

Codigo_tabla2 SEGMENT CODE ; En memoria de programa, relocalizable.

RSEG Codigo_tabla2

Tabla_2:

DW 4025h

DW 0ff03h

DW 450Eh ;

CSEG AT 500h ; en memoria de programa (500H)

Tabla_3:

DB 'CADENA DE CARACTERES' ; Se define cadena que será codificada en ASCII

DSEG AT 20H ; reserva variable

VAR:

DS 1 ; 1 byte en la dirección 20h

CADENA:

DS 10D ; Se reservan 10 bytes

; Se define la dirección de inicio del programa

CSEG AT RESET ; dirección absoluta en memoria de programa

CALL SUBRUTINA ; Identificando al programa

; Dirección de la subrutina a partir de la 600H

CSEG AT 600H

SUBRUTINA:

MOV A,VALOR_CONST;

MOV VAR,A;

RET;

END ; Fin del programa

Figura 4.4.- Detalle del depurador de KEIL en el sistema Vision-2.

Page 11: Ensamblador

Fundamentos del lenguaje ensamblador

245

El ensamblador generaría el siguiente archivo .LST:

A51 MACRO ASSEMBLER EJEMPLO_48

MACRO ASSEMBLER A51 V6.02

OBJECT MODULE PLACED IN .\ejemplo_48.OBJ

ASSEMBLER INVOKED BY: C:\KEIL\C51\BIN\A51.EXE .\ejemplo_48.asm SET(SMALL)

LOC OBJ LINE SOURCE

1 NAME EJEMPLO_1

0010 2 VALOR_CONST EQU 10H

0000 3 RESET CODE 0000H

4

---- 5 CSEG AT 300H

0300 04 6 Tabla_1: DB 04h

0301 05 7 DB 05h

0302 FF 8 DB 0ffh

9

10 Codigo_tabla2 SEGMENT CODE

---- 11 RSEG Codigo_tabla2

0000 12 Tabla_2:

0000 4025 13 DW 4025h

0002 FF03 14 DW 0ff03h

0004 450E 15 DW 450Eh ;

16

---- 17 CSEG AT 500h

0500 18 Tabla_3:

0500 43414445 19 DB 'CADENA DE CARACTERES'

0504 4E412044

0508 45204341

050C 52414354

0510 45524553

20

---- 21 DSEG AT 20H

0020 22 VAR:

0020 23 DS 1

24

0021 25 CADENA:

0021 26 DS 10D

27

28

29

---- 30 CSEG AT RESET

0000 D100 31 CALL SUBRUTINA

32

33

---- 34 CSEG AT 600H

0600 35 SUBRUTINA:

0600 E510 36 MOV A,VALOR_CONST;

0602 F520 37 MOV VAR,A;

0604 22 38 RET;

39

40

41 END

Page 12: Ensamblador

Fundamentos del lenguaje ensamblador

246

XREF SYMBOL TABLE LISTING

---- ------ ----- -------

N A M E T Y P E V A L U E ATTRIBUTES / REFERENCES

CADENA . . . . . . D ADDR 0021H A 25#

CODIGO_TABLA2. . . C SEG 0006H REL=UNIT 10# 11

EJEMPLO_1. . . . . N NUMB ----- 1

RESET. . . . . . . C ADDR 0000H A 3# 30

SUBRUTINA. . . . . C ADDR 0600H A 31 35#

TABLA_1. . . . . . C ADDR 0300H A 6#

TABLA_2. . . . . . C ADDR 0000H R SEG=CODIGO_TABLA2 12#

TABLA_3. . . . . . C ADDR 0500H A 18#

VALOR_CONST. . . . N NUMB 0010H A 2# 36

VAR. . . . . . . . D ADDR 0020H A 22# 37

REGISTER BANK(S) USED: 0

ASSEMBLY COMPLETE. 0 WARNING(S), 0 ERROR(S)

Nótese como la directiva en ensamblador:

Codigo_tabla2 SEGMENT CODE ; En memoria de programa, relocalizable.

RSEG Codigo_tabla2

ha generado bytes en memoria de programa que coinciden con el programa en RESET, lo anterior lo

resuelve el enlazador o a través de la definición de direcciones absolutas.

4.2.7.-El enlazador( Linker).

El enlazador es una herramienta muy útil cuando se trabajan programas muy largos que se realizan a

partir de varias secciones de código o subprogramas. Su función fundamental es aceptar varios módulos

objetos generados a partir del ensamblador, resolver las referencias a variables externas, incorporar

subrutinas a partir de determinada biblioteca y cargar cada módulo objeto en cualquier lugar de memoria

que se desee. Si el algoritmo 4.1 se quisiera definir a partir de la dirección 4000H, resulta:

PUNTERO EQU 4000H

2 4000 90 30 00 INICIO: MOV DPTR,PUNTERO

3 4003 65 E0 XRL A,A

4 4005 A9 10 MOV R1,10H

5 4007 F0 LAZO: MOVX @DPTR,A

6 4008 A3 INC DPTR

7 4009 D9 FC DJNZ R1,LAZO

8 400B CONTINUA:

Nótese como las direcciones de la tabla de símbolos cambian por la adición de la dirección de inicio

4000H:

Nombre Posición 8 CONTINUA 400B

2 INICIO 4000

5 LAZO 4007

Nótese además como los valores definidos a partir de directivas absolutas (EQU) no cambian. Los

símbolos y direcciones que cambian cuando el programa es ubicado en una nueva dirección se llaman

direcciones y símbolos relocalizables.

Page 13: Ensamblador

Fundamentos del lenguaje ensamblador

247

A partir de los archivos objetos generados por el ensamblador, el enlazador procesa los mismos y genera

los siguientes archivos:

(a).- Archivo listado (.LST): Contiene información acerca de cada paso ejecutado en el proceso de enlace

y localización de módulos, tabla de códigos localizados en memoria, lista de segmentos y símbolos y

referencias cruzadas generadas por las directivas PUBLIC y EXTERN.

(b).- Archivo objeto (.OBJ): Es utilizado por el depurador o debugger en la fase de depuración del

programa.

(c).- Archivo hexadecimal (.HEX): Es el resultado de la conversión del archivo objeto en hexadecimal,

creando un archivo con el formato Intel HEX para la programación de la ROM interna o externa del

sistema microcomputador.

Para facilitar el trabajo con el enlazador, un posible formato para la construcción de módulos objeto se

muestra a continuación:

-----------------------------------------------

; Importar símbolos externos

-----------------------------------------------

; Exportar símbolos a otros módulos

-----------------------------------------------

; Declaración de segmentos y variables

-----------------------------------------------

; Declaración de constantes

-----------------------------------------------

; Programa en ensamblador

-----------------------------------------------

Ejemplo 4.9:

Como ejemplos de como trabaja el enlazador, analicemos los programas( PROG_PRIN y

SUMA_MULTIPLE) que se muestran a continuación:

NAME PRINCIPAL

;Este programa llenara dos zonas de

; RAM para ser sumadas

; Biblioteca de simbolos externos

EXTRN CODE (SUMARA) ; módulo definido externamente

PUBLIC DIR_DATOS_A ; variables globales

PUBLIC DIR_DATOS_B

PUBLIC CANT_DATOS

; Define zona de memoria de datos

DIR_DATOS_A DATA 40H

DS 10D;

DSEG AT 50H

DIR_DATOS_B:

DS 10D;

Page 14: Ensamblador

Fundamentos del lenguaje ensamblador

248

; Constante

CANT_DATOS EQU 0AH

CSEG AT 00H

RESET:

MOV R1,#DIR_DATOS_A ; Se inicializa punteros

MOV R0,#DIR_DATOS_B

MOV R3,#CANT_DATOS ; Se inicializa contador

LLENA:

MOV @R1,#03 ; Se llena zona de datos

MOV @R0,#05

INC R0

INC R1

DJNZ R3,LLENA

CALL SUMARA

END

La subrutina, como módulo independiente, puede crearse como sigue:

NAME SUMA_MULTIPLE

; Sumara datos en multiple precision

; Biblioteca de simbolos externos

EXTRN DATA (DIR_DATOS_A)

EXTRN DATA (DIR_DATOS_B)

EXTRN NUMBER (CANT_DATOS)

PUBLIC SUMARA

SUMA_MULTIPLE SEGMENT CODE

RSEG SUMA_MULTIPLE

SUMARA:

MOV R0,#DIR_DATOS_B ; Se definen los datos inicializados

MOV R1,#DIR_DATOS_A ; en programa externo

MOV R3,#CANT_DATOS

CLR CY

CONT:

MOV A,@R0

ADDC A,@R1

MOV @R1,A

INC R0

INC R1

DJNZ R3,CONT

RET

END

El resultado que genera el ensamblador sería, para el programa principal:

MACRO ASSEMBLER A51 V6.02

OBJECT MODULE PLACED IN .\principal.OBJ

ASSEMBLER INVOKED BY: C:\KEIL\C51\BIN\A51.EXE .\principal.asm SET(SMALL) DEBUG EP

LOC OBJ LINE SOURCE

1 NAME PRINCIPAL

Page 15: Ensamblador

Fundamentos del lenguaje ensamblador

249

2 ;Este programa llenara dos zonas de

3 ; RAM para ser sumadas

4

5 ; Biblioteca de simbolos externos

6

7 EXTRN CODE (SUMARA)

8 PUBLIC DIR_DATOS_A

9 PUBLIC DIR_DATOS_B

10 PUBLIC CANT_DATOS

11

12 ; Define zona de memoria de datos

0040 13 DIR_DATOS_A DATA 40H

0000 14 DS 10D;

15

---- 16 DSEG AT 50H

0050 17 DIR_DATOS_B:

0050 18 DS 10D;

19

20 ; Constante

000A 21 CANT_DATOS EQU 0AH

22

---- 23 CSEG AT 00H

0000 24 RESET:

0000 7940 25 MOV R1,#DIR_DATOS_A ; Se inicializa punteros

0002 7850 26 MOV R0,#DIR_DATOS_B

0004 7B0A 27 MOV R3,#CANT_DATOS ; Se inicializa contador

0006 28 LLENA:

0006 7703 29 MOV @R1,#03 ; Se llena zona de datos

0008 7605 30 MOV @R0,#05

000A 08 31 INC R0

000B 09 32 INC R1

000C DBF8 33 DJNZ R3,LLENA

000E 120000 F 34 CALL SUMARA

35 END

SYMBOL TABLE LISTING

------ ----- -------

N A M E T Y P E V A L U E ATTRIBUTES

CANT_DATOS . . . . N NUMB 000AH A

DIR_DATOS_A. . . . D ADDR 0040H A

DIR_DATOS_B. . . . D ADDR 0050H A

LLENA. . . . . . . C ADDR 0006H A

PRINCIPAL. . . . . N NUMB -----

RESET. . . . . . . C ADDR 0000H A

SUMARA . . . . . . C ADDR ----- EXT

REGISTER BANK(S) USED: 0

ASSEMBLY COMPLETE. 0 WARNING(S), 0 ERROR(S)

El resultado del programa SUMA_MÚLTIPLE, después del proceso de ensamblaje sería:

MACRO ASSEMBLER A51 V6.02

OBJECT MODULE PLACED IN .\secundario.OBJ

ASSEMBLER INVOKED BY: C:\KEIL\C51\BIN\A51.EXE .\secundario.asm SET(SMALL) DEBUG EP

Page 16: Ensamblador

Fundamentos del lenguaje ensamblador

250

LOC OBJ LINE SOURCE

1 NAME SUMA_MULTIPLE

2 ; Sumara datos en multiple precision

3

4 ; Biblioteca de simbolos externos

5 EXTRN DATA (DIR_DATOS_A)

6 EXTRN DATA (DIR_DATOS_B)

7 EXTRN NUMBER (CANT_DATOS)

8 PUBLIC SUMARA

9

10 SUMA_MULTIPLE SEGMENT CODE

---- 11 RSEG SUMA_MULTIPLE

12

0000 13 SUMARA:

0000 7800 F 14 MOV R0,#DIR_DATOS_B ; Se definen datos inicializados

0002 7900 F 15 MOV R1,#DIR_DATOS_A ; en programa externo

0004 7B00 F 16 MOV R3,#CANT_DATOS

0006 C2D7 17 CLR CY

0008 18 CONT:

0008 E6 19 MOV A,@R0

0009 37 20 ADDC A,@R1

000A F7 21 MOV @R1,A

000B 08 22 INC R0

000C 09 23 INC R1

000D DBF9 24 DJNZ R3,CONT

000F 22 25 RET

26 END

SYMBOL TABLE LISTING

------ ----- -------

N A M E T Y P E V A L U E ATTRIBUTES

CANT_DATOS . . . . N ADDR ----- EXT

CONT . . . . . . . C ADDR 0008H R SEG=SUMA_MULTIPLE

El resultado del enlace entre ambos módulos resulta en el siguiente archivo generado por el enlazador:

BL51 BANKED LINKER/LOCATER V4.02

BL51 BANKED LINKER/LOCATER V4.02, INVOKED BY:

C:\KEIL\C51\BIN\BL51.EXE principal.obj, secundario.obj TO enlace RAMSIZE (256)

INPUT MODULES INCLUDED:

principal.obj (PRINCIPAL)

secundario.obj (SUMA_MULTIPLE)

LINK MAP OF MODULE: enlace (PRINCIPAL)

TYPE BASE LENGTH RELOCATION SEGMENT NAME

-----------------------------------------------------

* * * * * * * D A T A M E M O R Y * * * * * * *

REG 0000H 0008H ABSOLUTE "REG BANK 0"

0008H 0048H *** GAP ***

Page 17: Ensamblador

Fundamentos del lenguaje ensamblador

251

DATA 0050H 000AH ABSOLUTE

* * * * * * * C O D E M E M O R Y * * * * * * *

CODE 0000H 0011H ABSOLUTE

CODE 0011H 0010H UNIT SUMA_MULTIPLE

SYMBOL TABLE OF MODULE: enlace (PRINCIPAL)

VALUE TYPE NAME

----------------------------------

------- MODULE PRINCIPAL

N:000AH PUBLIC CANT_DATOS

D:0040H PUBLIC DIR_DATOS_A

D:0050H PUBLIC DIR_DATOS_B

C:0006H SYMBOL LLENA

N:0000H SYMBOL PRINCIPAL

C:0000H SYMBOL RESET

C:0000H LINE# 25

C:0002H LINE# 26

C:0004H LINE# 27

C:0006H LINE# 29

C:0008H LINE# 30

C:000AH LINE# 31

C:000BH LINE# 32

C:000CH LINE# 33

C:000EH LINE# 34

------- ENDMOD PRINCIPAL

------- MODULE SUMA_MULTIPLE

C:0011H SEGMENT SUMA_MULTIPLE

C:0011H PUBLIC SUMARA

C:0019H SYMBOL CONT

B:00D0H.7 SYMBOL CY

C:0011H LINE# 14

C:0013H LINE# 15

C:0015H LINE# 16

C:0017H LINE# 17

C:0019H LINE# 19

C:001AH LINE# 20

C:001BH LINE# 21

C:001CH LINE# 22

C:001DH LINE# 23

C:001EH LINE# 24

C:0020H LINE# 25

------- ENDMOD SUMA_MÚLTIPLE

INTER-MODULE CROSS-REFERENCE LISTING

------------------------------------

NAME . . . . USAGE MODULE NAMES

----------------------------------

CANT_DATOS . NUMB; PRINCIPAL SUMA_MULTIPLE

DIR_DATOS_A. DATA; PRINCIPAL SUMA_MULTIPLE

DIR_DATOS_B. DATA; PRINCIPAL SUMA_MULTIPLE

SUMARA . . . CODE; SUMA_MULTIPLE PRINCIPAL

LINK/LOCATE RUN COMPLETE. 0 WARNING(S), 0 ERROR(S)

Page 18: Ensamblador

Fundamentos del lenguaje ensamblador

252

El programa PROG_PRIN utiliza dos direcciones de datos (DIR_DATOS_A, DIR_DATOS_B) y una

constante (CANT_DATOS) que son compartidas con la subrutina SUMA_MÚLTIPLE. A través de la

directiva PUBLIC se indica que las etiquetas (constantes) definidas a la derecha pueden ser utilizadas por

otros programas. El programa principal hace un llamado a subrutina que no está en el módulo objeto y

que es definida en otro módulo, lo que se indica con la pseudoinstrucción EXTRN.

Para la subrutina SUMA_MULTIPLE las direcciones DIR_DATOS_A, DIR_DATOS_B y la constante

CANT_DATOS serán definidas externamente. La subrutina SUMARA es PUBLIC pues es referenciada

por PROG_PRIN( un módulo externo a ella).

El enlazador cargará PROG_PRIN y a partir del último código colocará la primera instrucción de

SUMARA( la que posee un desplazamiento en el PC de 0011H). Todas las instrucciones de SUMARA

serán colocadas en direcciones desplazadas en 11h valores, en nuevas direcciones de memoria.

4.2.8.-La creación de un módulo en ensamblador.

Los módulos, como las subrutinas, deben brindar información que el usuario necesite sin necesidad de

examinar la arquitectura interna del programa, las especificaciones típicas que deben definirse son:

a)Descripción del propósito del módulo.

b)Longitud en bytes de la subrutina.

c)Lista de parámetros de entrada.

d)Lista de parámetros de salida.

e)Registros y localizaciones de memoria utilizadas (útil cuando el módulo se use como respuesta a

interrupción, donde deben salvarse todos los registros implicados), en esta última se debe definir si las

direcciones son o no relocalizables.

f)Un ejemplo de valores de las variables de salida ante la definición de variables a la entrada.

g)Definir la biblioteca de símbolos externos.

Ejemplo 4.10:

Un ejemplo de como puede definirse un módulo se expone en el siguiente programa:

NAME CONVERSION_BCD_7SEG

;****************************************************************

; Este programa permite convertir un valor en BCD *

; a su equivalente 7 segmentos *

;****************************************************************

;*BYTES QUE OCUPA EN MEMORIA: 18 BYTES *

;****************************************************************

;*PARAMETROS DE ENTRADA: DIR_DATO_BCD:direccion donde debe estar*

;* colocado el valor en BCD a convertir *

;* con formato 0NH donde N es el valor en BCD *

;****************************************************************

Page 19: Ensamblador

Fundamentos del lenguaje ensamblador

253

;*PARAMETROS DE SALIDA: Valor equivalente a 7 segmentos en *

;* DIR_DATO_BCD *

;****************************************************************

;*REGISTROS UTILIZADOS: A,R0,PC *

;****************************************************************

;*LOCALIZACION DE MEMORIA: DIR_DATO_BCD, definida por quien *

;* llame a este modulo *

;****************************************************************

;*EJEMPLO: Debe ser definido por otro modulo: *

;* PUBLIC DIR_DATO_BCD *

; DSEG AT 50H *

; DIR_DATO_BCD: *

; DS 1D; *

;* *

;* Si (50H)=03 devuelve (50H)=66h *

;* Forma de llamado: CALL BCD_7SEG *

;****************************************************************

;*NOTA: La direccion donde se coloque la tabla puede ser *

;* relocalizada, pero siempre a continuacion de RET *

;****************************************************************

EXTRN DATA (DIR_DATO_BCD)

BCD_7SEG SEGMENT CODE

RSEG BCD_7SEG

BCD_7SEG:

MOV R0,#DIR_DATO_BCD

MOV A,@R0

ADD A,#02H ; Salto 2 bytes de código (dos próximas instrucciones)

MOVC A,@A+PC

MOV @R0,A

RET

; a continuación de la instrucción RET

POSIC_TABLA SEGMENT CODE

RSEG POSIC_TABLA

dw 3344h ; posibles códigos equivalentes 7_seg

dw 5566h

dw 7788h

dw 99aah

dw 0bbcch

END

4.3.- Algunas ideas para la programación en ensamblador.

La programación en ensamblador es una tarea ardua y laboriosa, aunque algunos conceptos que se presentan

aquí pueden resultar evidentes, son útiles para la programación en ensamblador.

(a).- Establecer un registro a cero: Un registro puede ser puesto a cero a través de las instrucciones: MOV

REG,00 ó XRL REG,REG. Para la comprensión de la segunda opción debe conocerse la función OR

EXCLUSIVO.

El or exclusivo devuelve como resultado un "1" si solo uno de los operandos vale 1, como se aprecia a

continuación:

Page 20: Ensamblador

Fundamentos del lenguaje ensamblador

254

XOR 0 1

0 0 1

1 1 0

De lo anterior se deduce que el or exclusivo de un número consigo mismo es cero. Un ejemplo se muestra a

continuación:

1 0 1 0

XOR 1 1 0 0

-----------

0 1 1 0

Para colocar a cero un registro puede utilizarse también la instrucción SUB REG,REG (sustracción de un

número por el mismo).

(b).- Complementar un bit: A menudo puede ser necesario cambiar el estado de un bit( especialmente para

trabajar sobre banderas establecidas por programa o sobre terminales de puerto, como puede ser el control

de un led en un reloj digital), para ello puede utilizarse el or exclusivo. La función or exclusivo de

cualquier bit con el bit correspondiente en "1" complementa dicho bit.

Ejemplo 4.11:

Complemente el bit 1 y 5 de un valor almacenado en un registro de 8 bits:

REGISTRO X X X X X X X X

XOR 0 0 1 0 0 0 1 0

-----------------------

RESULTADO X X XcX X X X

cX

Donde Xc representa el complemento de X.

(c).- Setear un bit: Para ello es útil la función OR, la cual da como resultado un "1" si al menos uno de los

operandos es "1":

OR 0 1

0 0 1

1 1 1

Por tanto, el OR de cualquier información contenida en cualquier bit con "1" resultará un 1.

Ejemplo 4.12:

Setee los bits 1 y 5 de la información contenida en cualquier registro.

REGISTRO X X X X X X X X

OR 0 0 1 0 0 0 1 0

----------------------

RESULTADO X X 1 X X X 1 X

Nótese como la información contenida en los bits sobre los que se hace el OR con 0, mantienen su valor.

Page 21: Ensamblador

Fundamentos del lenguaje ensamblador

255

(d).- Resetear un bit: Para ello puede utilizarse la función AND, en la misma basta que uno de los

operandos sea cero para que el resultado sea cero:

AND 0 1

0 0 0

1 0 1

Ejemplo 4.13:

Coloque los bits 1 y 5 de un registro a cero.

REGISTRO X X X X X X X X

AND 1 1 0 1 1 1 0 1

------------------------

RESULTADO X X 0 X X X 0 X

Nótese como la información contenida en los bits sobre los que se hace el AND con "1" mantienen su valor.

(e).- Realizar la sustracción a través de suma: Algunos dispositivos (como algunos microcontroladores) no

poseen instrucciones de sustracción. Un método alternativo es realizar la sustracción a través de la suma,

para lo cual la operación:

MINUENDO

- SUSTRAENDO

---------------------

RESTA

Puede realizarse ejecutando los siguientes pasos:

a)Se realiza el complemento a 1 del minuendo.

b)Se le suma a la anterior operación el sustraendo.

c)Se realiza el complemento a uno del resultado.

Ejemplo 4.14:

Realice la siguiente operación:

01001001B - 00110110B

a)Se realiza el complemento a uno del minuendo:

10110110B

b)Se le suma el sustraendo:

10110110B

+00110110B

---------------

11101100B

Page 22: Ensamblador

Fundamentos del lenguaje ensamblador

256

c)Se le determina el complemento a uno del resultado:

00010011B

Y este es el resultado de la sustracción planteada.

Un problema será determinar cuándo la operación anterior no da un resultado apropiado ( préstamo en la

operación de sustracción normal). Para ello el acarreo se utiliza como indicador.

Ejemplo 4.15:

Realice la siguiente operación:

00010000B - 00100000B

a)Se realiza el complemento a uno del minuendo:

11101111B

b)Se le suma el sustraendo:

11101111B

+00100000B

---------------

CY=1 00001111B Con un acarreo de "1"

c)Se le determina el complemento a uno del resultado:

11110000B

De lo anterior se puede deducir porqué se utiliza la puesta a “1” de la bandera acarreo como indicador

similar a la solicitud de préstamo cuando la operación de sustracción se realiza por el microprocesador.

(f).- Multiplicando y dividiendo por potencias de dos: La multiplicación y la división son operaciones

aritméticas de uso común para la solución a problemas exigidos a un sistema de cómputo, su ejecución tarda

varios períodos de reloj (existen microprocesadores que no lo tienen incluído y se debe implementar por

programa).

Se puede obtener( basado en la posición relativa de las cifras que conforman el número) el producto y la

división de determinado valor a través de la simple rotación.

Multiplicación: El rotar un valor a la izquierda permite obtener el producto del valor almacenado por dos,

para multiplicar por N( donde N tiene que ser una potencia de dos) se puede utilizar:

PRODUCTO = MULTIPLICANDO(N)

donde N = 2n y n = Número de rotaciones a la izquierda.

Ejemplo 4.16:

Page 23: Ensamblador

Fundamentos del lenguaje ensamblador

257

Multiplique por 16 el siguiente dato: 00000100B=4D

N=16=24

Como n=4, entonces la solución sería rotar el dato cuatro veces a la izquierda, de lo que resulta:

01000000B=64D

División: Se realiza rotando a la derecha el dividendo n unidades, para lo cual se puede aplicar la siguiente

fórmula:

COCIENTE = DIVISOR / N

Donde N = 2n y n = Número de rotaciones a la derecha.

Ejemplo 4.17:

Divida por 64 el siguiente valor: 01001010B

N=64= 26

Como n es seis, entonces se debe rotar seis unidades a la derecha, de lo que resulta:

COCIENTE = 00000001B

Se debe tener en cuenta que la rotación puede conllevar a la pérdida de información (como en el ejemplo

anterior). Tal pérdida puede evitarse con la utilización de múltiple precisión en el manejo de datos.

(g) La multiplicación de números empaquetados en BCD por dos: Para ello lo que se hace es doblar el

número( adicionar el número con él mismo) y posteriormente se realiza el ajuste decimal del resultado (el

mayor valor en ocho bits será 99H).

(h) La división de números empaquetados en BCD por dos: Para ello se rota a la derecha el número y se le

sustrae tres a cualquier dígito que sea ocho o mayor.

(i).- Redondeo de números: Este tipo de aplicación se desarrolla fundamentalmente cuando se trata el dato

en múltiple precisión (ver sección 4.4).

Para redondear un número binario se utiliza el siguiente principio: Si el bit más significativo del byte que

será truncado es 1 (128 o mayor si se interpreta como entero sin signo), se le añade 1 al byte más

significativo adyacente.

Ejemplo 4.18:

Redondee a un byte los números siguientes, resultados de una suma:

MSByte LSByte

00101100 10010000

Como el bit MSB del byte menos significativo es 1, se incrementa en 1 el byte más significativo, siendo el

resultado:

Page 24: Ensamblador

Fundamentos del lenguaje ensamblador

258

00101101

También se puede redondear números empaquetados en BCD. Para realizar este tipo de operación se tiene

en cuenta que si el dígito más significativo que será truncado es 5 o mayor, se le añade 1 al byte adyacente

más significativo, ejecutando posteriormente el ajuste decimal.

Ejemplo 4.19:

Redondee a dos dígitos los cuatro dígitos empaquetados en BCD que se muestran a continuación:

MSByte LSByte

01001001 01100010

Se debe eliminar el byte menos significativo, como el número que representa el dígito más significativo a

truncar( 6D=0110) es mayor que 5, se suma 1 al dígito inmediato superior (1001).

01001001

+ 1

------------

01001010

Posteriormente se debe realizar el ajuste decimal (sumar 6, pues el resultado es un código erróneo) de lo que

resulta:

01010000=50H

4.4.- Ejemplos de programas en ensamblador.

Sistemas en múltiple precisión:La precisión simple aplicada a los microprocesadores significa el tratamiento

de datos con un número de bits cuyo tamaño coincida con el tamaño de los registros de propósito general

del microprocesador utilizado para el diseño del sistema. En la presente sección se trata como manipular

datos que poseen un número de bits superiores al formato básico de trabajo del microprocesador, para lo

que se tomará como referencia el tratamiento sobre un tamaño de 8 bits, lo cual puede generalizarse a un

número superior de bits.

4.4.1.- La adición y la sustracción.

La adición y la sustracción en múltiple precisión implica, básicamente, conservar el acarreo o el préstamo

de adiciones o sustracciones del byte contiguo de orden inferior y sumarlo o sustraerlo a la posición del bit

menos significativo del byte de orden superior.

Si se interpreta el dato como entero con signo, entonces el bit más significativo del byte más significativo

representará el signo en un dato de orden n, siendo los bytes de orden inferior representaciones de simples

dígitos binarios.

Ejemplo 4.20:

Realice la siguiente operación de suma:

MSByte LSByte

Page 25: Ensamblador

Fundamentos del lenguaje ensamblador

259

00000010 11001001 713

+00001000 10100101 +2213

------------------------- --------

Como las microcomputadoras de 8 bits suelen utilizar operandos de 8 bits, la operación anterior debe

ejecutarse en dos fases: primero sumando el byte de más bajo orden, conservando el acarreo que debe

trascender a la operación de los bytes más significativos:

11001001

+10100101

--------------

CY=1 01101110

En el segundo paso, se suman los dos bytes de orden superior, sumando el acarreo precedente de la suma

anterior al bit menos significativo:

00000010

+00001000

+ 1 Acarreo precedente

--------------

00001011

Los dos resultados se combinan en la suma resultante de 16 bits:

MSByte LSByte

00001011 01101110 = 2926D

El proceso consiste, pues, en sumar dos bytes cada vez, conservar el acarreo y añadirlo al siguiente byte de

orden superior, volver a conservar el acarreo para un posible próximo paso y así sucesivamente, repitiendo

el proceso tantas veces como bytes tengan los operandos. En los microprocesadores existe la instrucción de

suma con acarreo (ADC), útil para esta aplicación.

Ejemplo 4.21:

NAME SUMA_MULTIPLE

;==========================================================

;PROPÓSITO DEL PROGRAMA: Sumar dos numeros multibytes

;almacenados en memoria.

;==========================================================

;PARAMETROS DE ENTRADA:

;

;R0-Apunta a la dirección mas significativa del primer sumando

;R1-Apunta a la dirección mas significativa del segundo sumando

;B-Contiene el numero de bytes de cada sumando

;==========================================================

;PARAMETROS DE SALIDA:

;

;El resultado de la operacion se devuelve en las mismas

;localizaciones del primer sumando

;==========================================================

;FORMA DE LLAMADO:CALL SUM_MULTIPLE

;==========================================================

;REGISTROS UTILIZADOS:A,R0,R1,B

Page 26: Ensamblador

Fundamentos del lenguaje ensamblador

260

;==========================================================

;BYTES QUE OCUPA EN MEMORIA: 21 Bytes.

;==========================================================

;EJEMPLO:

;

; Entrada:

;DIR_0=20H DIR_1=35H CONTADOR=04H y en memoria existe:

; (20H...23H)=(88H,88H,88H,88H)

; (35H...39H)=(22H,22H,22H,22H)

;

; Salida: (20H...23H)=(AAH,AAH,AAH.AAH)

;==========================================================

EXTRN NUMBER (DIR_0)

EXTRN NUMBER (DIR_1)

EXTRN NUMBER (CONTADOR)

PUBLIC SUM_MULTIPLE

SUMA_MULTIPLE SEGMENT CODE

RSEG SUMA_MULTIPLE

SUM_MULTIPLE:

mov R0,#DIR_0;

mov R1,#DIR_1;

mov B,#CONTADOR;

PROX_BYTE: mov A,@R1 ;SE OBTIENE SUMANDO

addc A,@R0 ; SE ADICIONA COSUMANDO CON ACARREO

mov @R0,A ;RESULTADO EN DIRECCION DE R0

inc R1

inc R0 ;PROXIMO DATO DE 8 BITS

djnz B,PROX_BYTE ;CONTROL DE NÚMERO DE BYTES DE OPERANDOS

jnc FIN

mov A,#01H ; SE GARANTIZA POSIBLE ULTIMO ACARREO

add A,@R0

mov @R0,A

FIN: ret

End

PROGRAMA DE COMPROBACIÓN:

NAME PROGRAMA_COMPROBACION

; Comprobación del algoritmo de suma múltiple

EXTRN CODE (SUM_MULTIPLE)

PUBLIC CONTADOR

PUBLIC DIR_0

PUBLIC DIR_1

CONTADOR EQU 04H;

DIR_0 EQU 20H;

DIR_1 EQU 35H;

DSEG AT DIR_0 ; DIRECCION DE SUMANDO Y DESTINO

DS CONTADOR ;

DSEG AT DIR_1 ; DIRECCIÓN DE COSUMANDO

DS CONTADOR ; NÚMERO DE BYTES DE OPERANDOS

Page 27: Ensamblador

Fundamentos del lenguaje ensamblador

261

INICIO SEGMENT CODE

RSEG INICIO

CALL SUM_MULTIPLE

END

La Sustracción.

La sustracción es semejante a la adición, pero en este caso el acarreo (que se setea en la sustracción como

indicación de préstamo) debe ser sustraído al byte siguiente de orden superior.

Ejemplo 4.22:

Realice la siguiente sustracción, considerando un formato básico de 8 bits:

MSByte LSByte

00010010 00011010 4634D

-00010000 10010010 -4242D

-------------------------- ---------

Como primer paso, se debe sustraer los bytes de más bajo orden, considerando el posible préstamo.

00011010

-10010010

--------------

B=1 10001000

Posteriormente, se realiza la sustracción del préstamo a la operación del byte de orden superior:

00010010

-00010000

- 1 Sustracción del préstamo precedente

-------------

00000001

El resultado sería:

MSByte LSByte

00000001 10001000 = 392D

Los préstamos deben ser sustraídos a las operaciones de sustracción de los bytes precedentes, semejante a la

adición. Los microprocesadores pueden sustraer con préstamo, operación útil para esta aplicación.

Ejemplo 4.23:

NAME SUSTRACCIÓN_MULTIPLE

;**********************************************************

; PROPÓSITO DEL PROGRAMA: La sustraccion de dos numeros

; multibytes almacenados en memoria.

;**********************************************************

; Parámetros de entrada:

; R0 - Apunta a la dirección más significativa del minuendo.

Page 28: Ensamblador

Fundamentos del lenguaje ensamblador

262

; R1 - Apunta a la dirección más significativa del sustraendo.

; R2 - Contiene el número de bytes de cada operando.

;**********************************************************

; Parametros de salida: El resultado de la operacion se

; devuelve en las mismas localizaciones del minuendo

; (primer operando).

;**********************************************************

; Registros utlilizados: A,R0,R1,B.

;**********************************************************

; Forma de llamado: Call RESTA_MULTI

;**********************************************************

; EJEMPLO:

; Entrada:

; Si R0--> 24h, R1-->34h y R2= 5h

; (20h....24h)=(88h,88h,88h,88h,88h)

; (30h....34h)=(22h,22h,22h,22h,22h)

; Salida:

; (20h....24h)=(66h,66h,66h,66h,66h)

; Si CY=1 después de la ejecución, resultado incorrecto.

;**********************************************************

PUBLIC RESTA_MULTI

EXTRN NUMBER (DIR_MINU)

EXTRN NUMBER (DIR_SUST)

EXTRN NUMBER (CANT_BYTES)

RES_MULTIPLE SEGMENT CODE

RSEG RES_MULTIPLE

RESTA_MULTI:

mov r0,#DIR_MINU;

mov r1,#DIR_SUST;

mov B,#CANT_BYTES;

clr C ;PREPARA ACARREO PARA LA PRIMERA SUSTRACCIÓN

PX_BYTE: Mov A,@R0 ;SE OBTIENE EL MINUENDO

subb A,@R1 ;SE SUSTRAE CON ACARREO EL SUSTRAENDO

mov @R0,A ;RESULTADO EN DIRECCION DE R0

dec R0 ;PROXIMO DATO DE 8 BITS

dec R1

djnz B,PX_BYTE ;CONTROL DE NÚMERO DE BYTES DE OPERANDOS

ret

end

PROGRAMA DE COMPROBACIÓN:

NAME PROGRAMA_COMPROBACION

; Comprobación del algoritmo de sustracción múltiple

DIR_MINU EQU 24h;

DIR_SUST EQU 34H;

CANT_BYTES EQU 05H;

EXTRN CODE (RESTA_MULTI)

PUBLIC DIR_MINU ;DIRECCION DE MINUENDO Y DESTINO

PUBLIC DIR_SUST ;DIRECCIÓN DE SUSTRAENDO

PUBLIC CANT_BYTES ;NÚMERO DE DATOS DE LOS OPERANDOS

Page 29: Ensamblador

Fundamentos del lenguaje ensamblador

263

CALL RESTA_MULTI

END

4.4.2.- La rotación.

En la fig. 4.5 se muestra como efectuar la rotación en ambos sentidos (derecha e izquierda) de un dato en

múltiple precisión.

En la rotación a la derecha se toma el byte más significativo y se rota a la derecha a través del acarreo (C)

(en el primer paso se colocará el valor de C en el bit más significativo), posteriormente C posee el valor que

existía en el bit menos significativo, el cual será introducido en el bit más significativo del próximo dato de

menor orden, el proceso se repite en dependencia del número de bytes. En C se devuelve el valor del bit

menos significativo del dato de menor orden (byte menos significativo o LSByte).

En la rotación a la izquierda se toma inicialmente el byte menos significativo y se rota a la izquierda a

través del acarreo (de acuerdo a ello el bit menos significativo tendrá el valor de C y el bit 7 será devuelto

en este último), para el próximo paso C será colocado en el bit menos significativo del próximo byte de

mayor orden, el proceso se repite de acuerdo al número de bytes hasta que C devuelve el valor del bit más

significativo del byte de mayor orden (MSByte).

La rotación de números multibytes puede ser útil en la conversión BCD-binario, multiplicación y división

en múltiple precisión o multiplicación y división por potencias de dos.

MSByte LSByte

(a) Rotación a la derecha.

MSByte LSByte

(b) Rotación a la izquierda.

Figura 4.5.- Rotación en múltiple precisión.

Ejemplo 4.24:

NAME ROTAR_DERECHA

;=============================================================================

;PROPÓSITO DEL PROGRAMA:Rotar un numero multibytes a la derecha

;=============================================================================

;PARAMETROS DE ENTRADA:

;

;B-Número de bytes del operando

.....

C

..... ..... .....

C

.....

C

..... ..... .....

C

Page 30: Ensamblador

Fundamentos del lenguaje ensamblador

264

;R0-Direccion menos significativa del número a rotar

;En el acarreo (CY)debe estar lo que se desea entrar en el bit 7 de la direccion

;menos significativa.

;=============================================================================

;FORMA DE LLAMADO:CALL ROTA_DERECHA

;=============================================================================

;REGISTROS UTILIZADOS:A,R0,B,C

;=============================================================================

;BYTES QUE OCUPA EN MEMORIA: 13

;=============================================================================

;EJEMPLO:

; Entrada:

; Si R0=20H B=03H CY=1 (20H...22H)=(77H,66H,22H)

; Salida:

; (20H...22H)=(BBH,B3H,11H)

;=============================================================================

PUBLIC ROTA_DERECHA

EXTRN NUMBER (DIR_BYTEALTO)

EXTRN NUMBER (CANT_BYTES)

ROTA_DER SEGMENT CODE

RSEG ROTA_DER

ROTA_DERECHA:

Mov B, #CANT_BYTES;

Mov R0, #DIR_BYTEALTO;

SETB C; CLR C SI C=0;

RotaDer:Mov A,@R0 ; Valor a rotar

RrC A ; Rota a la derecha el valor

Mov @R0,A ; Almacena valor rotado

Inc R0 ;

DjnZ B,RotaDer ; Control del número de bytes

Ret

End

PROGRAMA DE COMPROBACIÓN:

NAME PROGRAMA_COMPROBACION

; Comprobación del algoritmo de rotación a la derecha

EXTRN CODE (ROTA_DERECHA)

PUBLIC DIR_BYTEALTO

PUBLIC CANT_BYTES

DIR_BYTEALTO EQU 20h; DIRECCIÓN DEL BYTE MÁS SIGNIFICATIVO

CANT_BYTES EQU 03H; NÚMERO DE DATOS DEL OPERANDO

CALL ROTA_DERECHA

END

4.4.3.- Comparación de dos cadenas.

Cuando se comparan dos cadenas, la cadena 1 puede ser mayor, menor o igual que la cadena 2. Para ello, se

definen dos punteros que apunten al byte que define al dato más significativo de ambas cadenas, basta que

un dato más significativo de la cadena 1 sea mayor o menor que el dato equivalente de la cadena 2 para que

Page 31: Ensamblador

Fundamentos del lenguaje ensamblador

265

la cadena sea mayor o menor. En caso que los datos sean iguales, el proceso debe repetirse hasta que se

comparen los datos menos significativos, que determinarán la igualdad en ambas cadenas.

Ejemplo 4.25:

NAME COMPARACION_MULTIBYTES

;=============================================================================

;PROPÓSITO DEL PROGRAMA:Comparar dos números almacenados en memoria

;=============================================================================

;Los bytes menos significativos de los dos numeros a comparar estaran en las

;direcciones mas bajas

;=============================================================================

;PARAMETROS DE ENTRADA:

;

;B- Número de bytes a comparar

;R0-Octeto más significativo del número 1

;R1-Octeto más significativo del número 2

;=============================================================================

;PARAMETROS DE SALIDA:

;

;A-Resultado de la comparacion (bandera):

;A=00H si número_1>número_2

;A=01H si número_1<número_2

;A=02H si número_1=número_2

;=============================================================================

;FORMA DE LLAMADO:CALL COMPARA

;=============================================================================

;BYTES QUE OCUPA EN MEMORIA: 28

;=============================================================================

;REGISTROS UTILIZADOS:A,R0,R1,B, DIRECCIÓN_DATO 7FH

;=============================================================================

;EJEMPLO:

; Entrada:

; Si B=3 ,R0=20H, R1=30H y (20h...22h)=77H,88H,55H (30..32h)=77H,77H,77H

; Salida:

; A=00H

;=============================================================================

PUBLIC COMPARA

EXTRN NUMBER (DIR_N1)

EXTRN NUMBER (DIR_N2)

EXTRN NUMBER (CANT_BYTES)

COMP SEGMENT CODE

RSEG COMP

COMPARA:

mov r0, #DIR_N1

mov r1, #DIR_N2

mov B,#CANT_BYTES

COMPAR:

mov A,@R1 ; SE TOMA BYTE MÁS SIG. DE NUM. 2

mov 7FH,@R0 ;BYTE MAS SIGNIF. DE NUM. 1 A MEMORIA

cjne A,7FH,NOIGUAL ;SE COMPARA LOS DOS NÚMEROS

inc R0 ;DECREMENTO PUNTER0

inc R1

djnz B,COMPAR

mov A,#02H ;NUM. 1=NUM. 2

Page 32: Ensamblador

Fundamentos del lenguaje ensamblador

266

ret

NOIGUAL:jc MAYOR1

mov A,#01H ;NUM. 1<NUM. 2

ret

MAYOR1:mov A,#00H ;NUM. 1>NUM. 2

ret

END

PROGRAMA DE COMPROBACIÓN:

NAME PROGRAMA_COMPROBACION

; Comprobación del algoritmo de comparación de dos números multibytes.

DIR_N1 EQU 20h;

DIR_N2 EQU 30H;

CANT_BYTES EQU 03H;

EXTRN CODE (COMPARA)

PUBLIC DIR_N1 ; Dirección del octeto más significativo del num. 1

PUBLIC DIR_N2 ; Dirección del octeto más significativo del num. 2

PUBLIC CANT_BYTES ;Número de octetos de cada número

CALL COMPARA

END

4.4.4.- Incremento y decremento de un número binario.

Cuando se decrementa un número binario multibytes debe encuestarse cuando en el byte de menor orden

ocurre un underflow (paso de 00 a FFH), lo cual debe provocar un decremento en el byte de mayor orden

consecutivo. De forma similar, en el caso de incremento debe considerarse cuando ocurre un overflow (paso

de FFH a 00) en el byte de menor orden, ello debe provocar un incremento en el byte de mayor orden

consecutivo.

Ejemplo 4.26:

NAME INCREMENTO_HEXADECIMAL

;=============================================================================

;PROPÓSITO DEL PROGRAMA:Incrementar una unidad un numero de N bytes almacenado

;en memoria.

;=============================================================================

;PARAMETROS DE ENTRADA:

;

;B-Número de bytes del numero a incrementar

;R0-Apunta a la dirección más alta del numero hexadecimal

;=============================================================================

;PARAMETROS DE SALIDA:

;El resultado se da en las mismas localizaciones de memoria, debe considerarse

;el acarreo

;=============================================================================

;FORMA DE LLAMADO:CALL INC_HEX

;=============================================================================

;REGISTROS UTILIZADOS:R0,B

;=============================================================================

;BYTES QUE OCUPA EN MEMORIA: 17

Page 33: Ensamblador

Fundamentos del lenguaje ensamblador

267

;=============================================================================

;EJEMPLO:

; Entrada:

;Si R0=23h B=04h (20h...23h)=(22h,ffh,ffh,ffh)

; Salida:

; (20h...23h)=(23h,00h,00h,00h)

;=============================================================================

PUBLIC INC_HEX

EXTRN NUMBER (DIR_BYTEBAJO)

EXTRN NUMBER (CANT_BYTES)

INC_H SEGMENT CODE

RSEG INC_H

INC_HEX:

Mov B, #CANT_BYTES;

Mov R0, #DIR_BYTEBAJO;

CLR C

INCHEX: cjne @R0,#0ffh,termino; Se toma octeto

inc @R0 ; Se incrementa

dec R0

djnz B,INCHEX ; Control cant. de datos

ret

termino:

inc @r0;

ret

end

PROGRAMA DE COMPROBACIÓN:

NAME PROGRAMA_COMPROBACION

; Comprobación del algoritmo de incremento de número multibytes.

EXTRN CODE (INC_HEX)

PUBLIC DIR_BYTEBAJO

PUBLIC CANT_BYTES

DIR_BYTEBAJO EQU 23h ;Dirección del byte menos significativo

CANT_BYTES EQU 04H ;Cantidad de bytes del dato

CALL INC_HEX

END

Ejemplo 4.27:

NAME DECREMENTO_HEXADECIMAL

;=============================================================================

;PROPÓSITO DEL PROGRAMA:Decrementar una unidad un numero de N bytes almacenado

;en memoria.

;=============================================================================

;PARAMETROS DE ENTRADA:

;

;B-Número de bytes del número a decrementar

;R0-Apunta a la dirección más alta del número hexadecimal

;=============================================================================

;PARAMETROS DE SALIDA:

Page 34: Ensamblador

Fundamentos del lenguaje ensamblador

268

;El resultado se da en las mismas localizaciones de memoria, debe considerarse

;el acarreo

;=============================================================================

;FORMA DE LLAMADO:CALL DEC_HEX

;=============================================================================

;REGISTROS UTILIZADOS:R0,B

;=============================================================================

;BYTES QUE OCUPA EN MEMORIA: 15

;=============================================================================

;EJEMPLO:

; Entrada:

;Si R0=94h B=04h (91h...94h)=(23h,00h,00h,00h)

; Salida:

; (91h...94h)=(22h,ffh,ffh,ffh)

;=============================================================================

PUBLIC DEC_HEX

EXTRN NUMBER (DIR_BYTEBAJO)

EXTRN NUMBER (CANT_BYTES)

INC_H SEGMENT CODE

RSEG INC_H

DEC_HEX:

Mov B, #CANT_BYTES;

Mov R0, #DIR_BYTEBAJO;

INCHEX: cjne @r0,#00h,termino

dec @r0; ; Se decrementa valor

dec R0

djnz B,INCHEX ;Control de cantidad de datos

ret

termino:

dec @r0;

ret

end

PROGRAMA DE COMPROBACIÓN:

NAME PROGRAMA_COMPROBACION

; Comprobación del algoritmo de decremento de número multibytes.

EXTRN CODE (DEC_HEX)

PUBLIC DIR_BYTEBAJO

PUBLIC CANT_BYTES

DIR_BYTEBAJO EQU 23h; Dirección del byte menos significativo

CANT_BYTES EQU 04H; Cantidad de bytes del dato

CALL DEC_HEX

END

4.4.5.- Incremento y decremento de un número en BCD.

Para decrementar un número en BCD debe considerarse que un decremento de 00 en el byte de menor orden

debe provocar el paso a 99 del mismo y debe sustraerse uno al próximo byte de mayor orden. En caso de

Page 35: Ensamblador

Fundamentos del lenguaje ensamblador

269

que la cuarteta (nibble) menos significativa al que es necesario sustraer uno valga cero, este debe pasar a 9 y

realizarse un decremento a la cuarteta más significativa (sustraer 10H al byte).

Cuando se realiza el incremento de un número en BCD debe encuestarse el paso de 99H a 00, lo cual debe

provocar un incremento en el byte de mayor orden consecutivo. Cuando la cuarteta menos significativa a

incrementar valga 9, esta debe pasar a cero con el correspondiente incremento en la cuarteta más

significativa (sumar 10H al byte). El algoritmo puede optimizarse utilizando la instrucción DAA, la cual es

aplicable (si el microprocesador lo posee) generalmente para la adición.

Ejemplo 4.28:

NAME INCREMENTO_BCD

;=============================================================================

;PROPÓSITO DEL PROGRAMA:Incrementar en uno un numero de N bytes almacenado en

;memoria, manteniendo formato BCD.

;=============================================================================

;PARAMETROS DE ENTRADA:

;

;B-Número de bytes del numero a incrementar

;R0-Puntero a la dirección más alta del numero BCD

;=============================================================================

;PARAMETROS DE SALIDA:

;

;En las mismas localizaciones donde está definido el número

;=============================================================================

;FORMA DE LLAMADO:CALL INC_BCD

;=============================================================================

;REGISTROS UTILIZADOS:A,R0,B

;=============================================================================

;BYTES QUE OCUPA EN MEMORIA:17

;=============================================================================

;EJEMPLO:

; Entrada:

; Si R0=23h B=04h (20...23h)=(22h,99h,99h,99h)

; salida:

; (20...23h)=(23h,00h,00h,00h)

;=============================================================================

PUBLIC INC_BCD

EXTRN NUMBER (DIR_BYTEBAJO)

EXTRN NUMBER (CANT_BYTES)

INC_B SEGMENT CODE

RSEG INC_B

INC_BCD:

mov R0,#DIR_BYTEBAJO

mov B,#CANT_BYTES

INCBCD:mov A,@R0 ; toma dato

add A,#01H ; lo incrementa

da a ; ajusta manteniendo el BCD

mov @r0,a

jnc termino

dec R0

djnz B,INCBCD ; control del número de bytes

termino: ret

end

Page 36: Ensamblador

Fundamentos del lenguaje ensamblador

270

PROGRAMA DE COMPROBACIÓN:

NAME PROGRAMA_COMPROBACION

; Comprobación del algoritmo de incremeto de número BCD.

EXTRN CODE (INC_BCD)

PUBLIC DIR_BYTEBAJO

PUBLIC CANT_BYTES

DIR_BYTEBAJO EQU 23h ; Dirección del byte menos significativo

CANT_BYTES EQU 04H ; Cantidad de bytes del dato

CALL INC_BCD

END

Ejemplo 4.29:

NAME DECREMENTO_BCD

;=============================================================================

;PROPÓSITO DEL PROGRAMA:Decrementar en uno un numero de N bytes almacenado en

;memoria, manteniendo formato BCD.

;=============================================================================

;PARAMETROS DE ENTRADA:

;B-Número de bytes del numero a decrementar

;R0-Apunta a la dirección más significativa del numero BCD

;=============================================================================

;PARAMETROS DE SALIDA:

;

;En las mismas localizaciones donde el número se ha definido

;=============================================================================

;FORMA DE LLAMADO:CALL DEC_BCD

;=============================================================================

;REGISTROS UTILIZADOS:A,R0,B

;=============================================================================

;BYTES QUE OCUPA EN MEMORIA:33

;=============================================================================

;EJEMPLO:

; Entrada:

;Si R0=23h B=04h (20...23h)=(23h,00h,00h,00h)

; Salida:

; devuelve: (20...23h)=(22h,99h,99h,99h)

;=============================================================================

PUBLIC DEC_BCD

EXTRN NUMBER (DIR_BYTEBAJO)

EXTRN NUMBER (CANT_BYTES)

DEC_B SEGMENT CODE

RSEG DEC_B

DEC_BCD:

Mov B, #CANT_BYTES;

Mov R0, #DIR_BYTEBAJO;

DECBCD: mov a,@r0;

cjne a,#00h,dec_normal

anl a,#0F0h ; cuarteta más significativa

Page 37: Ensamblador

Fundamentos del lenguaje ensamblador

271

cjne a,#00h, dec_men

mov @r0,#99h ; si cero, 99

dec R0

djnz B,DECBCD ;se decrementa contador

ljmp termino

dec_normal:

dec @r0;

ljmp termino

dec_men: clr c

subb a,10h ; decrementa cuarteta más sign.

orl a,#09H;

mov @r0,a

termino:

ret

end

PROGRAMA DE COMPROBACIÓN:

NAME PROGRAMA_COMPROBACION

; Comprobación del algoritmo de decremeto de número BCD.

EXTRN CODE (DEC_BCD)

PUBLIC DIR_BYTEBAJO

PUBLIC CANT_BYTES

DIR_BYTEBAJO EQU 23h; Dirección del byte menos significativo

CANT_BYTES EQU 04H; Cantidad de bytes del dato

CALL DEC_BCD

END

4.4.6.- El redondeo binario.

Cuando se almacena un valor multibyte, el redondeo no es más que encuestar si el byte que será truncado es

80H o superior, cuando ello ocurre se incrementa en uno el byte adyacente de orden superior, colocando a

cero los bytes menos significativos restantes.

Ejemplo 4.30:

;TITULO: REDONDEO DE UN NUMERO BINARIO

;=============================================================================

;PROPOSITO DEL PROGRAMA: Redondear un binario de N bytes almacenado a partir

; de una localización de memoria dada.

;=============================================================================

;PARAMETROS DE ENTRADA:

;

; R0-Apunta a la dirección menos significativa del numero a redondear

; B-Contiene el número de bytes del numero a redondear

;=============================================================================

;PARAMETRO DE SALIDA:

;

; El resultado se devuelve en las mismas localizaciones donde se ha definido el numero.

;=============================================================================

;FORMA DE LLAMADO: CALL RED_BIN

;=============================================================================

Page 38: Ensamblador

Fundamentos del lenguaje ensamblador

272

;REGISTROS UTILIZADOS: A,R0,B

;=============================================================================

;BYTES QUE OCUPA EN MEMORIA:

;=============================================================================

;EJEMPLO:

; Entrada:

; Si R0=20H B=04H (20H...23H)=(23H,80H,00H,00H)

; Salida:

; (20H...23H)=(24H,00H,00H,00H)

;=============================================================================

PUBLIC RED_BIN

EXTRN NUMBER (DIR_BYTEALTO)

EXTRN NUMBER (CANT_BYTES)

RED_B SEGMENT CODE

RSEG RED_B

RED_BIN:

Mov B, #CANT_BYTES;

Mov R0, #DIR_BYTEALTO;

inc R0 ;R0 AL BYTE MAS SIGNIF. -1

mov A,@R0 ; SE TOMA DATO

cjne A,#80H,NOIGUAL ;? SI @R0>=80H

NOIGUAL:jc REDBIN1 ;APROXIMA AL MENOR

dec R0 ;APROXIMA AL MAYOR

inc @R0 ;INCREMENTA EL BYTE MAS SIGNIF.

inc R0

REDBIN1:dec B

mov A,#00H ;COLOCA CERO

REDBIN2:mov @R0,A ;RESETEO BYTES MENOS SIGNIF.

inc R0

djnz B,REDBIN2 ;DECREMENTA CONTADOR DE BYTES

ret

end

PROGRAMA DE COMPROBACIÓN:

NAME PROGRAMA_COMPROBACION

; Comprobación del algoritmo de redondeo binario.

EXTRN CODE (RED_BIN)

PUBLIC DIR_BYTEALTO

PUBLIC CANT_BYTES

DIR_BYTEALTO EQU 20h; Dirección del byte más significativo

CANT_BYTES EQU 04H; Cantidad de bytes del dato

CALL RED_BIN

END

4.4.7.- El redondeo en BCD.

Redondear en BCD es incrementar el byte de mayor orden cuando el byte que se va a truncar es 50H ( la

mitad de 10D) o superior.

Page 39: Ensamblador

Fundamentos del lenguaje ensamblador

273

Ejemplo 4.31:

NAME REDONDEO_BCD

;=============================================================================

;PROPOSITO DEL PROGRAMA:Redondear un BCD de N bytes almacenado a partir de

;una direccion de memoria

;=============================================================================

;PARAMETROS DE ENTRADA:

;

;B-Contiene el numero de bytes del numero a redondear

;R0-Dirección menos significativa del numero a redondear

;=============================================================================

;PARAMETROS DE SALIDA:

;

;Se devuelve en las mismas localizaciones.

;=============================================================================

;FORMA DE LLAMADO:CALL RED_BCD

;=============================================================================

;REGISTROS UTILIZADOS:A,R0,B

;=============================================================================

;BYTES QUE OCUPA EN MEMORIA: 28

;=============================================================================

;EJEMPLO:

; Entrada:

; Si R0=20H B=04H (20H...23H)=(66H,60H,00H,00H)

; Salida:

; (20H...23H)=(67H,00H,00H,00H)

;=============================================================================

PUBLIC RED_BCD

EXTRN NUMBER (DIR_BYTEALTO)

EXTRN NUMBER (CANT_BYTES)

RED_BC SEGMENT CODE

RSEG RED_BC

RED_BCD:

Mov B, #CANT_BYTES;

Mov R0, #DIR_BYTEALTO;

inc R0 ; Adjunto a byte + sig.

mov A,@R0

cjne A,#50H,NOIGUAL ; ¿mayor a 50h?

NOIGUAL:jc REDBCD1 ;aproximo al menor

dec R0 ;aproximo al mayor

mov A,@R0 ;en a el mas significativo

add a,#01H

da A

mov @R0,A ;en memoria el resultado del redondeo

inc R0

REDBCD1:dec B

mov A,#00H ;colocar a cero bytes restantes

REDBCD2:mov @R0,A ;colocar a cero bytes menos significativos

inc R0

djnz B,REDBCD2 ;Control número de bytes

ret

end

Page 40: Ensamblador

Fundamentos del lenguaje ensamblador

274

PROGRAMA DE COMPROBACIÓN:

NAME PROGRAMA_COMPROBACION

; Comprobación del algoritmo de redondeo en BCD.

EXTRN CODE (RED_BCD)

PUBLIC DIR_BYTEALTO

PUBLIC CANT_BYTES

DIR_BYTEALTO EQU 20h; Dirección del byte más significativo

CANT_BYTES EQU 04H; Cantidad de bytes del dato

CALL RED_BCD

END

4.4.8.- El complemento a dos de números multibytes.

En las aplicaciones donde haya que negar un número (o lo que es lo mismo, obtener el complemento a dos)

es necesario adicionar el acarreo generado por los bytes de orden inferior a los bytes de orden superior. Para

ello, se obtiene el complemento a dos del byte menos significativo y el posible acarreo generado debe

adicionarse al complemento a uno de los bytes de mayor orden.

Ejemplo 4.32:

Determine el número negativo de:

MSByte LSByte

00001001 00000000 2304D

Solución:

En primer lugar se obtiene el complemento a dos del byte de menor orden:

Complemento a dos = 11111111 + 1= 00000000 (C=1)

Posteriormente se suma el acarreo al complemento a uno del byte de mayor orden:

11110110

+ 1

-------------

11110111

El resultado sería:

11110111 00000000

Ejemplo 4.33:

NAME COMPLEMENTO_A_2

;=============================================================================

;PROPÓSITO DEL PROGRAMA:Complemento a dos de un número multibytes.

;=============================================================================

Page 41: Ensamblador

Fundamentos del lenguaje ensamblador

275

;PARAMETROS DE ENTRADA

;

; B-Número de bytes

; R0-Direccion más significativa donde está el dato

;=============================================================================

;PARAMETROS DE SALIDA

;

;El resultado se devuelve en las localizaciones donde el dato está almacenado y

;Cy=1 si esta fuera de rango.

;=============================================================================

;FORMA DE LLAMADO:CALL COMPLEMENTO

;=============================================================================

;REGISTROS UTILIZADOS:A,R0,B

;=============================================================================

;BYTES QUE OCUPA EN MEMORIA: 22

;=============================================================================

;EJEMPLO:

; Entrada:

;Si R0=20H y en memoria 20H=FFH 21H=00H con CY=1 y B=2

; Salida: 20H=01H 21H=00H

;=============================================================================

PUBLIC COMPLEMENTO

EXTRN NUMBER (DIR_BYTEBAJO)

EXTRN NUMBER (CANT_BYTES)

COMP_2 SEGMENT CODE

RSEG COMP_2

COMPLEMENTO:

MOV B,#CANT_BYTES

MOV R0,#DIR_BYTEBAJO

MOV A,@R0 ;BYTE A COMPLEMENTAR EN A

CPL A ;COMPLEM. A 2 EL PRIMER BYTE

ADD A,#01H

MOV @R0,A ;SALVO EL RESULTADO EN MISMA DIRECCIÓN

DEC B

REPCOP:DEC R0 ;PROXIMO BYTE

MOV A,@R0

CPL A

ADDC A,#00H ;ADICIONO EL ACARREO

MOV @R0,A ;SALVO EL RESULTADO

DJNZ B,REPCOP ;CONTADOR DE BYTES

RET

END

PROGRAMA DE COMPROBACIÓN:

NAME PROGRAMA_COMPROBACION

; Comprobación del algoritmo de complemento a dos multibytes

EXTRN CODE (COMPLEMENTO)

PUBLIC DIR_BYTEBAJO

PUBLIC CANT_BYTES

DIR_BYTEBAJO EQU 21h ; Dirección del byte menos significativo

CANT_BYTES EQU 02H ; Cantidad de bytes del dato

Page 42: Ensamblador

Fundamentos del lenguaje ensamblador

276

CALL COMPLEMENTO

END

4.4.9.- Mover o copiar de una zona de memoria a otra.

A menudo es necesario transferir bloques de información, para ello se ejecutan las funciones de mover o

copiar.

Cuando se mueve un bloque de datos, la cadena fuente es transferida a un destino (cadena destino) que se

sitúa a partir de una nueva dirección en memoria. La cadena fuente se sustituye por ceros. Cuando se copia,

se transfiere la cadena origen al destino y ambas zonas de memoria poseerán el mismo contenido.

Ejemplo 4.34:

NAME MUEVE_O_COPIA

;=============================================================================

;PROPÓSITO DEL PROGRAMA:Mover o copiar el contenido de una zona de memoria

;de datos a otra.

;=============================================================================

;PARAMETROS DE ENTRADA:

;

;A-Bandera que indica mover o copiar

;A=00H-Mover

;A=01H-Copiar

;R0-Direccion fuente más significativa

;R1-Direccion destino más significativa

;B-Número de bytes de la cadena

;=============================================================================

;FORMA DE LLAMADO:CALL MOV_O_COP

;=============================================================================

;REGISTROS UTILIZADOS:A,R0,R1,B

;=============================================================================

;BYTES QUE OCUPA EN MEMORIA: 29

;=============================================================================

;EJEMPLO:

; Entrada:

; Si R0=24H , R1=34H y B=5 20...24(FF,FF,FF,FF,FF)

; Salida:

; 30...34(FF,FF,FF,FF,FF)

; siendo 20..24(00,00,00,00,00) si mueve

; o 20..24(FF,FF,FF,FF,FF) si copia

;=============================================================================

PUBLIC MOV_O_COP

EXTRN NUMBER (DIR_BYTEALTO_ORIGEN)

EXTRN NUMBER (CANT_BYTES)

EXTRN NUMBER (BANDERA)

EXTRN NUMBER (DIR_BYTEALTO_DESTINO)

MOV_C SEGMENT CODE

RSEG MOV_C

MOV_O_COP:

Mov B, #CANT_BYTES;

Mov R0, #DIR_BYTEALTO_ORIGEN;

Page 43: Ensamblador

Fundamentos del lenguaje ensamblador

277

Mov R1, #DIR_BYTEALTO_DESTINO;

Mov A, #BANDERA

cjne A,#01H,MOVER ; mover?

COPIAR:mov A,@R0 ; toma dato

mov @R1,A ; y lo transfiere

dec R0 ; DECREMENTO PUNTEROS

dec R1

djnz B,COPIAR ;contador

ret

MOVER:mov A,@R0 ; dirección fuente

mov @R0,#00H ; se coloca a cero

mov @R1,A

dec R0 ;DECREMENTO PUNTEROS

dec R1

djnz B,MOVER ;contador

ret

END

PROGRAMA DE COMPROBACIÓN:

NAME PROGRAMA_COMPROBACION

; Comprobación del algoritmo para mover o copiar datos

EXTRN CODE (MOV_O_COP)

PUBLIC DIR_BYTEALTO_ORIGEN

PUBLIC CANT_BYTES

PUBLIC BANDERA

PUBLIC DIR_BYTEALTO_DESTINO

DIR_BYTEALTO_ORIGEN EQU 34h; Dirección más significativa del origen

DIR_BYTEALTO_DESTINO EQU 24H; Dirección más significativa del destino

CANT_BYTES EQU 05H; Cantidad de bytes a transferir

BANDERA EQU 01H; Indica si mueve o copia

CALL MOV_O_COP

END

4.4.10.- El tratamiento de tablas.

Una tabla consiste en un grupo de datos que ocupan posiciones contiguas. Ya sea mediante desplazamientos

aplicados a la tabla o recurriendo a otros datos asociados con la entrada de la tabla, ésta sirve para

correlacionar entre sí bloques de datos. Cada tabla está formada por un número variable de entradas

multiplicado por la longitud de cada una de ellas.

Sometiendo la dirección inicial de una tabla a desplazamientos, se pueden inspeccionar los elementos que la

componen. Como ejemplo puede considerarse una rutina de conversión de BCD a siete segmentos, en la

cual el valor en BCD se suma a un puntero que indica el inicio de la tabla, extrayéndose el código BCD

equivalente de la entrada correspondiente (ver secc. 4.2.8).

Otro ejemplo de tabla puede ser aquella en que el elemento o dato contenido en ella define el

desplazamiento que se aplica a otras operaciones, como por ejemplo, en un sistema de clasificación de cual

rutina debe ser ejecutada. Para atender una entrada por teclado pueden utilizarse dos tablas. La primera tabla

estaría formada por todas las señales de mando o control; si hubiera 10 comandos de 1 byte, la tabla tendría

Page 44: Ensamblador

Fundamentos del lenguaje ensamblador

278

10 bytes de largo, y cada entrada de 1 byte sería el caracter asociado a la señal de mando en cuestión. La

segunda tabla estaría formada por 10 entradas de 2 bytes, cada una de las cuales definen la dirección

correspondiente a la rutina que debe ejecutarse en respuesta al comando de control.

Como ejemplo, supóngase que se atiende un teclado que exporte caracteres ASCII, donde si "A","B" o "C"

son presionados se necesite ejecutar determinada función.

La primera tabla puede estar formada por:

TABLA_ENT:

db “A”,”B”,”C”

Si la tecla B es presionada, entonces un apuntador indicaría que B ha sido hallada en la tabla (A=00, B=01,

etc). En la segunda tabla estaría definido:

TABLA_DIR:

dw DIR_Ah, DIR_Bh, DIR_Ch

El apuntador debe ser multiplicado por dos ( una dirección de 16 bits ocupa dos bytes) y realizarse un

acceso a la dirección de respuesta (DIR_B) después de hacer un desplazamiento a partir de la dirección de

inicio de la segunda tabla.

Existen tablas donde los valores que la conforman no poseen un orden preestablecido( tabla de entradas

desordenadas), donde se hace necesario buscar si determinado dato existe, para lo que se recurre a un

escrutinio secuencial, inspeccionándose la tabla de principio a fin para comparar el contenido con la clave

buscada. El número medio de entradas que se procesa en tal búsqueda secuencial es el número total de

entradas de la tabla entre dos.

Si la tabla posee entradas ordenadas, el escrutinio binario puede usarse en la búsqueda de un dato. En este

tipo de escrutinio la zona a inspeccionar se divide en dos partes para cada comparación. La porción que se

inspeccionará en la siguiente comparación depende de la entrada que se tenga y la clave. Como ejemplo,

supóngase que la clave es BACH en la siguiente tabla:

Dirección de Entrada Valor No. de comparación

0 BACH Cuarta

1 BIZET Tercera

2 DVORAK Segunda

3 FRANK

4 LISZT Primera

5 RAVEL

6 ROSSINI

7 STRAUSS

8 VERDI

La primera comparación se hace en la mitad de la tabla, como la letra de la clave posee un valor inferior a la

L de LISZT se iría en la próxima comparación a la mitad inferior, si no fuese así se iría a la mitad superior.

Al efectuar cada comparación, la zona a examinar se reduce a la mitad. Cada nueva comparación tiene lugar

hacia el centro de la zona restante.

El número de comparaciones que habría que hacer en el peor caso sería:

Page 45: Ensamblador

Fundamentos del lenguaje ensamblador

279

1)(log2 rentradasdetotalNúmeroN

donde r significa redondeadas, en el ejemplo anterior, log2(9)=4, ya que log2(9)=4.xx.

Otra modalidad de estructura de datos es la matriz. Una tabla no es más que una matriz de una sola

dimensión cuando se hace referencia a la entrada de la misma mediante desplazamientos a partir del

comienzo, o en el índice. Los datos se pueden colocar en matrices bidimensionales o incluso de n

dimensiones. Una matriz de dos dimensiones está caracterizada por un número de fila (m) y un número de

columna (n), el número total de elementos es mn; la matriz se puede colocar en memoria en este orden:

C0,R0; C0,R1; C0,R2;...;C0,Rm-1; C1,R0,..etc; o en este otro modo: R0,C0; R0,C1; R0,C2; ...;R0, Cn-1;

R1,C0;..etc. En el primer caso, el desplazamiento medido a partir de la zona ocupada por los elementos

integrantes de la matriz viene dado por (Cm)+R, donde C es el número de la columna (empezando por

cero), m es el número total de filas y R es el número de la fila (comenzando por cero). En el segundo caso el

desplazamiento responde a la fórmula (Rn)+C, donde n es el número de columnas.

Ejemplo 4.35:

Establezca la siguiente matriz en memoria:

Número de columnas

Número de filas 0 1 2

0 0 3 5

1 2 8 9

2 4 3 1

Utilizando el primer método, sería:

db 0,2,4,3,8,3,5,9,1

Para acceder al dato correspondiente a la fila 1, columna 2 se aplica:

(Cm)+R = 2(3)+1 = 7

Como puede apreciarse, el séptimo valor (contando a partir de cero) es el 9.

4.4.10.1.-Entrar un dato en una tabla.

Un valor puede colocarse en una tabla en el byte más o menos significativo, lo cual debe seleccionarse en

el algoritmo a través de un indicador o bandera. Si se coloca el valor en el byte menos significativo el byte

más significativo se perderá y viceversa. El método previamente descrito puede optimizarse si se dispone de

dos punteros, los cuales se incrementarán al entrar un valor en el byte de menor orden o se decrementarán

al entrar el valor en el byte de mayor orden.

Estas rutinas pueden ser útiles para colocar un dato en memoria para un visualizador a 7 segmentos o

incrementar un buffer de entrada por teclado.

Ejemplo 4.36:

NAME ENTRADA_DATO_A_CADENA

;=============================================================================

Page 46: Ensamblador

Fundamentos del lenguaje ensamblador

280

;PROPÓSITO DEL PROGRAMA:Entrar un dato a una cadena de N bytes,la entrada

;pude ser tanto por la derecha como por la izquierda.

;=============================================================================

;PARAMETROS DE ENTRADA:

;

;B-Número de bytes de la cadena

;R0-Direccion mas significativa de la cadena

;R3-Bandera que indica entrada por derecha o izquierda

; R3=0; entra por la derecha (byte menos significativo)

; R3=1; entra por la izquierda (byte mas significativo)

;R2-Dato a entrar

;=============================================================================

;FORMA DE LLAMADO:CALL ENT_DATO

;=============================================================================

;REGISTROS UTILIZADOS:B,R0,R2,R3,A

;=============================================================================

;BYTES QUE OCUPA EN MEMORIA: 40

;=============================================================================

;EJEMPLO:

; Entrada:

; Si R0=22H B=03H R3=0H R2=45H

; (20H....22H)=(11H,22H,33H)

; Salida:

; (20H....22H)=(22H,33H,45H)

;=============================================================================

PUBLIC ENT_DATO

EXTRN NUMBER (DIR_BYTEALTO)

EXTRN NUMBER (CANT_BYTES)

EXTRN NUMBER (BANDERA)

EXTRN NUMBER (DATO)

ENT_C SEGMENT CODE

RSEG ENT_C

ENT_DATO:

Mov B, #CANT_BYTES;

Mov R0, #DIR_BYTEALTO;

Mov R3, #BANDERA

Mov R2, #DATO

dec B

cjne R3,#01H,ENTDER

ENTIZQD:dec R0 ;R0 APUNTA A UNA DIREC. MAS BAJA

mov A,@R0

inc R0 ;SUBO EL VALOR ANTERIOR

mov @R0,A ;A UNA DIREC. SUPERIOR

dec R0 ;DECREMENTO R0 A LA PROXIMA DIREC.

djnz B,ENTIZQD

mov A,R2

mov @R0,A ;ENTRO DATO A LA CADENA

ret

ENTDER:clr C ; SETEO EL ACARREO PARA LA RESTA

mov A,R0 ;GARANTIZA QUE R0 APUNTE A DIR. MAS BAJA

subb A,B

mov R0,A

ENTDER1:inc R0 ;R0 APUNTA A DIREC. MAS ALTA

mov A,@R0

Page 47: Ensamblador

Fundamentos del lenguaje ensamblador

281

dec R0 ;SUBO EL VALOR ANT. A DIREC. INFERIOR

mov @R0,A

inc R0 ;INC R0 A UNA DIRECCION MAS ALTA

djnz B,ENTDER1

mov A,R2

mov @R0,A ;ENTRO EL DATO A LA CADENA

RET

END

PROGRAMA DE COMPROBACIÓN:

NAME PROGRAMA_COMPROBACION

; Comprobación del algoritmo para entrar dato por derecha

; o izquierda

EXTRN CODE (ENT_DATO)

PUBLIC DIR_BYTEALTO

PUBLIC CANT_BYTES

PUBLIC BANDERA

PUBLIC DATO

DIR_BYTEALTO EQU 22h; Dirección apunta a dato más significativo

CANT_BYTES EQU 03H; cantidad de datos

BANDERA EQU 00H; Sentido de entrada

DATO EQU 45h; dato a entrar

CALL ENT_DATO

END

4.4.10.2.- El máximo y el mínimo de una tabla.

Para determinar el máximo de una tabla puede inicializarse una variable con el menor valor que puede

tomar un byte (00), tal valor debe compararse con cada uno de los elementos de forma tal que la variable

acumule el mayor valor (FFh). De forma idéntica se puede obtener el mínimo, pero ahora la variable debe

inicializarse con el mayor valor. Un método alternativo puede ser realizar la búsqueda por el método de la

burbuja.

Ejemplo 4.37:

NAME MAXIMO_DE_TABLA

;=============================================================================

;PROPÓSITO DEL PROGRAMA:Buscar el maximo valor de una tabla de N bytes

;=============================================================================

;PARAMETROS DE ENTRADA:

;

;R0-Apunta a la direccion inicial de la tabla

;B-Contiene la cantidad de elementos de la tabla

;=============================================================================

;FORMA DE LLAMADO:CALL MAXIMO

;=============================================================================

;REGISTROS UTILIZADOS:A,R0,DIR_DATO:30H,B

;=============================================================================

;BYTES QUE OCUPA EN MEMORIA: 20

;=============================================================================

Page 48: Ensamblador

Fundamentos del lenguaje ensamblador

282

;EJEMPLO:

; Entrada:

; Si R0=20H B=3 (20..22H)=(22H,44H,77H)

; Salida:

; 30H=77H

;=============================================================================

PUBLIC MAXIMO

EXTRN NUMBER (DIR_BYTEBAJO)

EXTRN NUMBER (CANT_BYTES)

MAX_C SEGMENT CODE

RSEG MAX_C

MAXIMO:

Mov B, #CANT_BYTES;

Mov R0, #DIR_BYTEBAJO;

mov A,@R0 ;Toma dato

mov 30H,A ;a memoria

MAX:mov A,@R0 ;próximo dato

cjne A, 30H, NOIGUAL ;se compara

NOIGUAL:jc NOMAX

mov 30H,A ;EN 30H EL NUEVO MAXIMO

NOMAX:inc R0

djnz B,MAX

ret

END

PROGRAMA DE COMPROBACIÓN:

NAME PROGRAMA_COMPROBACION

; Comprobación del algoritmo para búsqueda del máximo

EXTRN CODE (MAXIMO)

PUBLIC DIR_BYTEBAJO

PUBLIC CANT_BYTES

DIR_BYTEBAJO EQU 20h; Dirección menos significativa de la tabla

CANT_BYTES EQU 03H; Número de datos de la tabla

CALL MAXIMO

END

Ejemplo 4.38:

NAME MINIMO_TABLA

;=============================================================================

;PROPÓSITO DEL PROGRAMA:Buscar el minimo valor de una tabla de N bytes

;=============================================================================

;PARAMETROS DE ENTRADA:

;

;R0-Apunta a la direccion inicial de la tabla

;B-Contiene la cantidad de elementos de la tabla

;=============================================================================

;FORMA DE LLAMADO:CALL MINIMO

;=============================================================================

Page 49: Ensamblador

Fundamentos del lenguaje ensamblador

283

;REGISTROS UTILIZADOS:A,R0,DIR_DATO:30H,B

;=============================================================================

;BYTES QUE OCUPA EN MEMORIA: 20

;=============================================================================

;EJEMPLO:

; Entrada:

; Si R0=20H B=3 (20..22H)=(22H,44H,77H)

; Salida:

; 30H=22H

;=============================================================================

PUBLIC MINIMO

EXTRN NUMBER (DIR_BYTEBAJO)

EXTRN NUMBER (CANT_BYTES)

MIN_C SEGMENT CODE

RSEG MIN_C

MINIMO:

Mov B, #CANT_BYTES;

Mov R0, #DIR_BYTEBAJO;

mov A,@R0 ;toma dato

mov 30H,A ;primer dato a memoria

MIN:mov A,@R0

cjne A,30H,NOIGUAL

NOIGUAL:jnc NOMIN

mov 30H,A ;en 30H el mínimo

NOMIN:inc R0

djnz B,MIN

ret

END

PROGRAMA DE COMPROBACIÓN:

NAME PROGRAMA_COMPROBACION

; Comprobación del algoritmo para búsqueda del mínimo

EXTRN CODE (MINIMO)

PUBLIC DIR_BYTEBAJO

PUBLIC CANT_BYTES

DIR_BYTEBAJO EQU 20h; Dirección menos significativa de la tabla

CANT_BYTES EQU 03H; Número de datos de la tabla

CALL MINIMO

END

La clasificación por burbujas: Existe una estructura donde un conjunto de elementos está desordenado en

una tabla y puede que sea necesario que estos elementos adopten un orden progresivo. Una técnica de cla-

sificación es la denominada clasificación por burbujas.

En la clasificación por burbujas cada elemento del dato se compara con el precedente y se intercambia con

él si su valor es inferior. Así, el dato de menor valor va "emergiendo" hacia la parte superior de la tabla. La

clasificación se ha completado cuando no tienen lugar más intercambios.

Page 50: Ensamblador

Fundamentos del lenguaje ensamblador

284

Ejemplo 4.39:

Ordene en orden ascendente la siguiente tabla:

1

17

101

2

5

45

37

16

3

Para solucionar este problema, se deben ejecutar seis pasos, aparte del final, donde se determina que no

hacen falta más intercambios para tener clasificada la tabla.

Los pasos a desarrollar para clasificar por burbujas son:

Origen Después del Después del Después del

paso 1 paso 2 paso 3

1 1 1 1

17 17* 2 2

101* 2* 5 5

2* 5* 17 17*

5* 45* 37* 16*

45* 37* 16* 3*

37* 16* 3* 37

16* 3* 45 45

3* 101 101 101

Después del Después del Después del

paso 4 paso 5 paso 6

1 1 1

2 2 2

5 5* 3

16* 3* 5

3* 16 16

17 17 17

37 37 37

45 45 45

101 101 101

* - Significa que los valores se intercambian.

Nótese como es conveniente establecer dos punteros para comparar los datos de la lista.

Ejemplo 4.40:

Page 51: Ensamblador

Fundamentos del lenguaje ensamblador

285

NAME BURBUJA

;=============================================================================

;PROPÓSITO DEL PROGRAMA:Ordenar una tabla de N bytes

;=============================================================================

;PARAMETROS DE ENTRADA:

;

;R0-Apunta a la direccion inicial de la tabla

;B-Contiene la cantidad de elementos de la tabla

;=============================================================================

;FORMA DE LLAMADO:CALL BURBUJA

;=============================================================================

;REGISTROS UTILIZADOS:A,R0,B

;=============================================================================

;BYTES QUE OCUPA EN MEMORIA: 26

;=============================================================================

;EJEMPLO:

; Entrada:

; Si R0=20H B=3 (20..22H)=(22H,77H,66H,11H)

; Salida:

; (20..22H)=(11H,22H,66H,77H)

;=============================================================================

PUBLIC BURBUJA

EXTRN NUMBER (DIR_BYTEBAJO)

EXTRN NUMBER (CANT_BYTES_M1)

BURB SEGMENT CODE

RSEG BURB

BURBUJA:

Mov B, #CANT_BYTES_M1;

Mov R0, #DIR_BYTEBAJO;

mov r1, #00h;

Prox_comp:

mov A,@R0 ; toma dato

inc r0 ; proximo dato

subb a,@r0

jnc intercambio

inc r1 ; cantidad de acarreos

Sigo:

djnz B,Prox_comp

cjne r1,#CANT_BYTES_M1,BURBUJA

ret

intercambio:

mov a,@r0

dec r0 ; dirección anterior

xch a,@r0

inc r0

mov @r0,a

sjmp Sigo

end

PROGRAMA DE COMPROBACIÓN: NAME PROGRAMA_COMPROBACION

; Comprobación del algoritmo para ordenar por burbuja

Page 52: Ensamblador

Fundamentos del lenguaje ensamblador

286

EXTRN CODE (BURBUJA)

PUBLIC DIR_BYTEBAJO

PUBLIC CANT_BYTES_M1

DIR_BYTEBAJO EQU 20h; Dirección menos significativa de la tabla

CANT_BYTES_M1 EQU 03H; Número de datos de la tabla menos 1

CALL BURBUJA

END

4.4.11.- Las subrutinas de demora.

La subrutina de demora se utiliza en aquellas aplicaciones que requieren de determinada acción cada

cierto período de tiempo bien definido. Ello puede ser en aplicaciones de Entrada/Salida para poder

brindar intervalos de tiempo con longitudes específicas y crear pulsos de determinada frecuencia y

duración.

Ejemplo 4.41:

Obtenga un pulso en "1" lógico con una duración de N msegs.

Un programa genérico puede implementarse de la siguiente forma:

OUT (PTO_1), A

--------

-------- ; Demora de N msegs

--------

OUT (PTO_2),A

donde PTO_1 y PTO_2 pueden ser dos terminales de puerto como se muestran en la fig. 4.6.

PTO_1

PTO_2

DEMORA

N mseg

7474

D2

CLK3

Q5

Q6

PR

4C

L1

Fig. 4.6.- Método para obtener un pulso de duración específica.

El ejemplo anterior puede generalizarse a una señal de determinada frecuencia y ciclo útil impuesto por

programa a partir de la aplicación.

Page 53: Ensamblador

Fundamentos del lenguaje ensamblador

287

Las rutinas de demora pueden también facilitar el autochequeo, donde se espera determinado tiempo a

que un periférico ( como puede ser un impresor) esté listo para la transferencia.

La atención a un teclado necesita la supresión del tiempo de rebote (tiempo de establecimiento de los

contactos metálicos de las teclas), para el cual la generación de un tiempo de espera por programa puede

ser útil.

Para elaborar una rutina de demora puede utilizarse la siguiente fórmula:

Treal = Tfijo + Tlazo + Tajuste (4.1)

donde:

Treal =Tiempo deseado para la rutina de demora.

Tfijo =Tiempo que se demora en la ejecución de instrucciones no incluidas en el lazo de espera.

Tlazo =Tiempo que se demora en la ejecución de un lazo.

Tajuste =Tiempo que es necesario adicionar para obtener la duración total deseada.

Una secuencia ilustrativa de un programa de demora de propósito general para un microprocesador

genérico puede definirse de la siguiente forma:

SALVO REGISTROS (T1) ; Salvar a la pila los registros

; utilizados por el programa de

; demora.

INICIALIZO CONTADOR (T2) ; Se inicializa el valor del registro

; de control del lazo

LAZO:

DECREMENTO CONTADOR(T3);

SALTO SI NO ES CERO A LAZO(T4) ; Permite el control iterativo

; el valor de T4 puede ser

;diferente cuando se transfiere

; a LAZO con respecto

; a la ejecución de la

; próxima instrucción

RECUPERO REGISTROS (T5)

RETORNO (T6)

Los tiempos de demora del anterior algoritmo pueden determinarse a través de la siguiente expresión:

Tfijo =T1+T2+T5+T6+Tcall (4.2)

y

Tlazo =NN(T3+T4)-m (4.3)

donde:

NN =Valor con que es inicializado el contador.

Page 54: Ensamblador

Fundamentos del lenguaje ensamblador

288

Tcall =Tiempo que demora en ejecutarse la instrucción CALL que llama a la rutina de demora.

m =Valor de diferencia entre el tiempo que se demora la instrucción de salto en ir a LAZO con respecto a

la ejecución de la próxima instrucción.

Por ejemplo, una rutina de demora implementada para un microcontrolador de la serie MCS‟51 se

muestra a continuación:

DEMORA: PUSH DPL ; T1 =24t

MOV DPL,NN ; T2 =24t

LAZO: NOP ; T3 =12t

DJNZ DPL,LAZO ;T4 =24t si salta

;T4 =24t si no salta

POP DPL ;T5 =24t

RET ;T6 =24t

Donde t es el período del reloj externo que se ha conectado al microcontrolador.

La anterior demora tendría la siguiente duración:

Treal =Tfijo+Tlazo

Tfijo =T1+T2+T5+T6+Tcall=120t

Tlazo =NN(T3+T4) =NN(36)t

Treal =(120+NN(36))t

Si el microcontrolador trabaja a una frecuencia de 12MHz y el número de iteraciones se fijara en 12,

entonces la demora sería:

Treal =(120+12(36))(1/12MHz)=46segs.

Nótese como el valor de m (ver (4.3)), dentro de tiempo de lazo, no ha sido considerada en el ejemplo

anterior, ello viene dado porque el tiempo que se demora en saltar la instrucción DJNZ (que por cierto

tiene incorporada en sí el decremento de la variable contadora junto al salto) a LAZO es el mismo que el

que demora en ir a la próxima instrucción cuando la condición se cumple, lo cual no ocurre así si tal

programa fuese desarrollado para el microprocesador Z80:

PUSH DE ; T1=11t

LD D,NN ; T2=7t

LAZO: DEC D ; T3=4t

JR NZ,LAZO ; T4=12t SI SALTA

; T4=7t SI NO SALTA

POP DE ; T5=10t

RET ; T6=10t

En tal caso el tiempo de demora sería:

Tfijo =T1+T2+T5+T6 =55t

Tlazo=NN(T3+T4)-m=NN(4t+12t)-5t

Page 55: Ensamblador

Fundamentos del lenguaje ensamblador

289

donde m (definido por T4) es igual a 5t (el equivalente a 12t-7t).

Ejemplo 4.42:

Implemente una rutina de demora de 1mseg. para el microprocesador Z80, suponga que se trabaja a una

frecuencia de 1MHz.

Solución:

Se utilizará la misma rutina anteriormente comentada. Para obtener 1mseg. puede utilizarse (4.1):

Treal=Tfijo+Tlazo+Tajuste

Tfijo+Tlazo =55t+NN(4t+12t)-5t =1mseg.

Despejando NN, resulta:

NN = (1mseg-50t)/16t

Como t para un reloj de 1MHz es 1seg, resulta:

NN= 59.3 59

Nótese como la aproximación de NN es por defecto para que no se obtenga un tiempo superior al deseado.

El tiempo resultante sería:

Tfijo + Tlazo =(50+59(16))1seg = 994seg.

El tiempo de ajuste necesario para obtener 1mseg. sería:

Tajuste=Treal-(Tfijo+Tlazo) =1mseg-994seg =6seg.

Es necesario entonces adicionar una instrucción cuya duración sea de 6 períodos de reloj para obtener los

6seg. El programa final, que genera una demora de 1mseg puede implementarse:

PUSH DE

LD D,59D

LAZO:DEC D

JR NZ,LAZO

INC DE ; Incorpora el tiempo de ajuste

POP DE

RET

Aumentando el tiempo en una subrutina de demora.

La subrutina previamente elaborada posee un tiempo máximo límite que puede brindar (ello ocurre

cuando se inicializa NN en 00, lo que permite un lazo de 256 iteraciones). Cuando son necesarios

tiempos superiores, basta anidar lazos. Un ejemplo de subrutina desarrollada para el Z80 sería:

PUSH DE ;T1

Page 56: Ensamblador

Fundamentos del lenguaje ensamblador

290

LD D,NN ;T2

LAZO2:

LD E,MM ;T3

LAZO1:

DEC E ;T4

JR NZ,LAZO1 ;T5

DEC D ;T6

JR NZ,LAZO2 ;T7

POP DE ;T8

RET ;T9

Ahora el tiempo fijo sería:

Tfijo=T1+T2+T8+T9+Tcall=55t

y el tiempo del lazo:

Tlazo=NN(T3+MM*(T4+T5)-5+T6+T7)-5

Nótese como, si la rutina fuese elaborada para un microprocesador donde el tiempo de salto es el mismo

que el tiempo en ir a ejecutar la próxima instrucción ( por ejemplo, la serie MCS‟51), el término -5 no

tendría que considerarse.

Ejemplo 4.43:

NAME Demora_1

;**********************************************************

; Este programa permite: Hacer una demora cuyo rango

; para un reloj de 12 MHz ( serie MCS‟48) esta entre

; .007 mseg <= Td <= 1.282 mseg

; El tiempo puede ser calculado por la

; siguiente formula:

; Td = (24 + NN*60)t

; Siendo t : Período del reloj del sistema

; NN : Dato a decrementar que debe ser

; definido por el programador, debe

; estar en el registro R2.

;**********************************************************

; Bytes que ocupa en memoria: 6 Bytes.

;**********************************************************

; Parametros de entrada:

; R2 = NN ; Dato a decrementar.

;**********************************************************

; Registros utlilizados: A,R2.

;**********************************************************

; Forma de llamado: Call Demora1

;**********************************************************

Demora1: Mov A,R2 ; 12 periodos de reloj.

Dec A ; 12 periodos de reloj.

Mov R2,A ; 12 periodos de reloj.

JnZ Demora1 ; 24 periodos de reloj.

Ret ; 24 periodos de reloj.

End

Page 57: Ensamblador

Fundamentos del lenguaje ensamblador

291

Ejemplo 4.44:

NAME Demora _2.

;**********************************************************

; Este programa permite: Hacer una demora cuyo intervalo

; para un reloj de 2 MHz es:

; .05 mseg <= Td <= 526.69 mseg

; El tiempo puede ser calculado por la

; siguiente formula:

; Td = 64/FC + MM[20/FC + 16NN/FC]

; Siendo FC : Frecuencia del reloj del sistema

; NN : Dato a decrementar que debe ser

; definido por el programador, debe

; estar en el registro B.

; MM : Dato a decrementar que debe ser

; definido por el programador, debe

; estar en el registro C.

;**********************************************************

; Bytes que ocupa en memoria: 12 Bytes.

;**********************************************************

; Parametros de entrada:

; B = NN : valor a decrementar.

; C = MM ; valor a decrementar.

;**********************************************************

; Registros utlilizados: AF, BC.

;**********************************************************

; Forma de llamado: Call Demora2

;**********************************************************

.Z80

Aseg

Org 100h

Demora2: Push AF ; 11 estados de reloj

Push BC ; 11 estados de reloj

LazD2: Ld A,B ; 9 estados de reloj

LazD1: Dec A ; 4 estados de reloj

Jr nZ,LazD1 ; 12/7 estados de reloj

Dec C ; 4 estados de reloj

Jr nZ,LazD2 ; 12/7 estados de reloj

Pop BC ; 10 estados de reloj

Pop AF ; 10 estados de reloj

Ret ; 10 estados de reloj

End

Se puede tener en consideración que; alternativamente, se pueden implementar demoras utilizando las

siguientes estrategias:

a)A partir de un conjunto de instrucciones que demoren n estados (tiempos pequeños).

b)Lazos independientes unos de otros.

c)Llamar varias veces a una misma rutina.

4.4.12.- La conversión binario-BCD.

Page 58: Ensamblador

Fundamentos del lenguaje ensamblador

292

Para convertir un número binario a BCD debe considerarse cuántas veces puede sustituirse determinada

potencia de 10 (dependiente del rango del número) a un número binario. Para ello supóngase que se tiene

el valor 11101101B (237D), un método para determinar los dígitos en BCD puede ser:

11101101 237

-01100100 -100

------------------ ----- Dígitos de las centenas

10001001 137 igual a 2

-01100100 -100

------------------ -----

00100101 37

-00001010 -10

------------------ ----- Dígitos de decenas

00011011 27 igual a tres

-00001010 -10

------------------ -----

00010001 17

-00001010 -10

------------------ -----

00000111 7 -------- Dígito de unidades

Nótese como para obtener el dígito de las centenas es necesario determinar cuántas veces cabe 100 en el

número binario. Las veces que podrá ser sustraído 10 del número binario determinará el dígito de las

decenas, el número restante serán las unidades. Así, 100 puede ser sustraído (del valor 237D) dos veces

(0010B), 10 puede ser sustraído tres veces (0011B) y el resto (dígito de las unidades) será 7 (0111B). El

número BCD equivalente a 237 será 0010 0011 0111.

4.4.13.- Conversión ASCII-BCD.

Cuando un microprocesador se usa para atender un teclado, los números entran comúnmente en código

ASCII. Por ejemplo, el número 237D se almacenaría en memoria como tres caracteres ASCII:

Número Carácter ASCII

2 00110010

3 00110011

7 00110111

Nótese como los cuatro bits menos significativos del caracter ASCII representa el valor en BCD del

número correspondiente. Por tanto, para convertir caracteres ASCII a BCD basta eliminar los cuatro bits

más significativos ( AND ASCII,#0FH).

4.4.14.- Conversión BCD-binario.

Para convertir un número BCD a binario se debe realizar el proceso inverso a la conversión binario-BCD,

adicionar tantas veces la potencia de 10 como indique la cifra correspondiente en BCD. Si el número a

convertir es 237D (0010 0011 0111), nótese como 0010 representa dos centenas, 0011 tres decenas y

0111 siete unidades. A partir de cero, se puede adicionar 100d tantas veces como indique el número de las

centenas. La cantidad de veces que se sume 10d dependerá del valor del dígito de las decenas y

finalmente el valor del dígito de las unidades debe adicionarse, como se muestra a continuación:

01100100B 100D Se adiciona 100d dos veces

Page 59: Ensamblador

Fundamentos del lenguaje ensamblador

293

+01100100B +100D

-------------- ----------

11001000B 200D

+00001010B + 10D Se adiciona 10d tres veces

-------------- ----------

11010010B 210D

+00001010B + 10D

--------------- ----------

11011100B 220D

+00001010B + 10D

--------------- ----------

11100110B 230D

+00000111B + 7D Se adiciona las unidades

--------------- ---------

11101101B 237D

El resultado sería 11101101B, que representa al valor 237D.

El anterior método puede optimizarse si se considera que para obtener un número binario a partir de un

número decimal es necesario realizar múltiples divisiones por dos donde el primer resto representa el

dígito menos significativo y el último resto de la división el dígito más significativo.

Inicialmente, se coloca en cero la variable donde quedará el resultado binario y se setea el acarreo, el

objetivo de esta operación será el de indicar cuando finaliza el número de rotaciones necesarias para la

formación del número binario. La operación de rotación permite ir introduciendo los restos que devuelve

la operación de división en código BCD de NUMD. Para realizar la división entre dos (ver fig. 4.14 )

debe considerarse el peso de cada bit de acuerdo a la base del número:

7 6 5 4 3 2 1 0 No del bit

80 40 20 10 8 4 2 1 Peso en BCD

128 64 32 16 8 4 2 1 Peso en binario

Nótese como al rotar el número binario a la derecha automáticamente ejecuta la división por dos, pero

cuando el número se interpreta en BCD es necesario considerar la siguiente particularidad: El peso del bit

4 es 10 en BCD, al rotar a la derecha devolvería un peso de 8 puesto que la operación se ha realizado

sobre el número binario, pero al dividir entre dos el número 10 el resultado debe ser 5 en BCD. La

diferencia entre 8 y 5 es tres, por lo que para mantener el formato en BCD debe realizarse la sustracción

del valor 3(011B) al resultado binario. Nótese como algo semejante ocurre con el bit 7, si se introduce un

1 en este ello representa la división por dos de 100d, que es 50. Pero el peso del bit 7 es 80, la diferencia

(30d) debe ser sustraída del número BCD.

Cuando se implementa este algoritmo en múltiple precisión existirán dificultades en cuanto al tratamiento

del acarreo, para ello se puede implementar un contador en vez de utilizar el acarreo como bandera de fin

de conversión.

4.4.15.- La Suma chequeo.

Una operación muy útil para el diseño de equipos electrónicos es la "suma chequeo", que ha sido muy

utilizada para la verificación del estado de las memorias así como para verificar posibles errores en la

transmisión de datos. La suma chequeo se puede efectuar definiendo dos punteros, uno de ellos permitirá

almacenar las direcciones cuyo contenido se irán sumando y el otro a la dirección donde se guarda el

Page 60: Ensamblador

Fundamentos del lenguaje ensamblador

294

resultado. El contenido de la dirección definida por el primer vector se ira sumando con el acumulador y

guardando en la dirección definida por el segundo puntero hasta que se sumen el numero de direcciones

definidas por los datos trasmitidos.

Figura 4.14.- La división por dos de un número en BCD.

Ejemplo 4.45:

NAME SUMA_CHEQUEO

;=============================================================================

;PROPÓSITO DEL PROGRAMA:Determina suma de 16 bytes y almacena el negado

; de ello en dos bytes consecutivos.

;=============================================================================

;PARAMETROS DE ENTRADA:

;

;R0-Puntero a primer dato de la tabla

;=============================================================================

;PARAMETROS DE SALIDA:

;

;Devuelve en 40h, 41h el complemento a dos de la suma de los 16 bytes

;=============================================================================

NUM

BCD

Rotar a la

derecha

NUMBCD

Bit3=1

NUMBCD=

NUMBCD-3

Bit7=1

NUMBCD=

NUMBCD-30

Fin

Page 61: Ensamblador

Fundamentos del lenguaje ensamblador

295

;FORMA DE LLAMADO:CALL CHECK_SUM

;=============================================================================

;REGISTROS UTILIZADOS:A,R0,R2,B

;=============================================================================

;BYTES QUE OCUPA EN MEMORIA: 26

;=============================================================================

CHECK_S SEGMENT CODE

RSEG CHECK_S

CHECK_SUM:

mov r0,#30h ; puntero a datos

mov r2,#16d ; número de datos a sumar

mov a,#00 ; inicio destino

vuelvo:

clr c

addc a,@r0

jnc sigo

inc b ; byte más significativo del resultado

sigo:

inc r0 ; busco proximo byte

djnz r2,vuelvo

; determino complemento a dos y se carga en 40h,41h

cpl a

add a,#01

mov @r0,a ; -sig. en 40h

xch a,b

cpl a

addc a,#00h

inc r0

mov @r0,a ; +sig. en 41h

ret

END