Arquitectura del procesador matemático 8087 El funcionamiento del 8087 es diferente al del 8086. Internamente tiene 8 registros de 80 bits organizados como una pila cíclica. Cada elemento de la pila puede almacenar un valor en formato real temporal de 10 bytes (80bits). El puntero de la pila (ST) indica en todo momento el elemento en la cima. Puede valer entre 0 y 7. Las instrucciones del 8087 pueden trabajar con datos en memoria (ver el Ejemplo 2) o directamente con datos en la pila (ver el Ejemplo 1). De esta forma, una instrucción aritmética utiliza uno o dos operandos de la pila, y el resultado se deja también en la pila. Ejemplo 1: finit fild multiplicando fild multiplicador fmul st,st(1) fist resultado Ejemplo 2: finit fild multiplicando fimul multiplicador fist resultado Todas las instrucciones del 8087 comienzan por “F”. Si acaban por “P” quiere decir que la pila se cargará con el resultado. Por ejemplo, FISTP VAR saca el resultado de la cima de la pila, lo guarda en la variable en memoria y lo quita de la pila (mueve el puntero). Tipos de instrucciones: • De transferencia de datos • Aritméticas • De comparación • De cálculo de funciones transcendentes • Relativas a constantes • De control Para utilizar el 8087, el 8086 debe ejecutar la instrucción de inicialización FINIT . A continuación ya se pueden utilizar las instrucciones del 8087 (el procesador se ocupa en ejecutar las instrucciones máquina o pasárselas al co-procesador matemático). Si alguna instrucción del 8087 pudiera tardar mucho tiempo, podemos utilizar la instrucción FWAIT para que el 8086 espere a ejecutar la siguiente instrucción sólo cuando el 8087 haya terminado la que está en curso (no siempre será necesaria). Veamos a continuación tres ejemplos de uso del coprocesador matemático 8087 para hacer cálculos numéricos: Ejemplo para multiplicar dos variables Cálculo de resultado = var1 * var2 pila segment stack 'stack' dw 100h dup (?) pila ends datos segment 'data' var1 dw 7 var2 dw 3 resultado dw 0 datos ends codigo segment 'code' assume cs:codigo, ds:datos, ss:pila main PROC mov ax,datos mov ds,ax finit fild var1 fimul var2 fist resultado mov ax,resultado call escribir_numero mov ax,4C00h int 21h main ENDP escribir_numero PROC NEAR push ax push dx mov bx,10 mov dl,al cmp ax,bx jb escribir_resto sub dx,dx div bx call escribir_numero escribir_resto: add dl,'0' mov ah,2 int 21h pop dx pop ax ret escribir_numero ENDP codigo ends END main Ejemplo para multiplicar y dividir accediendo directamente a la pila Ejemplo para calcular una raíz cuadrada resultado = (var1 * var2) / var3 resultado = sqrt((var1 * var2) – var3) pila segment stack 'stack' dw 100h dup (?) pila ends datos segment 'data' var1 dw 8 var2 dw 3 var3 dw 2 resultado dw 0 datos ends codigo segment 'code' assume cs:codigo, ds:datos, ss:pila main PROC mov ax,datos mov ds,ax finit fild var3 fild var2 fild var1 fmul st,st(1) fdiv st,st(2) fist resultado mov ax,resultado call escribir_numero mov ax,4C00h int 21h main ENDP escribir_numero PROC NEAR push ax push dx mov bx,10 mov dl,al cmp ax,bx jb escribir_resto sub dx,dx div bx call escribir_numero escribir_resto: add dl,'0' mov ah,2 int 21h pop dx pop ax ret escribir_numero ENDP codigo ends END main pila segment stack 'stack' dw 100h dup (?) pila ends datos segment 'data' var1 dw 6 var2 dw 3 var3 dw 2 resultado dw 0 datos ends codigo segment 'code' assume cs:codigo, ds:datos, ss:pila main PROC mov ax,datos mov ds,ax finit fild fimul fisub fsqrt fist var1 ;cargar 6 var2 ;multip por 3 var3 ;restarle 2 ;hacer la raiz cuadrada resultado mov ax,resultado call escribir_numero mov ax,4C00h int 21h main ENDP escribir_numero PROC NEAR push ax push dx mov bx,10 mov dl,al cmp ax,bx jb escribir_resto sub dx,dx div bx call escribir_numero escribir_resto: add dl,'0' mov ah,2 int 21h pop dx pop ax ret escribir_numero ENDP codigo ends END main