Sunteți pe pagina 1din 10

Tema 6

Introduccin a la Programacin en
Ensamblador
La magia del compilador
Una vez hemos llegado en el estudio de la arquitectura del computador al
punto en que conocemos la ruta de datos, su funcionamiento y sus arquitecturas, es
conveniente justificar la necesidad de que la unidad de control del computador sea
capaz de ejecutar ciertas instrucciones. Haremos esto incluso antes de ver con detalle la
implementacin de la Unidad de Control y la implementacin de las diferentes
arquitecturas, ya que de esta forma justificaremos las instrucciones que creemos.
La programacin en lenguaje ensamblador es ligeramente ms complicada
que la programacin en alto nivel. La complicacin est marcada, fundamentalmente,
por tener que controlar nosotros absolutamente todo lo que el computador tiene que
realizar. Para facilitar la tarea vamos a marcar unas pautas que van encaminadas a
hacernos las cosas ms automticas.
Para la programacin en lenguaje ensamblador vamos a utilizar las tcnicas
aprendidas en algortmica. Como paso previo al desarrollo de un programa en
ensamblador necesitamos tener perfectamente definido lo que pretendemos que haga el
ordenador. Una vez sepamos lo que queremos debemos hacer el programa, pero de
forma directa sino a travs del correspondiente algoritmo; una vez desarrollada la traza
del algoritmo y comprobado que hace lo que pretendemos, el paso siguiente es la
codificacin del algoritmo en lenguaje ensamblador. De esta forma podemos
aprovecharnos de la programacin modular que tanto nos facilita la tarea de la creacin
de programas, en un lenguaje aparentemente hostil a la modularidad.
Para desarrollar el programa lo mejor es tener un esqueleto predefinido e
irlo completando con las partes que son especficas de nuestra aplicacin. Este
esqueleto lo veremos al final cuando ya hayamos estudiado el ncleo de la misma.
Para ayudarnos en el paso del lenguaje algotmico a lenguaje ensamblador
vamos preparar el esqueleto de las estructuras bsicas, de forma que nuestra
programacin sea lo ms homognea y repetitiva que podamos, con la consiguiente
reduccin de errores.
Arquitectura de Ordenadores I

107

Tema 6

Estructura selectiva simple si ... entonces ... fin si


La primera estructura algortmica que vamos a estudiar es :
si condicin entonces
accin
fin si

Esta estructura se podra implementar en ensamblador de la siguiente


forma :
si_001:
entonces_001:
fin_si_001:

condicin
salto_condicional fin_si_001
accin
resto_de_cdigo

Esto nos lleva al primer tipo de instrucciones que vamos a estudiar: los
saltos
Los Saltos
En cdigo mquina la programacin es totalmente secuencial. Una
instruccin se ejecuta detrs de otra indefectiblemente. La nica forma de hacer
programacin estructurada es provocando saltos en la secuencia del programa. Esto
complica notablemente la estructura del programa y su inteligibilidad de cara al
programador (de ah la necesidad de escribir y probar los algoritmos antes de comenzar
a escribir el cdigo mquina).
Los saltos los podemos definir como la ruptura de la secuencia lineal del
programa.
Hay dos tipos de saltos: los incondicionales y los condicionales
Son saltos incondicionales aquellos en los que una vez decodificada la
instruccin el salto se produce siempre. Son tiles para saltar trozos de cdigo de forma
obligatoria y tambin se utilizan para poder hacer algunos trucos que engaen al
microprocesador, en programas muy elaborados. La instruccin de salto suele ser tal
como:
JMP etiqueta

Los saltos condicionales son ms verstiles. El salto solo se produce si se


dan ciertas condiciones, de lo contrario la secuencia del programa contina de forma
normal. Cada microprocesador en concreto tiene sus propios saltos condicionales. El
juego puede ser muy extenso. Algunos de los ms comunes son:
JE Salta si igual
JG Salta si mayor
JGE Salta si mayor o igual
JL Salta si menor
JLE Salta si menor o igual
JZ Salta si es igual a cero

108

Arquitectura de Ordenadores I

Programacin en Ensamblador
JNZ Salta si no cero
JNE Salta si no igual (igual a JNZ)
JS Salta si no signo (si es positivo)
JS Salta si signo (si es negativo)

Para evaluar la condicin tenemos las instrucciones lgicas y aritmticas,


pero las ms comunes son las especficamente de comparacin:
CMP Compara operandos
TEST Test/Comparacin lgica de los dos operandos

Ejemplo
si contador>0 entonces
decrementar contador
fin si

En ensamblador
si_001:
registro

MOV AX, contador

; solo se puede comparar con un

CMP AX, 0
JG entonces_001

; evaluamos la condicin
; si condicin verdadera ejecuto la

JMP fin_si_001

; la condicin no es cierta, omito la

DEC contador

; accin(es)
; resto del cdigo

accin
accin
entonces_001:
fin_si_001:

Esta forma de actuar, aunque es totalmente fiel a la estructura algortmica


no es nada eficiente, ya que se ejecutan dos saltos, con la consiguiente prdida de
tiempo y el cdigo sale tambin ms extenso. Esta forma que se presenta a continuacin
es mucho ms eficiente, ya que solamente rompe la secuencia lineal del programa en un
caso; cuando la condicin es falsa.
si_001:
registro

MOV AX, contador

; solo se puede comparar con un

CMP AX, 0
JLE fin_si_001
DEC contador

; evaluamos la condicin
; salto si complementario de condicin
; accin(es)

fin_si_001:

Hemos de hacer hincapi en que la condicin de salto es la complementaria


de la condicin que tenemos en la estructura algortmica. A partir de ahora, todas las
implementaciones que hagamos las codificaremos solamente con la forma ms eficiente.
Hemos introducido, adems, una nueva instruccin aritmtica, DEC, cuya misin es
decrementar el operando que le sigue.

Estructura selectiva simple si ... entonces ... sino ... fin


si
si condicin entonces
accin1
sino

Arquitectura de Ordenadores I

109

Tema 6
accin2
fin si

Esta estructura se implementara en ensamblador de la siguiente forma :


si_001:
sino_001:
entonces_001:
fin_si_001:

condicin
salto_condicional entonces_001
accin2
JMP fin_si_001
accin1
resto_de_cdigo

Donde se ve la necesidad del uso de un salto incondicional para romper la


linealidad del programa.
Ejemplo
si contador>0 entonces
decrementar contador
sino
salir := 1;
fin si

En ensamblador
si_001:
registro

accin1
sino_001:

entonces_001:
fin_si_001:

MOV AX, contador

; solo se puede comparar con un

CMP AX, 0
JG entonces_001

; evaluamos la condicin
; si condicin verdadera ejecuto la

MOV AX, #1
MOV salir, AX
JMP fin_si_001
DEC contador

;
;
;
;
;

ponemos el valor de salir en AX


actualizamos la variable salir, accin2
no ejecuto la accin1
ejecuto la accin1
resto del cdigo

Estructura repetitiva mientras ... hacer ... fin mientras


mientras condicin
accin
fin mientras

Esta estructura se implementara en ensamblador de la siguiente forma :


mientras_001:

condicin
salto_condicional fin_mientras_001
accin
JMP mientras_001
fin_mientras_001: resto_de_cdigo

Ejemplo
mientras salir<>0 hacer
contador := contador + 1
fin mientras

En ensamblador quedara:
mientras_001:

110

MOV AX, salir

; solo se puede comparar con


; un registro
Arquitectura de Ordenadores I

Programacin en Ensamblador
CMP AX, 0
JZ fin_mientras_001
INC contador
JMP mientras_001

;
;
;
;
;

evaluamos la condicin
si la condicin es falsa termino
accin(es)
la condicin no es cierta, omito
la accin

fin_mientras_001: resto_de_cdigo

Donde hemos visto una nueva instruccin aritmtica, INC, cuya misin es
incrementar el operando que viene a continuacin.

Estructura repetitiva repetir ... hasta que ...


repetir
accin
hasta que condicin

Esta estructura se implementara en ensamblador de la siguiente forma:


repetir_001:

accin
condicin
salto_condicional repetir_001

Ejemplo
repetir
distancia := distancia + 3
hasta que distancia > 100

En ensamblador quedara :
repetir_001:

MOV AX, distancia


ADD AX, 3
MOV distancia, AX
CMP AX, 100
JLE repetir_001
resto_de_cdigo

;
;
;
;
;
;

solo se puede operar con el


acumulador
incrementamos en 3 (accin)
actualizamos la variable
evaluamos la condicin
si la condicin es falsa, repito

En este caso aprovechamos que AX ya contiene el valor de la distancia


para hacer la comparacin. Si nuestras acciones no dejan en ningn registro el valor que
necesitamos para hacer la comprobacin de la condicin, hay que cargar algn registro
con el valor adecuado para la comprobacin.
Hay que tener en cuenta que en la evaluacin de la condicin de nuevo
hemos utilizado la comparacin con el complementario de lo que realmente pretende el
algoritmo. De esta forma optimizamos el cdigo.

Estructura repetitiva desde ... hasta ... hacer ... fin


desde
desde variable := inicio hasta final hacer
accin
fin desde

Arquitectura de Ordenadores I

111

Tema 6

Esta estructura se caracteriza por tener los lmites bien definidos, lo cual se
corresponde en ensamblador con un bucle tpico.
desde_001:
hasta_001:

fin_desde_001:

MOV CX, inicio


CMP CX, final
JG fin_desde_001
accin
INC CX
MOV variable, CX
JMP hasta_001
resto_de_cdigo

;
;
;
;
;
;
;

cargamos el valor inicial


comparo el comienzo con el final
salimos del bucle
accin a realizar
incrementamos el contador del bucle
actualizamos la variable1
evaluamos la siguiente iteracin

Como podemos apreciar en esta implementacin utilizamos dos saltos con


el consiguiente perjuicio. Veamos como hacerlo saltando una sola vez.
desde_001:

MOV CX, inicio


CMP CX, final
JG fin_desde_001
accin
INC CX

hasta_001:

fin_desde_001:

MOV variable, CX
CMP CX, final
JLE hasta_001
resto_de_cdigo

;
;
;
;
;
;
;
;
;

cargamos el valor inicial


comparo el comienzo con el final
salimos del bucle
accin a realizar
incrementamos el contador
del bucle
actualizamos la variable
hemos llegado al final ?
siguiente iteracin del bucle

Ntese que siguen habiendo dos saltos, pero el primero slo se evala la
primera vez y a continuacin, dentro del bucle propiamente dicho, solo se evala el
segundo una vez por iteracin.
Ejemplo
para i := 1 hasta N hacer
a := i
fin para

En ensamblador quedara :
desde_001:

hasta_001:

fin_desde_001:

MOV CX, #1
CMP CX, N
JG fin_desde_001
MOV a, CX
INC CX
MOV i, CX
CMP CX, N
JLE hasta_001
resto_de_cdigo

;
;
;
;
;
;
;
;

cargamos el valor inicial


comparo el comienzo con el final
salimos del bucle
accin a realizar
incrementamos el contador del bucle
actualizamos la variable
hemos llegado al final ?
siguiente iteracin del bucle

Hay un caso particular de esta estructura, cuando el final es cero.


desde variable := inicio hasta 0 paso -1 hacer
accin
fin desde

Solo es necesario si vamos a utilizar la variable dentro del bucle. Si la vamos a utilizar al salir del bucle solo sera
necesario actualizarla una vez fuera del bucle. Si no se utiliza nunca sobra su declaracin y cualquier asignacin.

112

Arquitectura de Ordenadores I

Programacin en Ensamblador

En este caso particular podemos recurrir al uso eficiente del juego de


instrucciones del microprocesador. Pudiendo quedarnos el cdigo de la siguiente
forma :
desde_001:

hasta_001:

fin_desde_001:

MOV CX, inicio


CMP CX, 0
JG fin_desde_001
accin
MOV variable, CX
LOOP hasta_001
resto_de_cdigo

;
;
;
;
;
;

cargamos el valor inicial


comparo el comienzo con el final
salimos del bucle
accin a realizar
actualizamos la variable
siguiente iteracin del bucle si CX0

Estructura selectiva mltiple segn ... hacer ... fin segn


segn valor hacer
1: accin1
2: accin2
3: accin3

n: accinN
sino
accinD
fin segn

La forma ms sencilla de implementar esta opcin es mediante una tabla de


salto. En este tipo de tabla se almacenan las direcciones de las rutinas de las acciones
correspondientes a cada uno de los casos posibles. Este mtodo slo es posible si las
opciones son consecutivas la una a la otra.
segun_001:

segun_ma_001:

segun_me_001:

MOV BX, valor


; parmetro de salto
DEC BX
; el primer desplazamiento es 0
CMP BX, 0
; compruebo el rango inferior
JGE segun_ma_001
; salto si mayor o igual que 0
MOV BX, sino_001-Tsalto_sgn_001
; desplazamiento de sino
JMP segn_me_001
; saltamos directamente a sino
SHL BX, 1
; multiplico por 2 (son enteros)
CMP BX, sino_001-Tsalto_sgn_001
; compruebo el rango superior
JL segun_me_001
; salto si menor que lmite
MOV BX, sino_001-Tsalto_sgn_001
; desplazamiento del caso por defecto
MOV IP, Tsalto_sgn_001[BX]
; salto encubierto
; aqu no llega nunca

; implementacin de las acciones


sgn_ac1_001:
accin1
JMP fin_segn_001
sgn_ac2_001:
accin2
JMP fin_segn_001
sgn_ac1_001:
accin3
JMP fin_segn_001

sgn_acN_001:
accinN
Arquitectura de Ordenadores I

;
;
;
;
;
;

ejecuta la accin 1
ejecutamos la siguiente sentencia
ejecuta la accin 2
ejecutamos la siguiente sentencia
ejecuta la accin 1
ejecutamos la siguiente sentencia

; ejecuta la accin N
113

Tema 6

sgn_acD_001:
fin_segun_001:

JMP fin_segn_001
accinD
resto_del_cdigo

; ejecutamos la siguiente sentencia


; ejecuta la accin por defecto

Cuando las opciones no son consecutivas la una a la otra hay dos


opciones: utilizar un diccionario de smbolos, hacer todas las comparaciones y los
saltos correspondientes uno por uno. Este ltimo caso es factible cuando las opciones
son pocas, si son muchas el mtodo del diccionario es ms eficiente y sencillo de
codificar.
; Tabla de salto del segn 001
Tsalto_sgn_001: dw sgn_ac1_001
dw sgn_ac2_001
dw sgn_ac3_001

dw sgn_acN_001
sino_001:
dw sgn_acD_001
; diccionario del segn 001
dicc_sgn_001:
dB +-*/= ^
f_dicc_sgn_001:
; comienzo de la implementacin del segn 001
; bsqueda en el diccionario
segn_001:
MOV BX, offset dicc_sgn_001
; BX apunta al diccionario
DEC BX
; para el preincremento
MOV CX, f_dicc_sgn_001-dicc_sgn_001
; cargo en CX el nmero de smbolos
MOV AL, valor
; pongo en AL el valor del segn
bucle_001:
INC BX
; preincremento de BX (++BX)
CMP AL, [BX]
; compruebo si valor est en la tabla
LOOPNE bucle_001
; cierra el bucle si no son iguales y
; CX es mayor que cero
SUB BX, dicc_sgn_001 ; dejo en BX la posicin relativa
; del smbolo
SHL BX, 1
; multiplico BX por 2, la direccin
; tiene la longitud de una palabra
CMP CX, 0
; compruebo la forma de salir
JNZ salto_sgn_001
; salta si el smbolo est en la tabla
MOV BX, sino_sgn_001-tsalto_sgn_001
; dejo en BX el desplazamiento
; del caso por defecto
salto_sgn_001:
MOV IP, Tsalto_sgn_001[BX]
; salto encubierto
; aqu no llega nunca
; el resto del cdigo es igual que en el ejemplo del caso anterior
; implementacin de las acciones
sgn_ac1_001:
accin1
; ejecuta la accin 1
JMP fin_segn_001
; ejecutamos la siguiente sentencia
sgn_ac2_001:
accin2
; ejecuta la accin 2
JMP fin_segn_001
; ejecutamos la siguiente sentencia
sgn_ac1_001:
accin3
; ejecuta la accin 3
JMP fin_segn_001
; ejecutamos la siguiente sentencia

114

Arquitectura de Ordenadores I

Programacin en Ensamblador

sgn_acN_001:
sgn_acD_001:
fin_segun_001:

accinN
JMP fin_segn_001
accinD
resto_del_cdigo

; ejecuta la accin N
; ejecutamos la siguiente sentencia
; ejecuta la accin por defecto

Problema:
Se recomienda al alumno la implementacin del segn por el mtodo de
las comparaciones sucesivas.

Subprogramas
Por ltimo nos queda ver, para terminar esta introduccin, las llamadas a
subprogramas. Las llamadas vienen a ser algo as como:
Subprograma modulo_1 (parmetros)
variables
inicio
accin1
accin2

accinN
fin subprograma

Para implementar los subprogramas tenemos que introducir una nueva


instruccin en nuestro lenguaje ensamblador. Esta instruccin es la llamada a
subrutina, que en mnemnico suele representarse por CALL (llamar), BSR (Branch
to SubRoutine, Ramificacin a subrutina), JSR (Jump to SubRoutine, salto a subrutina),
o algo similar. Para terminar la subrutina, tenemos que decirle al procesador que la
llamada ha terminado, esto lo hacemos indicndole RET (RETorno) o algo similar. De
esta forma, la codificacin en ensamblador quedara como sigue.
; declaracin del mdulo 1
Modulo_1:
accin1
accin2

accinN
RET

; Llamada al mdulo 1
CALL modulo_1
resto_de_cdigo

Una representacin de lo que significa la llamada a un procedimiento,


desde el punto de vista del flujo del programa, se puede observar en la Figura 1:

Arquitectura de Ordenadores I

115

Tema 6

CALL modulo_1

CALL modulo_1

Accin_1
Accin_2

Accin_N
RET

Figura 1. Llamada a subrutina o procedimiento

Nos falta hablar del paso de parmetros. Para pasar los parmetros
podemos utilizar los registros del procesador. Esto tiene el inconveniente de que los
parmetros son siempre por referencia, el resultado que tome el registro aparece en el
programa principal tambin, con el consiguiente inconveniente. Si los pasamos mediante
variables, no podemos llamar a un procedimiento desde dentro de l mismo, puesto que
destruiramos las variables de la primera llamada. Por otro lado tenemos que recordar
de alguna forma el punto donde hay que retornar cuando se termine de ejecutar el
procedimiento.
Llegamos de esta forma a la PILA. La pila es una zona de memoria donde
trabajaremos de una forma especial y que nos permite resolver los problemas
planteados anteriormente. El juego de instrucciones requiere dos nuevos elementos:
meter un dato en la pila (PUSH) y retirar un dato de la pila (POP). Cuando estudiemos
los distintos modos de direccionamiento hablaremos con ms en detalle de estas
instrucciones.

116

Arquitectura de Ordenadores I

S-ar putea să vă placă și