PRÁCTICA 13
PRÁCTICA 13
PRÁCTICA 13
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
LENGUAJE ENSAMBLADOR 80386 <strong>PRÁCTICA</strong> <strong>13</strong><br />
AUTOR: PROFESOR SALVADOR SAUCEDO FLORES<br />
EDICIÓN: PROFESOR PABLO FUENTES RAMOS<br />
<strong>PRÁCTICA</strong> <strong>13</strong><br />
SUMA, RESTA, MULTIPLICACIÓN Y DIVISIÓN DE DOS NÚMEROS<br />
REALES DE PUNTO FLOTANTE DE PRECISIÓN SENCILLA, SEGÚN<br />
NORMA IEEE-754<br />
1 INTRODUCCIÓN<br />
Mediante esta práctica trabajaremos con números reales de precisión<br />
sencilla, según el estándar IEEE-754 y haremos las operaciones básicas de<br />
suma, resta, multiplicación y división de dos números de punto flotante,<br />
necesitándose por fuerza de un microprocesador 80386 o más reciente que<br />
cuente con coprocesador matemático.<br />
2 OBJETIVOS<br />
Al término de esta práctica el alumno podrá:<br />
2.1 Trabajar con rutinas aritméticas que usan el procesador numérico.<br />
2.2 Realizar operaciones básicas y exhibir el resultado<br />
2.3 Hacer que un programa revise si el procesador numérico está disponible<br />
3 DESARROLLO<br />
3.1 Capturar los siguientes los siguientes cuatro módulos, ensamblarlos<br />
y meterlos a la librería PF.<br />
%TITLE “INICIA87.ASM INICIALIZA EL PROCESADOR NUMÉRICO 80387”<br />
; Ensamblar y poner en librería PF.LIB<br />
;<br />
; Llamar con: AX = palabra de control para fijar redondeo, modo, bits de precisión, máscara de excepciones<br />
;<br />
; Retorna: (si el coprocesador está presente) bandera ZF = puesta (1)<br />
;<br />
; (Si coprocesador no hallado) ZF = falsa (0)<br />
;<br />
; Destruye: nada<br />
IDEAL<br />
MODEL small<br />
<strong>13</strong>-1
LENGUAJE ENSAMBLADOR 80386 <strong>PRÁCTICA</strong> <strong>13</strong><br />
codeseg<br />
PUBLIC Inicia87<br />
PROC Inicia87<br />
push bx ax ;salva registros<br />
mov ax,-1 ;pone FFFFH en la pila<br />
push ax<br />
mov bx,sp ;la hace direccionable<br />
fninit ;trata de inicializar el coprocesador<br />
fnstsw [ss:bx] ;trata de traer palabra de estado<br />
pop ax ;si 8 bits bajos son cero,<br />
or al,al ;el coprocesador está presente<br />
jnz @@10 ;salta si no hay coprocesador<br />
fldcw [ss:bx+2] ;carga al coprocesador la palabra de control<br />
@@10:<br />
pop ax bx ;restaura registros<br />
ret ;y regresa el resultado en la bandera Z<br />
ENDP Inicia87<br />
end<br />
%TITLE “FALOG.ASM CALCULA ANTILOG COMÚN EN 80387”<br />
;<br />
; FALOG.ASM calcula el antilogaritmo en 80387<br />
;<br />
; Llamar con: ST(0) = argumentos<br />
;<br />
; Retorna: ST(0) = antilogaritmo de base 10<br />
;<br />
; Usa: registros del CPU se preservan, usa tres celdas de la pila del coprocesador<br />
;<br />
; Nota: Para obtener antilogaritmo natural, reemplazar “fldl2t” con la instrucción “fldl2e”.<br />
;<br />
; Estar seguro que el coprocesador ha sido iniciado con un llamado previo a INICIA87!<br />
IDEAL<br />
MODEL small<br />
Codeseg<br />
vieja equ [word bp-4] ;palabra original de control<br />
nueva equ [word bp-2] ;palabra nueva de control<br />
PUBLIC falog<br />
PROC falog<br />
push ax ;salva registros y<br />
push bp ;forma apuntador<br />
mov bp,sp ;para variables locales<br />
AUTOR: PROFESOR SALVADOR SAUCEDO FLORES<br />
EDICIÓN: PROFESOR PABLO FUENTES RAMOS<br />
<strong>13</strong>-2
LENGUAJE ENSAMBLADOR 80386 <strong>PRÁCTICA</strong> <strong>13</strong><br />
sub sp,4<br />
fldl2t ;carga log2(10)<br />
fmulp st(1),st(0) ;log2(10) * argumento<br />
fld st(0) ;duplica el producto<br />
fstcw vieja ;trae palabra vieja de control<br />
fwait ;espera<br />
mov ax,vieja ;cambia modo de redondeo<br />
and ax,0f3ffh ;a “hacia abajo”<br />
or ax,0400h<br />
mov nueva,ax<br />
fldcw nueva ;fija modo de redondeo<br />
frnint ;trae parte entera del producto<br />
fldcw vieja ;restaura modo original de redondeo<br />
fld st(0) ;duplica parte entera<br />
fxch st(2) ;trae producto original<br />
fsubrp st(1),st(0) ;halla parte fraccional<br />
fld1<br />
fchs<br />
fxch st(1) ;escala parte fraccional<br />
fscale<br />
fstp st(1) ;descarta basura del coprocesador<br />
f2xm1 ;eleva 2 a la -1<br />
fld1<br />
faddp st(1),st(0) ,corrige por el -1<br />
fmul st(0),st(0) ;hace resultado al cuadrado<br />
fscale ;escala por parte entera<br />
fstp st(1) ;tira basura del coprocesador<br />
add sp,4 ;descarta variables locales<br />
pop bp ;restaura registros y<br />
pop ax ;retorna resultado en ST(0)<br />
ret<br />
ENDP falog<br />
end ;fin de módulo FALOG.ASM<br />
%TITLE “ATOF – CONVERSIÓN DE ASCII A BINARIO DE PUNTO FLOTANTE”<br />
; Ensamblarlo y ponerlo en librería PF<br />
;<br />
; ATOF.ASM Convierte cadena ASCII a número binario de punto flotante en la pila de 80387<br />
; (También requiere FALOG en FALOG.ASM<br />
;<br />
; Llamar con DS:DI = dirección de ka cadena con la forma<br />
; [signo][digitos][.[digitos]][E\e[signo][exp]] se ignoran espacios y tabuladores delanteros<br />
;<br />
; Retorna: ST(0) = valor binario en punto flotante DS:SI = dirección+1 del terminador<br />
;<br />
; Usa: nada<br />
;<br />
; Esta rutina no advierte en el caso de que haya sobre flujo y termina con el primer<br />
; carácter no valido<br />
; Asegurarse de que el 80387 ha sido previamente iniciado con una llamada previa a INICIA87!<br />
blanco equ 20h ;ASCII de carácter blanco<br />
AUTOR: PROFESOR SALVADOR SAUCEDO FLORES<br />
EDICIÓN: PROFESOR PABLO FUENTES RAMOS<br />
<strong>13</strong>-3
LENGUAJE ENSAMBLADOR 80386 <strong>PRÁCTICA</strong> <strong>13</strong><br />
tab equ 09h ;ASCII de carácter tabulador<br />
IDEAL<br />
MODEL small<br />
dataseg<br />
Int10 dw 10 ;constante entera 10<br />
Digito dw 0 ;dígito convertido actual<br />
Lugares dw 0 ;número de lugares decimales<br />
codeseg<br />
EXTRN falog:near ;se necesita la rutina FALOG<br />
PUBLIC atof<br />
PROC atof ;ASCII a punto flotante<br />
push ax cx dx ;salva registros<br />
call convierte ;convierte la mantisa<br />
neg dx ;salva -1 * lugares decimales<br />
mov [lugares],dx<br />
or al,20h ;mantiene carácter para minúsculas<br />
cmp al,’e’ ;¿está el exponente presente?<br />
je @@10 ;si, salta<br />
fldz ;asume exponente cero<br />
jmp @@20<br />
@@10:<br />
call convierte ;convierte exponente<br />
@@20:<br />
fiadd [lugares] ;ajusta exponente para dec. lugares en mantisa<br />
call falog ;eleva a la potencia 10<br />
fmul ;exponente * mantisa<br />
pop dx cx ax ;restaura registros<br />
ret ;retorna ST(0) = resultado<br />
ENDP atof<br />
;<br />
; CONVIERTE: Llamada por ATOF para convertir un número ASCII con posible signo y/0 punto decimal<br />
; Entrada: DS:SI = dirección de la cadena<br />
; Retorna: ST(0) = resultado<br />
; AL = primer carácter no convertible<br />
; DX = número de dígitos tras el punto decimal<br />
; DS:SI = dirección +1 del carácter en AL<br />
; Usa: AH,CX<br />
;<br />
PROC convierte ;convierte campo numérico<br />
fldz ;inicializa resultado<br />
xor cx,cx ;inicializa signo<br />
AUTOR: PROFESOR SALVADOR SAUCEDO FLORES<br />
EDICIÓN: PROFESOR PABLO FUENTES RAMOS<br />
<strong>13</strong>-4
LENGUAJE ENSAMBLADOR 80386 <strong>PRÁCTICA</strong> <strong>13</strong><br />
mov dx,-1 ;inicializa conteo decimal<br />
@@10:<br />
lodsb ;elimina espacios<br />
cmp al,blanco ;ignora blancos delanteros<br />
je @@10<br />
cmp al,tab ;ignora tabuladores delanteros<br />
je @@10<br />
cmp al,’+’ ;verifica si un + precede<br />
je @@20 ;si, salta<br />
cmp al,’-‘ ;¿es el símbolo -?<br />
jne @@30 ;no, prueba si numérico<br />
dec cx ;si, pone bandera<br />
@@20:<br />
lodsb ;trae siguiente carácter<br />
@@30:<br />
cmp al,’0’ ;¿es carácter válido?<br />
jb @@40 ;salta si no ‘0’ a ‘9’<br />
cmp al,’9’<br />
ja @@40 ;salta si no ‘0’ a ‘9’<br />
and ax,0fh ;aísla cuatro bits bajos<br />
mov [digito],ax ;y salva valor del dígito<br />
fimul [int10] ;valor previo * 10<br />
fiadd [digito] ;acumula nuevo dígito<br />
or dx,dx ;¿pasó punto decimal?<br />
js @@20 ;no, convierte siguiente dígito<br />
inc dx ;si, cuenta dígitos<br />
jmp @@20 ;convierte siguiente dígito<br />
@@40:<br />
cmp al,’.’ ;¿es el punto decimal?<br />
jne @@50 ;no, proceder<br />
inc dx ;indica punto decimal hallado<br />
jmp @@20 ;convierte más dígitos<br />
@@50:<br />
jcxz @@60 ;salta si resultado positivo<br />
fchs ;hace resultado negativo<br />
@@60:<br />
or dx,dx ;¿halló punto decimal?<br />
jns @@70 ;si, salta<br />
xor dx,dx ;retorna cero lugares<br />
@@70:<br />
ret ;retorna ST(0) = resultado<br />
ENDP convierte<br />
end ;fin de módulo ATOF.ASM<br />
AUTOR: PROFESOR SALVADOR SAUCEDO FLORES<br />
EDICIÓN: PROFESOR PABLO FUENTES RAMOS<br />
<strong>13</strong>-5
LENGUAJE ENSAMBLADOR 80386 <strong>PRÁCTICA</strong> <strong>13</strong><br />
%TITLE “FTOA – PUNTO FLOTANTE A ASCII”<br />
; Ensamblarlo y ponerlo en librería PF<br />
;<br />
; FTOA.ASM – Convierte binario de punto flotante<br />
; Número real en la pila del 80387 Stack en ASCII (usa FALOG de FALOG.ASM)<br />
;<br />
; Llamar con ST(0) = número de punto flotante<br />
; DS:DI = área para recibir cadena<br />
;<br />
; Retorna: DS:SI = dirección de cadena convertida<br />
; AX = largo de la cadena<br />
; Pila del coprocesador “sube”<br />
;<br />
; Usa: nada<br />
;<br />
; Asegurarse de que el coprocesador ha sudo iniciado adecuadamente con una llamada previa a INICIA87!<br />
IDEAL<br />
MODEL small<br />
dataseg<br />
signo dw 0 ;recibe estado FXAM<br />
viejo dw 0 ;modo de redondeo previo<br />
nuevo dw 0 ;nuevo modo de redondeo<br />
exp dw 0 ;potencia de 10<br />
status dw 0 ;recibe estado ICOM<br />
mant dt ;mantisa como valor BCD<br />
fp<strong>13</strong>17 dq 1,0e17 ;constante para escalamiento<br />
fp1e18 dq 1,0e18 ;constante para escalamiento<br />
int10 dw 10 ;constante par escalamiento<br />
CadOp db ‘+0.000000000000000000E+000’ ;exhibido si<br />
LonOp equ offset CadOn-offset CadOp ;ST(0) = +0<br />
CadOn db ‘-0.000000000000000000E+000’ ;exhibido si<br />
LonOn equ offset CadIp-offset CadOn ;ST(0) = -0<br />
CadIP db ‘’ ;exhibido si<br />
LonIP equ offset CadIn-offset CadIp ;es infinito positivo<br />
CadIN db ‘’ ;exhibido si ST(0)<br />
LonIN equ offset CadNatN-offset CadIN ;es infinito negativo<br />
CadNaN db ‘’ ;exhibido si ST(0)<br />
LonNaN equ offset CadAn-offset CadNaN ;contiene Not-A-Número<br />
CadAn db ‘’ ;exhibido para anormales<br />
LonAn equ offset CadDe-offset CadAn ;positivos y negativos<br />
CadDe db ‘’ ;exhibido para denormales<br />
LonDe equ offset CadVac-offset CadDe ;positivos o negativos<br />
CadVac db ‘’ ;exhibido si ST(0’)<br />
LonVac equ offset Tipofin-offset CadVac ;está marcado vacío<br />
AUTOR: PROFESOR SALVADOR SAUCEDO FLORES<br />
EDICIÓN: PROFESOR PABLO FUENTES RAMOS<br />
<strong>13</strong>-6
LENGUAJE ENSAMBLADOR 80386 <strong>PRÁCTICA</strong> <strong>13</strong><br />
Tipofin db 0<br />
codeseg<br />
EXTRN falog:near ;se usa rutina FALOG<br />
PUBLIC ftoa<br />
PROC ftoa ;punto flotante a ASCII<br />
push bx dx cx di es ;salva registros<br />
push ds ;hace que DS apunte a @data<br />
pop es<br />
fxam ;prueba tipo de número<br />
fstsw ;salva estado de FXAM<br />
fwait<br />
mov bx,[signo] ;retira estado y<br />
and bx,4700h ;aísla C3, C2, C1, C0<br />
rol bx,1 ;para formar un<br />
rol bx,1 ;con valor de 0-15, y luego<br />
shl bh,3 :*2 para formar índice de asalto<br />
rol bx,3<br />
shl bx,1<br />
jmp [cs: TipoTab+bx] ;salta según tipo de número<br />
@@10:<br />
fabs ;forza un número positivo<br />
fxtract ;extrae exponente<br />
fxch st(1) ;pone exponente encima<br />
fldlg2 ;forma potencia de 10<br />
fmulp st(1),st(0)<br />
fstcw [viejo] ;salva modo de redondeo actual<br />
fwait<br />
mov ax,[viejo] ;hace “1”s campo de redondeo<br />
or ax,0c00h ;modo “truncar”<br />
mov [nuevo],ax<br />
fldcw [nuevo] ;forza nuevo modo de redondeo<br />
fld st(0) ;duplica potencia de diez<br />
frndint ;halla parte entera del<br />
fist [exp] ;exponente y la salva<br />
fldcw [viejo] ;restaura modo de redondeo anterior<br />
fsubp st(1),st(‘0) ;halla parte fraccionaria de<br />
call falog ;potencia de diez<br />
fmulp st(1),st(0) ;multiplica por la mantisa<br />
fmul [ft1e18] ;escala mantisa par BCD<br />
frndint ;tira el remanente<br />
@@20:<br />
fcom ]fp1e17] ;¿es la mantisa < 1.0e17?<br />
fstsw [status]<br />
fwait<br />
mov ax,[status]<br />
sahf<br />
jae @@30 ;no, proceder<br />
AUTOR: PROFESOR SALVADOR SAUCEDO FLORES<br />
EDICIÓN: PROFESOR PABLO FUENTES RAMOS<br />
<strong>13</strong>-7
LENGUAJE ENSAMBLADOR 80386 <strong>PRÁCTICA</strong> <strong>13</strong><br />
fimul [int10] ;si, mantisa*10<br />
dec [exp] ;y decrementa exponente<br />
jmp @@20<br />
@@30:<br />
fcom [fp1e18] ;¿es la mantisa < 1.0e18?<br />
fstsw [status]<br />
fwait<br />
mov ax,[status]<br />
sahf<br />
jb @@40 ;si, proceder<br />
fidiv [int10] ;no, mantisa / 10<br />
inc [exp] ;e incrementa exponente<br />
jmp @@30<br />
@@40:<br />
fbstp [mant] ;salva mantisa en BCD<br />
fwait<br />
mov di,si ;direcciona cadena ASCII<br />
mov ,’+’ ;asume es positivo<br />
test [signo],200h ;verifica banderas de FXAM<br />
jz @@50 ;brinca, valor es positivo<br />
mov al,’-‘<br />
@@50:<br />
stosb ;salva símbolo + o –<br />
mov al,’0’ ;salva cero delantero<br />
stosb<br />
mov al,’.’ ;pone punto decimal<br />
stosb<br />
mov bx,8 ;apunta a últimos dígitos BCD<br />
@@60:<br />
mov al,[byte bx+mant] ;convierte byte BCD a<br />
shr al,1 ;dos dígitos ASCII<br />
shr al,1<br />
shr al,1<br />
shr al,1<br />
call digit ;convierte nibble alto<br />
mov al,[byte bx+mant]<br />
call digit ;convierte nibble bajo<br />
dec bx ;procesa valores BCD<br />
jns @@60 ;hasta convertir 18 dígitos<br />
mov al,’E’ ;pone la E para exponente<br />
stosb<br />
mov bx,[exp] ;prueba signo del exponente<br />
mov al,’+’<br />
or bx,bx<br />
jns @@70 ;brinca, exponente es positivo<br />
mov al,’-‘<br />
neg bx ;valor absoluto del exponente<br />
@@70:<br />
stosb ;salva signo del exponente<br />
AUTOR: PROFESOR SALVADOR SAUCEDO FLORES<br />
EDICIÓN: PROFESOR PABLO FUENTES RAMOS<br />
<strong>13</strong>-8
LENGUAJE ENSAMBLADOR 80386 <strong>PRÁCTICA</strong> <strong>13</strong><br />
mov ax,bx ;convierte exponente a<br />
cwd ;tres dígitos ASCII<br />
mov cx,100<br />
div cx<br />
call digit ;exponente: dígito de cientos<br />
mov ax,dx<br />
cwd<br />
mov cx,10<br />
div cx<br />
call digit ;exponente: dígito de decenas<br />
mov ax,dx<br />
call digit<br />
@@80:<br />
mov ax,di ;retorna AX = longitud de cadenas<br />
sub ax,si ;y DS:SI dirección de cadenas<br />
pop es di dx cx bx ;restaura registros<br />
ret<br />
@@100:<br />
mov di,offset CadOp ;valor de +cero<br />
mov cx,LonOp<br />
jmp @@200<br />
@@110<br />
mov di,offset CadOn ;valor de –cero<br />
mov cx,LonOn<br />
jmp<br />
@@120:<br />
mov di,offset CadVac ;valor vacío<br />
mov cx,LonVac<br />
jmp @@200<br />
@@<strong>13</strong>0:<br />
mov di,offset CadDe ;valor denormalizado<br />
mov cx,LonDe<br />
jmp @@200<br />
@@140:<br />
mov di,offset CadAn ;valor anormal<br />
mov cx,LonAn<br />
jmp @@200<br />
@@150:<br />
mov di,offset NaN ;valor NaN<br />
mov cx,LonNaN<br />
jmp @@200<br />
@@160:<br />
mov di,offset CadIP ;valor de +infinito<br />
mov cx,LonIP<br />
jmp @@200:<br />
AUTOR: PROFESOR SALVADOR SAUCEDO FLORES<br />
EDICIÓN: PROFESOR PABLO FUENTES RAMOS<br />
<strong>13</strong>-9
LENGUAJE ENSAMBLADOR 80386 <strong>PRÁCTICA</strong> <strong>13</strong><br />
@@170:<br />
mov di,offset CadIN ;valor de –infinito<br />
mov cx,LonIN<br />
@@200:<br />
xchg si,di ;SI = cadena enlatada<br />
push di, ;DI = área del llamador<br />
rep movsb ;copia cadena enlatada<br />
pop si ;restaura SI<br />
fstp st(0) ;descarta valor original<br />
jmp @@80<br />
TipoTab dw @@140 ;0000 +anormal<br />
dw @@150 ;0001 +NaN<br />
dw @@140 ;0010 –anormal<br />
dw @@150 ;0011 -NaN<br />
dw @@10 ;0100 +normal<br />
dw @@160 ;0101 +infinito<br />
dw @@10 ;0110 –normal<br />
dw @@170 ;0111 –infinito<br />
dw @@100 ;1000 +cero<br />
dw @@120 ;1001 vacío<br />
dw @@110 ;1010 –cero<br />
dw @@120 ;1011 vacío<br />
dw @@<strong>13</strong>0 ;1100 +denormal<br />
dw @@120 ;1101 vacío<br />
dw @@<strong>13</strong>0 ;1110 –denormal<br />
dw @@120 ;1111 vacío<br />
ENDP ftoa<br />
;<br />
; DIGIT: Convierte el nibble bajo en AL a un dígito ASCII y lo salva en dirección dada por ES:DI<br />
; Llamar con: AL = valor a convertir en bits 0-3<br />
; ES:DI =dirección donde poner carácter ASCII<br />
; Retorna: AL = sin cambio<br />
; ES:DI = dirección+1<br />
;<br />
PROC digit ;nibble a dígito ASCII<br />
push ax ;salva registro<br />
add al,’0’ ;convierte a carácter ASCII<br />
stosb ;salva el carácter<br />
pop ax ;restaura registro<br />
ret<br />
ENDP digit<br />
end ;fin de módulo FTOA.ASM<br />
AUTOR: PROFESOR SALVADOR SAUCEDO FLORES<br />
EDICIÓN: PROFESOR PABLO FUENTES RAMOS<br />
<strong>13</strong>-10
LENGUAJE ENSAMBLADOR 80386 <strong>PRÁCTICA</strong> <strong>13</strong><br />
3.2 Capturar el programa A387.ASM, ensamblarlo y crear el programa<br />
ejecutable<br />
%TITLE “SUMA, RESTA, MULTIPLICA Y DIVIDE NÚMERO CIENTÍFICOS”<br />
; Programa A387, tipo EXE. Suma, resta, multiplica y divide dos número reales<br />
; Ensamblarlo con: tasm /zi a387<br />
; Ligarlo con: tlink /v a387<br />
IDEAL<br />
MODEL small<br />
STACK 256<br />
P386N<br />
P387<br />
Dataseg<br />
C DB -17.35 ;número real de precisión sencilla<br />
D DB 7.153 ;ídem<br />
buff DB 17,18 dup (0) ;cadena queda en buff+2<br />
PROB DB ‘División por cero’,<strong>13</strong>,10,0<br />
ST80387 DW 0<br />
RECORD SW BSY:1,C3:1,TOP:3,C2:1,C1:1,C0:1,IT:1,X:1,P:1,U:1,O:1,Z:1,DE:1,I:1<br />
rc EQU <strong>13</strong> ;ASCII de retorno de carro<br />
nl EQU 10 ;ASCII de nueva línea<br />
ClaveFin DB 0<br />
saludo DB ‘Este programa encuentra la suma, la reta, el producto y’<br />
DB ‘el cociente’,rc,nl<br />
DB ‘de dos números de punto flotante.’<br />
DB ‘Usa el coprocesador 80387.’,rc.rc,nl<br />
DB ‘formato: [+//-][.][E/e][+/-]’,rc,nl,0<br />
RepCPU DB ‘El programa requiere por lo menos un 80386 con coprocesador’,rc,nl,0<br />
A DD 99.98999264 ;4 bytes para real sencillo<br />
B DD 17.01480361 ;ídem para destino<br />
suma DD 0 ;suma en BCD<br />
resta DD 0 ;resta en BCD<br />
multi DD 2 dup (0)<br />
ResSuma DB 26 dup (0) ;resultado de la suma<br />
ResResta DB 26 dup (0) ;resultado de la resta<br />
CadSuma DB ‘La suma es…….: ‘,0<br />
CadResta DB ‘La resta es……..; ‘,0<br />
Apr1er DB ‘Teclear primer número real…:’,0<br />
Apr2do DB ‘Teclear segundo número real…:’,0<br />
ResMulti DB 26 dup (0)<br />
CadMulti DB ‘El producto es…: ‘,0<br />
CadCociente DB ‘El cociente es….: ‘,0<br />
ResCociente DB 26 dup (0)<br />
codeseg<br />
EXTRN atof:near,ftoa:near,SacaCadena:near,SacaCadena2:near<br />
EXTRN Nuevalinea:near,cpu:near,Inicia87:near<br />
AUTOR: PROFESOR SALVADOR SAUCEDO FLORES<br />
EDICIÓN: PROFESOR PABLO FUENTES RAMOS<br />
<strong>13</strong>-11
LENGUAJE ENSAMBLADOR 80386 <strong>PRÁCTICA</strong> <strong>13</strong><br />
Entra:<br />
mov ax,@data ;inicia registro<br />
mov<br />
programa:<br />
ds,ax ;de segmento de datos<br />
mov es,ax<br />
call NuevaLinea ;salta línea<br />
call cpu ;indaga tipo de CPU<br />
cmp ax,386h ;por lo menos un 80386<br />
jae<br />
@@05:<br />
@@10<br />
mov di,offset RepCPU<br />
call SacaCadena ;avisa que saldrá<br />
mov ah,4ch ;función de DOS<br />
int 21h ;para salir<br />
@@10:<br />
mov ax,0000h<br />
call Inicia87<br />
jnz @@05<br />
mov di,offset saludo ;bienvenida e instrucciones<br />
call SacaCadena<br />
call NuevaLinea<br />
mov di,offset Apr1er ;pide primer número<br />
call SacaCadena<br />
mov ah,0ah ;pide cadena de entrada<br />
mov dx,offset buff<br />
int 21h<br />
finit ;limpia pila de 387 y lo inicia<br />
mov si,offset buff+2<br />
call atof<br />
fstp [A] ;lo salva en A<br />
call NuevaLinea ;salta a siguiente línea<br />
mov di,offset Apr2do ;pide segundo número<br />
call SacaCadena<br />
mov ah,0ah<br />
mov dx,offset buff<br />
int 21h<br />
mov si,offset buff+2<br />
call atof ;lo hace flotante<br />
call NuevaLinea<br />
fst [B] ;lo salva en B<br />
fadd [A] ;suma valor en RAM<br />
call NuevaLinea<br />
mov di,offset CadSuma ;exhibe letrero de resultado<br />
call SacaCadena ;de suma<br />
fst [D] ;salvamos resultado<br />
mov si,offset ResSuma<br />
call ftoa ;convierte a ASCII<br />
mov di,offset ResSuma<br />
mov cx,ax ;trae cantidad de caracteres<br />
call SacaCadena2<br />
AUTOR: PROFESOR SALVADOR SAUCEDO FLORES<br />
EDICIÓN: PROFESOR PABLO FUENTES RAMOS<br />
<strong>13</strong>-12
LENGUAJE ENSAMBLADOR 80386 <strong>PRÁCTICA</strong> <strong>13</strong><br />
; hace la resta…<br />
fld [A] ;trae primer número<br />
fsub [B] ;resta valor en RAM<br />
call NuevaLinea<br />
mov di,offset CadResta ;exhibe letrero de resultado<br />
call SacaCadena ;de suma<br />
fst [C] ;salvamos resta<br />
mov si,offset ResResta<br />
call ftoa ;convierte a ASCII<br />
mov di,offset ResResta<br />
mov cx,ax ;trae cantidad de caracteres<br />
call SacaCadena2<br />
; hace la multiplicación…<br />
fld [A] ;trae primer número<br />
fmul [B] ;multiplica por valor en RAM<br />
call NuevaLinea<br />
mov di,offset CadMulti ;exhibe letrero de resultado<br />
call SacaCadena ;de producto<br />
fst [C] ;salvamos producto<br />
mov si,offset ResMulti<br />
call ftoa ;convierte a ASCII<br />
mov di,offset ResMulti<br />
mov cx,ax ;trae cantidad de caracteres<br />
call SacaCadena2<br />
; hace la división…<br />
fld [A] ;trae primer número<br />
fdiv [B] ;divide por el valor en RAM<br />
call NuevaLinea<br />
mov di,offset CadCociente ;exhibe letrero de resultado<br />
call SacaCadena ;de división<br />
fstsw [ST80387] ;salvamos banderas<br />
test [ST80387],MASKZ<br />
jnz @@30<br />
mov si,offset ResCociente<br />
call ftoa ;convierte a ASCII<br />
mov di,offset ResCociente<br />
mov cx,ax ;trae cantidad de caracteres<br />
call SacaCadena2<br />
@@20:<br />
fclex ;limpia excepciones<br />
mov ax,4c00h<br />
int 21h ;fin del programa<br />
@@30:<br />
mov di,offset PROB ;saca mensaje<br />
call SacaCadena ;del problema (división por cero)<br />
jmp SHORT@@20<br />
end Entra ;fin del programa A387.ASM<br />
AUTOR: PROFESOR SALVADOR SAUCEDO FLORES<br />
EDICIÓN: PROFESOR PABLO FUENTES RAMOS<br />
<strong>13</strong>-<strong>13</strong>
LENGUAJE ENSAMBLADOR 80386 <strong>PRÁCTICA</strong> <strong>13</strong><br />
3.3 Ejecutar el programa: C>A387 (Se muestran cuatro corridas)<br />
C:\SEM386>a387<br />
Este programa encuentra la suma, la resta, el producto y el cociente de dos<br />
números de punto flotante. Usa el coprocesador 80387<br />
formato: [+//-][.][E/e][+/-]<br />
Teclear primer número real…..: -54.429<br />
Teclear segundo número real..: 86.542<br />
La suma es…….: +0.321129991455078126E+002<br />
La resta es……..: -0.14097100067<strong>13</strong>86719E+003<br />
El producto es…: -0.471039458198321518E+004<br />
El cociente es….: -0.628931628222747430E+000<br />
C:\SEM386><br />
C:\SEM386>a387<br />
Este programa encuentra la suma, la resta, el producto y el cociente de dos<br />
números de punto flotante. Usa el coprocesador 80387<br />
formato: [+//-][.][E/e][+/-]<br />
Teclear primer número real…..: 1<strong>13</strong>.097<br />
Teclear segundo número real..: -34.29<br />
La suma es…….: +0.788070001220703125E+002<br />
La resta es……..: +0.147387001037597656E+003<br />
El producto es…: -0.387809623772918712E+004<br />
El cociente es….: -0.3298250<strong>13</strong>4220826<strong>13</strong>E+001<br />
C:\SEM386><br />
C:\SEM386>a387<br />
Este programa encuentra la suma, la resta, el producto y el cociente de dos<br />
números de punto flotante. Usa el coprocesador 80387<br />
formato: [+//-][.][E/e][+/-]<br />
Teclear primer número real…..: 9.87e11<br />
Teclear segundo número real..: 14.19567e-6<br />
La suma es…….: +0.987499986944000014E+012<br />
La resta es……..: +0.987499986943999986E+012<br />
El producto es…: +0.140182237339267731E+008<br />
El cociente es….: +0.695634655804740981E+017<br />
C:\SEM386><br />
AUTOR: PROFESOR SALVADOR SAUCEDO FLORES<br />
EDICIÓN: PROFESOR PABLO FUENTES RAMOS<br />
<strong>13</strong>-14
LENGUAJE ENSAMBLADOR 80386 <strong>PRÁCTICA</strong> <strong>13</strong><br />
3.4 Este programa se puede se puede depurar con Turbo Debugger mediante el<br />
siguiente comando:<br />
C>TD A387.EXE<br />
Ejecutar paso a paso las rutinas ftoa y atof y estudiar cómo trabaja.<br />
3.5 Poner los registros en 32 bits y visualizar las variables A y B, que son<br />
reales.<br />
3.6 ¿Cuál es la representación interna de -10.0 y de 25.0?<br />
4 TAREAS<br />
C:\SEM386>a387<br />
Este programa encuentra la suma, la resta, el producto y el cociente de dos<br />
números de punto flotante. Usa el coprocesador 80387<br />
formato: [+//-][.][E/e][+/-]<br />
Teclear primer número real…..: -87.654<br />
Teclear segundo número real..: 0.0<br />
La suma es…….: -0.8765399932861<strong>13</strong>28<strong>13</strong>E+002<br />
La resta es……..: -0.8765399932861<strong>13</strong>28<strong>13</strong>E+002<br />
El producto es…: -0.0000000000000000000E+000<br />
El cociente es….: División por cero<br />
C:\SEM386><br />
4.1 Introducir al programa el procedimiento Confirma y llamarlo para verificar<br />
la opción de realizar otro cálculo<br />
4.2 Verificar los límites de operación del coprocesador numérico corriendo<br />
A387 dando valores críticos.<br />
4.3 Agregar al programa la capacidad de recibir los dos números en la línea de<br />
comandos.<br />
4.4 En el módulo A387.ASM añadir una rutina para exhibir resultados con tres<br />
decimales de precisión, justificando a la derecha el resultado y si el mismo<br />
no cabe en diez lugares, escribir puros asteriscos.<br />
4.5 Hacer que el programa A387 corra si el coprocesador no existe.<br />
AUTOR: PROFESOR SALVADOR SAUCEDO FLORES<br />
EDICIÓN: PROFESOR PABLO FUENTES RAMOS<br />
<strong>13</strong>-15