Sei sulla pagina 1di 13

TALLER DE PROGRAMACION EN BAJO NIVEL

REGISTROS
Los registros de datos, como su nombre indica, contienen generalmente datos. (S, lo s, no
parecen gran cosa, pero es lo que hay) A veces se les llama "de propsito general", y la verdad
es que es un nombre ms apropiado, si bien un poco ms largo. Aunque tiene distinto nombre
cada uno de ellos, cuentan bsicamente con la misma funcionalidad, con algunas excepciones.
Determinadas operaciones por ejemplo la multiplicacin exige que los operandos estn en
registros especficos.
AX es a menudo llamado acumulador, ms por motivos histricos que por otra cosa.
BX se puede usar como registro base en algunos modos de direccionamiento, es decir,
para apuntar a posiciones de memoria con l.
CX es usado por algunas instrucciones como contador (en ciclos, rotaciones..)
DX o registro de datos; a veces se usa junto con AX en esas instrucciones especiales
mencionadas.
Cada registro de estos est dividido a su vez en dos registros de 8 bits, que pueden ser ledos o
escrito de manera independiente:
REGISTRO
AX
BX
CX
DX

HIGH
1111
1111
1111
1111

LOW
1111
1111
1111
1111

1111
1111
1111
1111

1111
1111
1111
1111

Aparte de los registros x8086 nos provee otros tipos de estructura como ser:
PILA: La pila o stack es bsicamente una estructura de almacenamiento para los registros antes
el almacenamiento era restringido a un mximo 7 registros almacenados, pero ahora con esto
ya no es tan restringido pudiendo la pila almacenar FFF9 registros en ella. Cabe mencionar que
la pila solo almacena registros de 16 bits y no as de 8 bits. Tambin vale la pena mencionar
que usa LIFO (Last In Fisrs Out) en su estructura. Con las aclaraciones mencionadas
anteriormente se sugiere manejar la pila con el menor de datos almacenados posible.
Para almacenar un registro en la pila se usa la siguiente sintaxis
push origen
Siendo:
push -> Una palabra reservada
origen -> El registro de origen

Para des empilar un registro almacenado se usa la siguiente sintaxis


pop destino

Siendo:
pop -> Una palabra reservada
destino -> registro destino donde se des empilara
VARIABLES
A veces requerimos almacenar algn valor en alguna variable o simplemente mostrar una
cadena en la consola para hacer cualquiera de estas opciones es necesario tener declarada una
variable la sintaxis para declarar una variable es la siguiente:
Identificador tipo valor
Siendo:
identificador -> un nombre para nuestra variable
tipo -> podran ser

db: Este define un byte lo que es lo mismo decir 8 bits. Lo que nos dice en otra
manera que solo podemos almacenar 8 bits en esta variable recordemos que un
registro est compuesta por 16 bits la mitad serian 8 bits entonces vale decir que el
mximo rango que se podr almacenar solo ser o lo que este en la parte Alta(*H) del
registro o en la parte baja(*L) o bien en otras palabras podra almacenar FF o su
equivalente en decimal 255 como mximo valor.
dw: Este define un Word lo que es lo mismo decir 16 bits. Entonces como mximo
valor podramos almacenar FFFF o su equivalente 65535. Toma todo el registro como
valor mximo.

valor -> asignamos un valor de acuerdo al tamao que definimos anteriormente y si


ese valor es algo que generaremos despus se puede poner ? que dice que no se conoce
en este punto
CADENAS
8086 maneja las cadenas como un array de caracteres como son caracteres su mximo valor
ser 16 bits as que cuando declaremos una cadena en x8086 se tiene que poner de tipo db por
lgica la forma en como una cadena es recorrida es algo curiosa. El lenguaje ensamblador nos
provee 3 punteros a memoria estos son el si, di, y bi este ltimo solo se usa si y solo si los dos
anteriores estn siendo usados.
Como operamos con cadenas. En ensamblador una cadena se identifica porque tiene un
carcter especial de fin el cual es $ siempre una cadena tiene que tener este carcter al
ltimo de ello esto le indica que es el fin de esta misma.
Ejemplo:
Para declarar una variable que tenga como cadena un hola mundo seria de la siguiente forma
cadena db hola mundo$

NUMEROS
Cualquier operacin que se haga en los registros ser en hexadecimales, pero esto no infiere al
modo en cmo debemos declarar un nmero. Para declarar un numero como variable
necesitamos analizar ciertos puntos el numero ira creciendo? ser una constante?
Recordemos que un registro almacena valores de 8 bits (255) y 16 bits (65535) como mximo
entonces teniendo idea de eso podemos definir el tamao en memoria a almacenar
contador db 0
numero dw 4000
OPERACIONES BASICAS
MOVER(mov) : esta instruccin nos permite mover datos entre registros o tambin mover
variables a registros su sintaxis es la siguiente.
mov origen, destino
donde:
origen -> es el registro donde se tiene la informacin
destino -> es el registro el cual ira la informacin.
La mecnica es la siguiente: Se obtiene la informacin del origen, verifica si el destino es del
mismo tamao, si lo es borra lo que hay en el destino y remplaza por la informacin.
Nota
Cabe mencionar que el comando mov solo mueve registros del mismo tamao al igual que las
variables.
Ejemplos:
mov bx,0 -> Cuando hacemos esta instruccin lo que le decimos es mover al registro bx 0 algo a
tomar en cuenta es que toda operacin sobre los registros es en hexadecimales as que cualquier
valor que se mande que no sea un registro ser convertido a hexadecimal.
mov ax,10 -> En el registro ax despus de realizar este comando se tendr 000A
mov ax,10o -> En el registro ax se tendr lo siguiente 0008 porque estamos diciendo que en ax
se almacenara el valor 10 en sistema octal para decir que un nmero esta en base ocho tenemos
que poner un o al final del numero en este ejemplo 10o es 8 en hexadecimal.
mov ax,11101111b -> En el registro ax se tendr lo siguiente 00EF lo mismo que en el caso
anterior el nmero 11101111 que est en binario se convierte a hexadecimal y lo almacenara
en ax para que ensamblador se d cuenta que el nmero que estamos asignando esta en binario
tenemos que poner b al final del nmero.
mov ax,10h -> lo que tendremos en ax sera 0010 en este caso no convertir a hexadecimal
porque al poner h al final del numero decimos que el nmero es hexadecimal as que solo lo
mueve al registro ax
mov al,1d -> Al igual que en los otros casos especificamos que el numero esta en decimal con
la letra d como no es hexadecimal entonces se lo convierte en este caso al tendr el valor 01

no es necesario poner la letra d porque implcitamente si no se pone una letra delante de un


numero lo toma como decimal.
mov ax, bx -> mueve a ax lo que est en bx en si borra limpia ax y copia lo que esta en bx.
mov variable, ax -> esto ser vlido siempre y cuando variable este definido como dw.
mov al,variableDos -> esto mover lo que tiene al a variableDos siempre y cuando variableDos
sea un db.
Suma(add)
Esta instruccin es utilizada para sumar los valores de 2 registros de 16 bits o 32 bits. La
sintaxis de este comando es la siguiente:
add registro1, registro2
Notas

Ambos registros deben ser del mismo tamao.


El resultado de la suma se almacenar en el registro1

Resta(sub)
Esta instruccin es utilizada para restar los valores de 2 registros sigue la misma sintaxis de add
y las mismas restricciones como ser que ambos deben ser del mismo tamao y el resultado se
almacena en registro 1.
sub resgistro1, registro2
Multiplicacin(mul)
Esta instruccin es especial como su nombre lo indica su nombre se encarga de realizar una
multiplicacin, pero su sintaxis es algo curiosa.
mul registro
como nos podemos percatar solo le pasamos un registro. En este punto podemos pensar si es
multiplicacin porque tan solo le paso un registro. Lo que ensamblador hace es multiplicar el
registro por ax o al segn sea el registro que se pas en mul hay que tener cuidado con esto un
ejemplo claro cuando tenemos en ax 0100 y en bx 000A y realizamos la instruccin mul bl la
consecuencia de este comando agarra el 10 de bl y lo multiplicara por al que en este caso ser
00 al hacer esta multiplicacin se borrara lo que hay en ax y se remplazara con el resultado de
la multiplicacin que seria 0000 pero aqu hay inconsistencia el resultado debi ser 0A00 es lo
que se esperaba el error esta en que escribimos mul bl estamos multiplicando registros de 8
bits y ax en esta instancia tiene mas de 8 bits exactamente 12 bits asi que solo agarrara la
parte de 8 bits de este y lo multiplicara lo que producir el error en el resultado entonces la
solucin a este problema es realizar una multipliacion a 16 bits poniendo bx en lugar de bl
cuando realizamos mul bx se multiplicaran registros de 16 bits recordemos que el maximo
rango que puede almacenar un registro de 32 bits es 65535 cuando la multiplicacin sobrepasa
este valor utiliza a dx como parte del resultado.

Divisin(div)
La divisin en ensamblador es parecida a la multiplicacin solo recibe un registro.
El tamao mximo del dividendo ser el tamao de bits que se desea dividir si es 8 bits ser
255 y si es 16 bits ser 65535.

Divisin 8 bits
1. En al se almacena el dividendo.
2. Nos aseguramos que en ah sea 0, si no fuera 0 podra formar parte del
dividendo y estara en contra de dividir 8 bits.
3. En bl ponemos el divisor.
4. Ejecutamos div bl
5. Luego de ejecutar la instruccin en ah estar el residuo y en al cociente.

Divisin 16 bits
1. En ax se almacena el dividendo
2. Limpiamos el registro dx si no lo hacemos podra haber inconsistencia en la
divisin porque tomara dx como parte del dividendo
3. En bx el divisor
4. Ejecutamos div bx
5. Luego de ejecutar la instruccin en dx estar el residuo y en ax el cociente

Interrupciones del sistema


El sistema provee muchas interrupciones ya sea para recibir un carcter o para imprimir algn
carcter o capturar el cursor o impresora y mucho ms en esta parte repasaremos algunas
importantes del sistema
1) LEER UN CARCTER
A veces necesitamos introducir datos a un problema una cadena, un carcter especial
o un nmero. Para hacer esto posible ensamblador nos provee una interrupcin que
es la 21h pero para poder leer un carcter necesitamos ciertos pasos antes de la
interrupcin.
1) Primero debemos mover 01h a ah
2) Int 21 h
3) Luego de ejecutar la interrupcin en al estar el carcter leido en
formato ASCII
2) MOSTRAR UN CARCTER
Ensamblador nos permite mostrar un carcter ASCII en consola para ello necesitamos
hacer lo siguiente:
1) Primero movemos a dl el carcter en ASCII o tambin podemos ponerlo
entre comillas simples el carcter a mostrar
2) Seguido mov ah,02h
3) Despus int 21h

3) LEER UN CARCTER Y NO IMPRIMIRLO


A veces nos vemos en la necesidad de leer un carcter y no mostrarlo ese rato pero
con el mtodo que hicimos anteriormente logramos leerlo pero a la misma vez que lo
hacia lo imprima para hacer que esto no ocurra debemos hacer lo siguiente:
1) Primero se debe mover ah,07h
2) Seguido debemos ejecutar int 21h
3) En al se almacenara el valor en ASCII del carcter ledo pero no se
mostrara en consola.
4) MOSTRAR UNA CADENA
Como vimos anteriormente una cadena es un array de caracteres con una
caracterstica especial que tiene como fin de cadena al carcter $ podemos mostrar
una cadena de la siguiente manera:
1) Primero tenemos que apuntar al inicio de la cadena de manera obligada esta
referencia tiene que hacerla dx de la siguiente manera
mov dx, offset cadena
2)
Seguidamente mov ah,09h
3) Ejecutamos int 21h
Nota : por debajo lo que hace esto es ir imprimiendo en consola hasta que
encuentre el carcter $.
Cadenas especiales:
Salto de lnea -> salto db 10,13,$
Cadena con salto de lnea -> cadena db hola mundo,10,13,$
Cadena con tamao especifico y llenada con valores de 0 ->
cadena db 6 dup(0)
en donde 6 es el tamao que se reserva y dup indica el valor que tendrn esos
espacios de memoria en este caso reservamos 6 espacios de memoria con 0.
Cadena de nmeros -> nmeros db 1,10,100 que en otras palabras seria un
arreglo de bytes {1,10,100}
5) TERMINAR PROGRAMA
Para terminar un programa se usa la interrupcin 20h -> int 20h

Manejo de cadenas
Como mencionamos anteriormente ensamblador provee 3 puntero a cadenas ahora
aprenderemos como usarlos.

1) Apuntando a una cadena


Para apuntar al inicio de una cadena usamos el comando offset siguiendo la siguiente
sintaxis
mov puntero, offset cadena
en donde puntero puede ser si, di o bi en caso extraordinario.
Hasta este punto lo que tenemos es que puntero tenga referencia a 0xf00
cadena
0
1
2
3
$
0xf00 0xf01 0xf02 0xf03 0xf04
2) Accediendo al valor del puntero
Para poder acceder al valor que tiene el puntero se hace lo siguiente.
mov al,[puntero]
en donde [puntero] es la forma de acceder al dato actual al que hace referencia el
puntero en el ejemplo anterior al hacer [puntero], al tendr el valor de 0.
3) Recorriendo una cadena
En el ejemplo anterior ya pudimos acceder a 0 pero que pasa si yo quiero acceder a 1
entonces tengo que actualizar el puntero hay 2 formas de hacerlo:
1) la primera forma es usando el inc puntero que lo que hace es incrementar en 1
el puntero la principal desventaja es esta solo puedo incrementar en 1 que
pasa si yo estoy en 0 y quiero acceder a 3 no podr hacerlo de manera directa.
2) La segunda forma es usando add puntero, valor en donde valor ser el ndice
al cual quieres acceder en este caso 3 y con ello ya podemos acceder a un
ndice de forma ms directa.
Nota: podemos tambin hacer uso del comando dec o sub para ir recorriendo de forma inversa
una cadena.
Recorrimiento de registros
A veces nos vemos en la necesidad de hacer operaciones con binarios ya sea mostrar la suma,
resta, multiplicacin y divisin pero lo que se nos viene a la cabeza a primera vista es tengo en
el registro un valor tengo que convertirlo a binario y este lo almaceno hago lo mismo con el
otro valor y despus proceder a la suma es en esta instancia en que hacemos mucho calculo
como ser las divisiones sucesivas y ello pero ensamblador nos provee una serie de
instrucciones que hacen ello pero antes recordemos los registros. Miremos un poco su
estructura.
AX

AH

AL

Es la estructura recordemos que ah y al son de 16 bits y ax es 32 bits miremos un poco ms


abajo que esto.
AH
AX

1111

1111

AL
1111

1111

Ahora podemos darnos cuenta que cualquier valor que tenga al, ah o ax por ms que veamos
sus valores en hexadecimales por debajo son binarios

Veamos un ejemplo:

Ax

00

FF

As se ve cuando usamos la instruccin -> mov al,255 pero viendo ms detallado el registro lo
que se tiene es:
AX

0000

0000

1111

111

Ohh ahora todo tiene sentido. Cuando pensemos en convertir a binario ya no tenemos que
pensar en divisiones sucesivas, pero entonces como lo hacemos como mencionamos
anteriormente ensamblador nos provee ciertas instrucciones para este propsito las cuales
veremos ahora cabe mencionar que estas instrucciones hacen uso del flag Carry:
Corrimiento a la izquierda(SHL)
Para los ejemplos de aqu en adelante utilizaremos este como referencia.
Supongamos que en ax ejecutamos la siguiente instruccin -> mov ax,15
En ax quedara algo asi:
Ax

00

0F

Por debajo como ya podremos imaginar estara de esta forma


AX

0000

0000

0000

1111

La sintaxis de la instruccin shl es:


shl destino, fuente
en donde destino ser el registro a ser desplazado hacia la izquierda y fuente deber ser o solo
1 o el registro cl en donde estar la cantidad de desplazamiento que har. pero veremos cmo
acta esta instruccin en este ejemplo si yo ejecuto la siguiente instruccin:
shl al,1
lo que le indico con esta instruccin quiero desplazar el registro al hacia la izquierda 1 vez el
efecto de esto sera lo siguiente:
AX
0000
0000
0000
1110
Esto en el registro de Ax pero en el flag del carry estar el valor que el bit que se desplaz lo
que es lo mismo decir
carry

Quiz en este ejemplo no se comprendi bien su funcionalidad haremos un ejemplo para ver
ms detalladamente suponiendo que en tengo esto en al:

AL
abcdefgh
Al ejecutar la instruccin anterior quedara asi:
AL
Carry

bcdefgh0
a

Ohh ahora ya se entiende mejor la teora como vemos a se desplaz a la izquierda en otras
palabras se sac el valor a y todos los dems recorrieron uno atrs y el ultimo se puso en 0.
Ahora como dijimos antes podemos colocar en cl la cantidad de veces que queremos que se
desplace supongamos que en el anterior ejemplo colocamos en cl 3 el resultado sera lo
siguiente:
AL
Carry

defgh000
c

Carry solo es 1 bit asi que a medida que se vaya haciendo el desplazamiento este se va
actualizando.
Desplazamiento hacia la derecha(shr)
Al igual que en la anterior instruccin hace exactamente lo mismo solo que esta vez hacia la
derecha basndonos en el ejemplo anterior. Cabe mencionar que tiene la misma sintaxis que
en la anterior instruccin el cual es:
shr destino, fuente
ahora si yo ejecuto la siguiente instruccin -> shr al, 1 tendr lo siguiente
AL
Carry

0abcdefg
h

Rotacin a la derecha(ror)
Esta instruccin tiene la misma sintaxis que las anteriores, pero con un efecto diferente como
bien indica su nombre es rotacin as que el efecto que hace sobre el registro es mover 1 hacia
la derecha los dems y al primer bit ira el ultimo del registro, al carry va el ultimo bit.
Si ejecuto la siguiente instruccin:
ror al,1
tendr lo siguiente
AL
Carry

habcdefg
h

Rotacin a la izquierda(rol)
Misma sintaxis que el anterior y mismo efecto que el ultimo mencionado solo que esta vez lo
har hacia la izquierda si ejecuto la siguiente instruccin

rol al,1
tendr lo siguiente
AL
Carry

bcdefgha
a

Rotacin carey derecha(rcr)


Hasta ahora hablamos de cmo hacer los desplazamientos y rotaciones y sabemos que
despus de ejecutar las anteriores instrucciones el bit se almacenaba en el flag carry ahora si
queremos obtener ese bit para hacer operaciones con el ejemplo si tuviera si quisiera hacer la
suma de binario tengo que hacerla bit a bit entonces necesito de alguna forma obtener los bits
de estos s que con las anteriores instrucciones tengo el bit, pero ahora como lo obtengo para
operar con l.
Para ello ensamblador nos provee la instruccin rcr y rcl que lo que harn ser rotar el carry a
la izquierda o derecha sobre un registro destino.
Si ejecuto la siguiente instruccin:
rcr dl,1
antes:
carry
dl

1
00000000

carry
Carry

0
10000000

Ahora

Rotacin carry left(rcl)


Mismo efecto que el anterior solo que esta vez lo har hacia la izquierda ejecutando la
siguiente instruccin
rcl dl,1
Antes:
carry
dl

1
00000000

carry
Carry

0
00000001

Ahora

Saltos
Salto sin condicin(jmp)
Ensamblador nos ofrece una instruccin jmp el cual significa salto sin condicin se puede
colocar en cualquier parte del programa y lo que necesita es una etiqueta a donde saltara es
de carcter obligatorio que exista la etiqueta. Su sintaxis es la siguiente:
jmp etiquetaDestino
Saltos condicionales
Ensamblador ofrece una serie de instrucciones que se ejecutan baja cierta condicin el cual es
una comparacin entre registros se usa la siguiente sintaxis
cmp registro1,registro2
salto condicional
En donde:
registro1 y registro2 son del mismo tamao
salto condicional puede ser:
Instruccin
ja
Jb
jz
je
jae
jbe

Funcin
Salta si es mayor
Salta si es menor
Salta si es igual a zero
Salta si son iguales
Salta si es mayor igual
Salta si es menor igual

sintaxis
ja etiqueta
jb etiqueta
jz etiqueta
je etiqueta
jae etiqueta
jbe etiqueta

La comparacin se lee de la siguiente manera si registro 1 es condicional que registro 2 en


donde condicional es cualquier funcin de la tabla.
Ejemplo:
Registro1 es mayor que registro 2 seria as:
cmp registro1, registro2
ja esMayor
Rutinas
loop : Ensamblador nos provee una forma de hacer una rutina o un ciclo a veces no vemos en
la necesidad de hacer sumas sucesivas o restas sucesivas hasta n. como conocemos el lmite
del ciclo podemos usar la instruccin loop. El cual requiere una etiqueta que indica el principio
del ciclo y que en cx este la cantidad de veces que se repetir todo lo que este entre la
etiqueta y el loop.
La mecnica es simple llega al loop vuelve a la etiqueta inicial a su misma vez decrementa cx y
hace este proceso hasta que cx sea 0.

Su sintaxis es la siguiente:
EtiquetaIncio:
Instrucciones
loop EtiquetaInicio
Instruccin call:
Ahora que ya tenemos idea de cmo empezara a programar en ensamblador se nos viene a la
cabeza ideas como para leer un carcter necesito usar la interrupcin 21h y tengo que poner
en ah,01h ahora si quiero leer 4 nmeros tendra que repetir esto 4 veces y no habr alguna
forma de evitar esto. Pues el lenguaje ensamblador nos provee una instruccin que hace esto
el cual es denominado call, cuya funcin es hacer una llamada a un subproceso la sintaxis de
esta instruccin es la siguiente:
call etiquetaSubproceso

.
int 20h
etiquetaSubproceso:
conjunto de instrucciones
ret
la mecnica de call es la misma que la del santo incondicional solo que a diferencia de esta,
este tiene una instruccin ret que dice retornar de donde fue llamada esto es una gran ventaja
adems que nos permite hacer un salto a una etiqueta ejecutar el conjunto de instrucciones
que hay en ella y despus volver.
Macros:
Los macros en ensamblador no son ms que subprogramas que podemos usarlas en cualquier
parte del cdigo y no solo en nuestro cdigo actual sino tambin en otros cdigos la forma en
como utilizaremos este macro es haciendo un include del archivo que tiene los macros para
poder utilizar los macros contenidos en l. La sintaxis de un macro es la siguiente
macro identificador parmetros
esqueleto cdigo macro
endm
en donde:

identificador es el nombre del macro


parmetros es el conjunto de parmetros que recibir para mi macro
si dentro del esqueleto usaremos etiquetas tenemos que hacer que estas estn
definidas como locales de la siguiente manera -> local etiqueta
para finalizar un macro tenemos que usar lo siguiente endm que significa fin macro

la forma en como lo llamaremos es de la siguiente forma


include nombreDeTuArchivoDeMacros.asm
org 100h
identificador parmetros
resto del programa
int 20h
Ahora que vimos ya las instrucciones bsicas nos toca observar como es la estructura de un
programa en ensamblador
include archivo -> bloque de include en donde incluimos libreras y macros
org 100h -> inicio del programa
conjunto de instrucciones
int 20h -> fin del programa
cadena db ? bloque de declaracin de variables
etiquetas que llamo la instruccin call

Potrebbero piacerti anche