Sunteți pe pagina 1din 13

Manejo de Pila

El stack del 8086 está implementado utilizando fundamentalmente las operaciones PUSH
y POP conjuntamente con los registros SS y SP.
El tope del stack está apuntado por SS:SP y las operaciones PUSH y POP los actualizan
de forma de obtener la semántica de stack como veremos más adelante.

PUSH
Formato: PUSH op
Tipo Args: (R,M)
Lógica: SP=SP-2
MOV SS:[SP],op
Descripción: Decrementa el puntero del stack, SP y transfiere la palabra
especificada por op a la dirección SS:SP

POP
Formato: POP op
Tipo Args: (R,M)
Lógica: MOV op ,SS:[SP]
SP=SP+2
Descripción: Transfiere la palabra en tope del stack al operando op y luego
incrementa el puntero del stack, SP.
Ejercicios - Explicación

1. Elaborar un programa fuente en assembler que permita ingresar una cadena de


caracteres e imprimirla al revés en pantalla (Máximo 50 Caracteres).

datos segment
men DB "Ingrese cadena de caracteres: $"
buffentrada DB 53 DUP(?)
buffsalida DB 53 DUP(?)
cant DB 0
datos ends
pila segment stack
DB 100 DUP(?) ;le definimos de tamaño 100 debido a que vamos a guardar como
máximo 50 caracteres por lo tanto 50*2=100 bytes
pila ends
codigo segment
assume cs:codigo,ds:datos,ss:pila
inicio:
mov ax,datos
mov ds,ax
mov ax,pila
mov ss,ax
mov ax,0
mov ah,09h ;Agregamos el Servicio 09 en ah, para mostrar un mensaje por
pantalla
mov dx,offset men
int 21h
mov si,offset buffentrada
mov byte ptr[si],51 ;especificamos en el buffer el valor máximo de caracteres a
ingresar(Considerando el enter).
mov ah,0ah
mov dx,offset buffentrada
int 21h
mov ax,0
mov al,[si+1]
mov cant,al ;guardamos en la variable cant, la cantidad de caracteres ingresados,
este se encuentra en la posición 1 del buffer.
add si,2
mov cl,0

para :
cmp cl,cant ;comparamos nuestro contador cl, con la cantidad para recorrer el buffer
de acuerdo a los valores ingresados.
je salida
mov ax,0
mov al, [si]
push ax;guardamos en la pila un carácter de la cadena.
inc cl ;incrementamos nuestro contador.
inc si
jmp para
salida:
mov si,offset buffsalida
mov byte ptr[si],0ah ;lo que hacemos en este bloque de salida, es agregar en las 2
primeras posiciones el ASCII del salto de línea y del enter para que el resultado se pueda
visualizar debajo del mensaje.
inc si
mov byte ptr[si],0dh
inc si
desapila:
cmp cant,0
je finsi
mov ax,0
pop ax
mov [si],al ;desapilamos los caracteres guardados en la pila pero tomando la parte
baja, ya que los caracteres apilados son de 8 bits y lo guardamos en el buffer de salida.
dec cant
inc si
jmp desapila
finsi:
mov byte ptr[si],24h
mov ah,09h
mov dx,offset buffsalida ;guardamos el servicio 09h en ah para imprimir cadena en
pantalla guardando la dirección del buffer en dx y llamamos al sistema operativo a través
de la interrupción 21.
int 21h
mov ah,4ch ;fin del proceso
int 21h
codigo ends
end inicio

2. Elaborar un programa fuente en assembler que permita mostrar en pantalla a un número


de 16 bits especificado en el segmento de datos, utilizando la pila para la
descomposición del número en sus dígitos constitutivos.
datos segment
men db “El numero de 16 bits es: $”
buffsalida db 6 DUP(?)
num dw 23456
datos ends
pila segment stack
db 10 dup (?) ; le asignamos un tamaño de 10 bytes porque la longitud máxima de
un números que puede soportar el 8086 es de 5 por lo tanto 5*2=10
pila ends
codigo segment
assume cs:codigo,ds:datos,ss:pila
inicio:
mov ax,datos
mov ds,ax
mov ax,pila
mov ss,ax
mov ax,0
mov ax,num
mov bx,10
mov cl,0
divide:
mov dx,0
div bx
add dx,30h ;en el bloque divide, lo que hacemos es el proceso de descomposición
del número que se encuentra guardado en la variable num, para descomponerlo lo
dividimos entre 10 y le sumamos 30 para tener el ASCII del número para que se imprima
correctamente a la hora que lo mandemos al buffer.
push dx
inc cl ;incrementamos nuestro cl, que nos va a servir para saber cuantas veces
apilamos para más adelante desapilar la misma cantidad.
cmp ax,0h
jne divide
mov si,offset buffsalida
para:
cmp cl,0
je salida
pop ax
mov [si],al ;desapilamos los dígitos y lo agregamos al buffer de salida para
imprimirlos por pantalla
dec cl
inc si
jmp para
salida:
mov byte ptr [si],24h
mov ah,09h
mov dx,offset men
int 21h
mov dx,offset buffsalida ;imprimimos por pantalla
int 21h
mov ah,4ch
int 21h ;finalizamos el proceso
codigo ends
end inicio

3. Hacer un programa que muestre la sucesión de Fibonacci en forma invertida. El


programa pedirá al usuario la cantidad de términos a trabajar.
datos segment
men db "Ingrese cantidad de terminos a trabajar: $"
buffsalida db 10 dup(?)
buffentrada db 5 dup(?)
cant db 0
datos ends
pila segment stack
db 58 dup (?) ;le ponemos de valor de 58 debido que el máximo valor de fibonacci
que puede ser almacenado en un registro de 16 bits sería hasta el número 24, entonces
24*2=48 pero faltaría añadir el tamaño de la descomposición de dicho número para
guardarlo en un buffer e imprimirlo, por lo tanto la máxima longitud del número sería de 5,
5*2=10, 48+10=58 bytes.
pila ends
codigo segment
assume cs:codigo,ds:datos,ss:pila
inicio:
mov ax,datos
mov ds,ax
mov ax,pila
mov ss,ax
mov ax,0
mov ah,09h
mov dx,offset men
int 21h
mov si,offset buffentrada ; especificamos en el buffer el valor máximo de 2 dígitos
y el enter por lo tanto sería de tamaño 3.
mov byte ptr[si],3
mov ah,0ah
mov dx, offset buffentrada
int 21h
mov dx,0
mov ax,0
mov al,[si+1]
mov cant,al ;obtenemos la cantidad de digitos que fueron ingresados para
componer dichos ASCII en un número decimal.
mov ax,0
add si,2
mov al,[si]
sub al,30h ;obtenemos en al el primer digito del numero en decimal
cmp cant,1
je serie
mov bl,10
mul bl
mov ah,[si+1]
sub ah,30h
add al,ah ;y si el número es de 2 dígitos al número anterior lo multiplicamos por 10
y le sumamos el valor del otro dígito.
serie:
mov cant,al
mov ax,0
push ax
inc ax
push ax ;guardamos en la pila los 2 primero número de la serie el 0 y el 1.
mov cl,3
para:
cmp cl,cant
ja desapilar
mov ax,0
mov bx,0
pop ax
pop bx
push bx
push ax
add ax,bx ;desapilamos 2 números y los apilamos con cuidado para que no afecte
el orden y luego sumamos estos dos números y el resultado lo apilamos.
push ax
inc cl
jmp para
desapilar:
mov si,offset buffsalida
mov byte ptr [si],0ah
inc si
mov byte ptr [si],0dh ;guardamos en el buffer de salida en las 2 primeras posiciones
el ASCII del salto de línea y del enter para mostrar los números uno debajo de otro.
inc si
mov ax,0
pop ax ;extraemos el último número apilado
mov ch,0
mov bx,10
descomponer:
mov dx,0
div bx
add dx,30h ;descomponemos el número extraído diviendolo en 10 y apilando sus
dígitos.
push dx
inc ch
cmp ax,0
jne descomponer
imprimir:
mov ax,0
pop ax
mov [si],al
inc si
dec ch
cmp ch,0
jne imprimir
mov byte ptr [si],2ch
inc si
mov byte ptr [si],20h
inc si
mov byte ptr [si],24h ;agregamos el signo del dólar para indicar el fin de la cadena
dec cant
mov ah,09h
mov dx,offset buffsalida
int 21h
cmp cant,0
ja desapilar
mov ah,4ch
int 21h
codigo ends
end inicio

4. Elaborar un programa en ASSEMBLER que permita recibir una expresión aritmética en


notación POSTFIJA como cadena y procesarla usando la pila para obtener el resultado
el cual será mostrado en pantalla (considerar que todos los números que están en la
cadena son de 1 solo dígito).

datos segment
men db "Ingrese expresion postfija: $"
buffentrada db 15 dup(?)
buffsalida db 8 dup(?)
cant db 0
datos ends
pila segment stack
db 24 dup(?) ;tamaño 24 porque se ha considerado ingresar como máximo 12 números.
pila ends
codigo segment
assume cs:codigo, ds:datos, ss:pila
inicio:
mov ax,datos
mov ds,ax
mov ax,pila
mov ss,ax
mov ax,0h
mov ah,09h
mov dx,offset men
int 21h
mov si,offset buffentrada
mov byte ptr [si],13h ;que se puedan ingresar máximo 13 caracteres incluido el enter
mov ah,0ah
mov dx,offset buffentrada
int 21h
mov al,[si+1]
mov cant,al ; guardamos en la variable cant, la cantidad de caracteres ingresados para
saber hasta dónde vamos a recorrer el buffer.
mov ax,0h
inc si
inc cant
para:
inc si
dec cant
cmp cant,0h ; si cant es 0 ya se recorrió todo el buffer y se procede a descomponer
je finpara
mov al,[si]
mov ah,0h
cmp al,30h ; verificamos que si el carácter tomado es un número, si no saltamos a
comprobar si es un operador.
jb operador
cmp al,39h
ja operador
sub al,30h ;le restamos 30 para tenerlo como número y lo apilamos.
push ax
jmp para
operador:
cmp al,2bh ;comparamos el valor del registro al sí es igual al ascii del signo “+”
jne resta
mov ax,0
mov bx,0
pop ax
pop bx
add ax,bx ; desapilamos 2 números y efectuamos la suma y apilamos el resultado.
push ax
jmp para
resta:
cmp al,2dh ;comparamos el valor del registro al sí es igual al ascii del signo “-“
jne producto
mov ax,0
mov bx,0
pop ax
pop bx
sub bx,ax ; desapilamos los números y efectuamos la resta y apilamos el resultado.
push bx
jmp para
producto:
cmp al,2ah ;comparamos si el valor del registro al sí es igual al ascii del “*”.
jne division
mov ax,0d
mov bx,0d
pop ax
pop bx
mul bx ;desapilamos 2 números y realizamos un producto de 16bits, el resultado lo
apilamos.
push ax
jmp para
division:
cmp al,2fh ;comparamos si el valor del registro al sí es igual al ascii del “/”.
jne modulo
pop bx
pop ax
div bx
push ax
jmp para
modulo:
cmp al,25h ;comparamos si el valor del registro al sí es igual al ascii del “%”.si es
diferente, eso quiere decir que el carácter no es un numero ni tampoco un operador
permitido por lo tanto salto a la etiqueta “para”. Para obtener un nuevo carácter.
jne para
mov ax,0h
mov bx,0h
pop bx
pop ax
div bx ;desapilamos los 2 número y los pasamos a dividir pero en este caso,
queremos el módulo, apilamos dx(ahí se almacena el residuo).
push dx
jmp para
finpara:
mov ax,0h
mov bx,0h
mov cl,0h
pop ax
mov bx,0ah
descomponer:
mov dx,0
div bx
add dx,30h ;antes de apilar le sumamos 30 para que tenga su equivalente en ascii, y no
tener problemas al momento de imprimirlo por pantalla.
push dx
inc cl
cmp ax,0h
jne descomponer
mov si,offset buffsalida
mov byte ptr [si],0ah
inc si
mov byte ptr [si],0dh ; agregamos en las 2 primera posiciones del buffer de salida el ascii
del salto de línea y del enter.
inc si
imprimir:
mov ax,0
pop ax
mov [si],al ;guardamos en el buffer los dígitos del número.
inc si
dec cl
cmp cl,0
jne imprimir
mov byte ptr [si],24h ;agregamos el ascii del “$” que indica fin de la cadena
mov ah,09h
mov dx,offset buffsalida
int 21h ;imprimos a pantalla
mov ah,4ch ;finalizamos el proceso
int 21h
codigo ends
end inicio

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