Documente Academic
Documente Profesional
Documente Cultură
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
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
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