; --------------------------------------------------------------------------- ; Deze file bevat de afhandeling van floating point functies. Deze functies ; testen niet of de 80x87 processor aanwezig is. Ze mogen pas aangeroepen ; worden als getest is of de coprocessor aanwezig is. Dit kan met subfunctie ; #00. ; Met subfunctie #00 kan eveneens ingesteld worden met welke floating point ; notatie gewerkt dient te worden. Ondersteund worden Atom notatie en Intel8 ; --------------------------------------------------------------------------- ; Auteur: Roland Leurs ; december 1995 ; Toevoeging: Leendert Bijnagte ; februari 1998 0.0 ; Maart 1998 0.1 Aanpassing in documentatie, FPATN opgevoerd ; Domweg vergeten in de vorige uitvoering ; --------------------------------------------------------------------------- P386 P387 ATOM DQ 0 ; ATOM FP GETAL INTEL DQ 0 ; INTEL FP GETAL COPROC DB 0 ; COPROCESSOR TYPE FPMODE DB 0 ; FLOATING POINT MODE CONST180 DQ 180.0 ; CONSTANTE WAARDE 180 HALF DQ 0.5 ; CONSTANTE WAARDE 0.5000 SaveCW DW ? ; var voor 2^x (LB) MaskedCW DW ? ; --------------------------------------------------------------------------- ; Algemene floating point subroutines ; --------------------------------------------------------------------------- ATEL PROC NEAR ; CONVERSIE VAN ATOM->INTEL8 XOR AX,AX ; CLEAR INTEL WAARDE MOV WORD PTR INTEL[0],AX MOV WORD PTR INTEL[2],AX MOV WORD PTR INTEL[4],AX MOV WORD PTR INTEL[6],AX MOV AH,BYTE PTR ATOM[1] ; ATOM MANTISSA NAAR AX:BX MOV AL,BYTE PTR ATOM[2] MOV BH,BYTE PTR ATOM[3] MOV BL,BYTE PTR ATOM[4] XOR DX,DX ; DX OOK BIJ INTEL MANTISSA MOV CX,0BH ; LAADT TELLER ATEL1: SHR AX,1 ; SCHUIF MANTISSA DRIE BITS RCR BX,1 RCR DX,1 LOOP ATEL1 MOV CL,BYTE PTR ATOM[1] ; LAADT SIGN BIT IN CL7 SHL AX,1 ; MAAK PLAATS VOOR SIGN BIT SHL CL,1 ; ZET SIGN BIT IN CARRY RCR AX,1 ; SCHUIF SIGN BIT IN AX AND AX,1000000000001111B ; EXPONENT NOG BEREKENEN MOV CL,BYTE PTR ATOM[0] ; LAADT EXPONENT IN CL XOR CL,80H ; INVERTEER BIAS BIT XCHG AX,CX ; WISSEL AX EN CX TIJDELIJK CBW XCHG AX,CX ; WISSEL AX EN CX WEER ADD CX,1022 ; BEREKEN INTEL'S EXPONENT SHL CX,1 ; RESULTAAT OPSCHUIVEN SHL CX,1 SHL CX,1 SHL CX,1 XOR AX,CX ; EXPONENT TOEVOEGEN MOV WORD PTR INTEL[6],AX ; RESULTAAT OPSLAAN MOV WORD PTR INTEL[4],BX MOV WORD PTR INTEL[2],DX RET ; EINDE ROUTINE ATEL ENDP INTOM PROC NEAR ; CONVERSIE VAN INTEL8->ATOM MOV AH,BYTE PTR INTEL[7] ; LAADT MANTISSA IN AX:BX:BX MOV AL,BYTE PTR INTEL[6] MOV BH,BYTE PTR INTEL[5] MOV BL,BYTE PTR INTEL[4] MOV DH,BYTE PTR INTEL[3] MOV DL,BYTE PTR INTEL[2] MOV CX,11 ; LAADT TELLER INTOM1: SHL DX,1 ; SCHUIF LINKS RCL BX,1 RCL AX,1 LOOP INTOM1 ; ELF MAAL DOEN SHL AX,1 ; EVEN OPSCHUIVEN MOV CL,BYTE PTR INTEL[7] ; LEES TEKEN VAN INTEL SHL CL,1 ; SCHUIF TEKEN IN CARRY RCR AX,1 ; SCHUIF TEKEN IN MANTISSA MOV BYTE PTR ATOM[1],AH ; ATOM MANTISSA WEGSCHRIJVEN MOV BYTE PTR ATOM[2],AL MOV BYTE PTR ATOM[3],BH MOV BYTE PTR ATOM[4],BL MOV AH,BYTE PTR INTEL[7] ; LAADT INTEL EXPONENT MOV AL,BYTE PTR INTEL[6] MOV CL,4 ; LAADT TELLER SHR AX,CL ; BEPAAL EXPONENT AND AX,7FFH ; ALLEEN ONDERSTE 11 BITS SUB AX,1022 ; ATOM EXPONENT BEREKENEN PUSHF ; SAVE CARRY SHL AL,1 ; EVEN PLAATSMAKEN VOOR BIAS POPF ; HAAL CARRY TERUG RCR AL,1 ; ZET CARRY ALS BIAS XOR AL,80h ; INVERT OM KLOPPEND TE MAKEN MOV BYTE PTR ATOM[0],AL ; BERG ATOM EXPONENT OP RET ; EINDE ROUTINE INTOM ENDP ZENDREAL PROC NEAR ; STUUR FP GETAL NAAR ATOM CMP FPMODE,0 ; TEST OP ATOM MODE JNE ZENDREAL1 ; SPRING INDIEN INTEL MODE CALL INTOM ; CONVERTEER WAARDE NAAR ATOM MOV SI,OFFSET ATOM ; LAADT ADRES ATOM MODE MOV CX,5 ; LEES AANTAL TE ZENDEN BYTES JMP SHORT ZENDREAL2 ; GEDWONGEN SPRONG ZENDREAL1: MOV SI,OFFSET INTEL ; LAADT ADRES INTEL MODE MOV CX,8 ; LAADT AANTAL TE ZENDEN BYTES ZENDREAL2: MOV AL,BYTE PTR [SI] ; LEES BYTE CALL ZENDBYTE ; STUUR NAAR ATOM INC SI ; VERHOOG POINTER LOOP ZENDREAL2 ; DOE VOOR ALLE BYTES RET ; EINDE ROUTINE ZENDREAL ENDP LEESREAL PROC NEAR ; LEES FP GETAL VAN ATOM CMP FPMODE,0 ; TEST OP ATOM MODE JNE LEESREAL1 ; SPRING INDIEN INTEL MODE MOV DI,OFFSET ATOM ; LAADT ADRES ATOM MODE MOV CX,5 ; LEES AANTAL TE ZENDEN BYTES JMP SHORT LEESREAL2 ; GEDWONGEN SPRONG LEESREAL1: MOV DI,OFFSET INTEL ; LAADT ADRES INTEL MODE MOV CX,8 ; LAADT AANTAL TE ZENDEN BYTES LEESREAL2: CALL LEESBYTE ; LEES BYTE VAN ATOM MOV BYTE PTR [DI],AL ; BERG OP IN VARIABELE INC DI ; VERHOOG POINTER LOOP LEESREAL2 ; DOE VOOR ALLE BYTES CMP FPMODE,0 ; TEST NOGMAALS OP ATOM MODE JNE LEESREAL3 ; SPRING INDIEN NIET ATOM CALL ATEL ; ZET OM NAAR INTEL NOTATIE LEESREAL3: RET ; EINDE ROUTINE LEESREAL ENDP ; --------------------------------------------------------------------------- ; Subcommando interpreter ; --------------------------------------------------------------------------- FPFUN: CALL LEESBYTE ; LEES SUBFUNCTIE NUMMER CMP AL,20H ; TEST OP GELDIGE FUNCTIE JLE FPFUN1 ; SPRING INDIEN GELDIG MOV FUN_CODE,AL ; ZET AL IN WERKRUIMTE ;MP ERROR ; GEEF FOUTMELDING EN BEEINDIG ROUTINE FPFUN1: MOV AH,0 ; MAAK HOGE BYTE AX 0 SHL AX,1 ; MAAK ER EEN WORD POINTER VAN MOV BX,AX ; ZET TABEL OFFSET IN BASE REGISTER JMP WORD PTR FPTAB[BX] ; SPRING NAAR SUBFUNCTIE FPTAB: DW FPROC, FPADD, FPSUB, FPMUL, FPDIV, FPABS ; 0, 1, 2, 3, 4, 5 DW FPRNDINT, FPSQRT, FTANG, FPSIN, FPCOS ; 6, 7, 8, 9, A DW FPDEG, FPRAD, FPOWER, FPHTN, FPLN, FPLOG ; b, c, d, e, f, 10 DW FPYTOX, FPEXP, FPTENTOX, FPACOT, FPACOS ; 11, 12, 13, 14, 15 DW FPASIN, FPSEC, FPCSC, FPCOT, FPTWOTOX ; 16, 17, 18, 19, 1a DW FPATN ; 1b DW FPEQ, FPNE, FPGE, FPGT, FPLE, FPLT ; 1C, 1D, 1E, 1F, 20 ; Dit is de wensenlijst van Leendert van functies die er in zouden moeten ; Niet direct bij aanvang, maar zeker bij latere uitbreidingen. ; Naam | Doel van de functie unc. No Datum Laatste ; FABS | Absolute value 5 13/3/1998 ; FACOS | FP Arc Cosine 21 13/3/1998 ; FASIN | FP Arc Sine 22 13/3/1998 ; FATAN | FP Arc Tangent 27 13/3/1998 ; FATANH | FP Hyperbolic Arc Tangent 14 13/3/1998 ; FCOS | FP Cosine 10 13/3/1998 ; FCOSH | FP Hyperbolic Cosine ; FETOX | FP e^x 17 13/3/1998 ; FETOXM1 | FP e^(x-1) ; FGETEXP | Get exponent ; FGETMAN | Get mantissa ; FINT | FP Integer ; FINTRZ | Get integer and round down ; FLOGN | FP Ln(n) 15 13/3/1998 ; FLOGNP1 | FP Ln(n+1) ; FLOG10 | FP Log10(n) 16 13/3/1998 ; FLOG2 | FP Log2(n) ; FNEG | Negate a floating point number ; FSIN | FP Sine 9 13/3/1998 ; FSINH | FP Hyperbolic Sine ; FSQRT | FP Square Root 7 13/3/1998 ; FTAN | FP Tangent 8 13/3/1998 ; FTANH | FP Hyperbolic Tangent ; FTENTOX | FP 10^x 18 13/3/1998 ; FTWOTOX | FP 2^x 26 13/3/1998 ; --------------------------------------------------------------------------- ; Commando's ; --------------------------------------------------------------------------- FPROC: CALL LEESBYTE ; LEES FP-MODE (0=ATOM, 1=INTEL) MOV FPMODE,AL ; BERG OP FNINIT ; INIT COPROCESSOR XOR DX,DX ; CLEAR PROCESSORTYPE MOV WORD PTR INTEL,5A5AH FNSTSW WORD PTR INTEL CMP BYTE PTR INTEL,DL JNE SET_FLAGS ; GEEN COPROCESSOR AANWEZIG FNSTCW WORD PTR INTEL MOV AX,WORD PTR INTEL AND AX,103FH CMP AX,3FH JNE SET_FLAGS ; GEEN COPROCESSOR AANWEZIG INC DX ; VERHOOG PROCESSORTYPE 8087/80287 FLD1 FLDZ FDIV FLD ST FCHS FCOMPP FSTSW WORD PTR INTEL MOV AX,WORD PTR INTEL SAHF JE SET_FLAGS ; SPRING ALS 8087 OF 80287 INC DX ; HET IS EEN 80387 OF HOGER SET_FLAGS: MOV COPROC,DL ; SCHRIJF PROCESSORTYPE WEG MOV AL,DL ; STUUR TEVENS NAAR ATOM CALL ZENDBYTE JMP LEESCOM ; EINDE COMMANDO FPADD: CALL LEESREAL ; LEES EERSTE GETAL FLD INTEL ; LEES IN PROCESSOR CALL LEESREAL ; LEES TWEEDE GETAL FADD INTEL ; TEL DE GETALLEN OP FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO FPSUB: CALL LEESREAL ; LEES EERSTE GETAL FLD INTEL ; LEES IN PROCESSOR CALL LEESREAL ; LEES TWEEDE GETAL FSUB INTEL ; TREK GETALLEN VAN ELKAAR AF FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO FPMUL: CALL LEESREAL ; LEES EERSTE GETAL FLD INTEL ; LEES IN PROCESSOR CALL LEESREAL ; LEES TWEEDE GETAL FMUL INTEL ; VERMENIGVULDIG DE GETALLEN FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO FPDIV: CALL LEESREAL ; LEES EERSTE GETAL FLD INTEL ; LEES IN PROCESSOR CALL LEESREAL ; LEES TWEEDE GETAL FDIV INTEL ; DEEL DE GETALLEN FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO FPABS: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR FABS ; BEREKEN ABSOLUTE WAARDE FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO FPRNDINT: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR FRNDINT ; ROND AF NAAR INTEGER WAARDE FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO FPSQRT: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR FSQRT ; BEREKEN VIERKANTSWORTEL FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO FTANG: CALL LEESREAL ; LEES GETAL CMP COPROC,2 ; TEST OP 80387 JE FTAN387 ; JA, VERVOLG ROUTINE JMP FTAN287 ; VOOR 287 ANDERE ROUTINE FTAN387: FLD INTEL ; LEES WAARDE IN PROCESSOR FPTAN ; BEREKEN VERHOUDING Y/X FDIV ; BEREKEN TANGENS FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO FTAN287: CALL _FTAN287 ; LAAT TANGENS BEREKENEN DOOR PROC CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO _FTAN287 PROC NEAR ; BEREKEN TANGENS VAN GETAL IN ST FINIT FLD INTEL ; LEES WAARDE IN PROCESSOR FLD HALF ; LAAD 0.5 FLDPI ; LAAD PI FMUL ; BEREKEN 0.5*PI FLDPI ; LAAD PI NOGMAALS FXCH ST(2) ; ST=x, ST(1)=0.5*PI, ST(2)=PI FTST ; BEPAAL TEKEN VAN ST FSTSW TEMP ; ZET STATUSREGISTER IN TEMP FWAIT MOV AX,WORD PTR TEMP; KOPIEER STATUS NAAR FLAGS SAHF JC FTAN_NEG ; SPRING ALS ST < 0 FTAN_POS: FCOM ST(1) ; KIJK OF ST > 0.5*PI FSTSW TEMP FWAIT MOV AX,WORD PTR TEMP AND AH,01000001B ; FILTER BENODIGDE STATUSBITS JNZ FTAN287A ; EXIT ALS ST <= 0.5*PI FSUB ST,ST(2) ; ST:=ST-PI JMP SHORT FTAN_POS FTAN_NEG: FXCH ST(1) ; ZET -0.5*PI IN ST(1) FCHS FXCH ST(1) ; ST=x, ST(1)=-0.5*PI, ST(2)=PI FTAN_NEG1: FCOM ST(1) ; KIJK OF ST < -0.5*PI FSTSW TEMP FWAIT MOV AX,WORD PTR TEMP SAHF JNC FTAN287A ; EXIT ALS ST >= -0.5*PI FADD ST,ST(2) ; ST:=ST+PI JMP SHORT FTAN_NEG1 FTAN287A: FTST ; BEPAAL TEKEN VAN NIEUWE ST FSTSW TEMP ; BERG OP IN WERKRUIMTE FABS ; BEPAAL |ST| FLD HALF ; LAAD 0.5 FMUL ST,ST(3) ; VERMENIGVULDIG MET 0.5*PI FABS ; HET RESULTAAT KAN NEGATIEF ZIJN FCOM ; TEST OF ST(1) < OF > 0.25*PI FSTSW TEMP[2] FWAIT MOV AX,WORD PTR TEMP[2] SAHF JC FTANREV ; SPRING ALS ST(1) > 0.25*PI FLD ST(1) ; LAAD ARGUMENT IN ST FPTAN ; BEREKEN TANGENS VAN ST FDIV JMP SHORT FTAN287B ; GA TEKEN NOG GOED ZETTEN FTANREV: FLD HALF ; LAAD 0.5 FLDPI ; LAAD PI FMUL ; BEREKEN 0.5*PI FSUB ST,ST(1) ; BEREKEN 0.5*PI-ST(1) FPTAN ; BEREKEN DAAR DE TANGENS VAN FDIV FLD1 ; LAAD WAARDE 1 FDIV ; BEREKEN 1/TAN(0.5*PI-x) FTAN287B: MOV AX,WORD PTR TEMP; HAAL TEKEN INFO TERUG SAHF ; ZET IN FLAGS JNC FTAN287C ; SPRING INDIEN POSITIEF FCHS ; MAAK NEGATIEF FTAN287C: FSTP INTEL ; ZET EINDRESULTAAT IN WERKRUIMTE FWAIT RET ; EINDE TAN287 ROUTINE _FTAN287 ENDP P386 ; DEZE FUNCTIES ALLEEN VOOR 80386 P387 FPSIN: CALL LEESREAL ; LEES GETAL CMP COPROC,2 ; TEST OP 387 JE FPSIN387 JMP FPSIN287 ; VOOR 287 ANDERE ROUTINE FPSIN387: FLD INTEL ; LEES IN PROCESSOR FSIN ; BEREKEN SINUS FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO P286 P287 FPSIN287: CALL FPCOSIN287 ; BEREKEN SINUS FLD QWORD PTR TEMP ; LAAD SINUS FSTP INTEL ; ZET IN GEHEUGEN FWAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO P386 P387 FPCOS: CALL LEESREAL ; LEES GETAL CMP COPROC,2 ; TEST OP 387 JE FPCOS387 JMP FPCOS287 ; VOOR 287 ANDERE ROUTINE FPCOS387: FLD INTEL ; LEES IN PROCESSOR FCOS ; BEREKEN COSINUS FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO P286 ; EN WEER TERUG NAAR 286 INSTRUKTIES P287 FPCOS287: CALL FPCOSIN287 ; BEREKEN COSINUS CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE ROUTINE FPCOSIN287 PROC NEAR ; BEREKEN COS EN SIN VAN ST FLDPI ; LAAD PI FLD INTEL ; LAAD x FPREM FST QWORD PTR TEMP[24] ; BEWAAR IN WERKRUIMTE FSTP INTEL ; PLAATS IN WERKRUIMTE FWAIT CALL _FTAN287 ; BEREKEN TAN FLD INTEL ; HAAL TAN OP FST QWORD PTR TEMP[16] ; BERG OP VOOR LATER GEBRUIK FLD INTEL ; HAAL NOGMAALS TAN OP FMUL ; BEREKEN TAN-KWADRAAT FLD1 ; TEL ER 1 BIJ OP FADD FLD1 ; LAAD 1 FDIVR ; BEREKEN 1/(1+TAN-KWADRAAT) FSQRT ; BEREKEN SQRT (1/(1+TAN-KWADRAAT)) FSTP INTEL ; ZET IN GEHEUGEN FWAIT FLD QWORD PTR TEMP[24] ; TEKEN NOG AANPASSEN FABS ; BEPAAL |ST| (ST= x) FLDPI ; LAAD PI FLD HALF ; LAAD 0.5 FMULP ; ST = 0.5*PI FCOM ST(1) ; TEST OF |x| < 0.5*PI FSTSW TEMP MOV AX,WORD PTR TEMP SAHF JNC FPCOSIN287A FLD INTEL ; WIJZIG HET TEKEN FCHS FST INTEL ; BERG COS x WEER OP FPCOSIN287A: FLD INTEL ; LAAD COS IN ST FLD QWORD PTR TEMP[16] ; LAAD TAN IN ST FMUL ; COS * TAN = SIN FSTP QWORD PTR TEMP ; BERG SIN x OP IN TEMP FWAIT FINIT ; RESET 287 RET ; INTEL=COS, ST=SIN FPCOSIN287 ENDP FPDEG: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR FMUL CONST180 ; VERMENIGVULDIG MET 180 FLDPI ; DEEL DOOR PI FDIV FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO FPRAD: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR FDIV CONST180 ; DEEL DOOR 180 FLDPI ; DEEL DOOR PI FMUL FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO ; Dit ding gebruik ik als raamwerk voor de volgende functies. ; Hier wordt een argument doorgegeven en vervolgens ook weer geretourneerd. ;FPSKEL: CALL LEESREAL ; LEES GETAL ; FLD INTEL ; LEES IN PROCESSOR ; FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN ; WAIT ; CALL ZENDREAL ; STUUR NAAR ATOM ; JMP LEESCOM ; EINDE COMMANDO ; FPEQ vergelijkt twee waarden op de stack en geeft in geval van ; een gelijke waarde een 0 terug en anders een 1 ; bits C0, 1 en 3 bevatten relevante informatie: ; C3 C2 C0 ; 0 0 0 st > source (JA, JAE) ; 0 0 1 st < source (JB, JBE) ; 1 0 0 st = source (JZ) ; 1 1 1 st is geen nummer FPEQ: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR CALL LEESREAL ; put number on top of stack FLD INTEL FCOMPP ; sleur 2 waardes van de stack mov bl, 02AH ; bl op 0, geen Z geen C op 6502 niveau FSTSW AX ; status in ax, update flags sahf ; store C0 in carry, c2 in par, en c3 in zero flag JZ equal mov bl, 0 ; doe alsof er een Carry en een Z is voor de 6502 equal: WAIT MOV AL, bl ; ALLES 0 CALL ZENDBYTE ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO ; FPNE vergelijkt twee waarden op de stack en geeft in geval van ; een gelijke waarde een 0 terug en anders een 1 ; bits C0, 1 en 3 bevatten relevante informatie: ; C3 C2 C0 ; 0 0 0 st > source (JA, JAE) ; 0 0 1 st < source (JB, JBE) ; 1 0 0 st = source (JZ) ; 1 1 1 st is geen nummer FPNE: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR CALL LEESREAL ; put number on top of stack FLD INTEL FCOMPP ; sleur 2 waardes van de stack mov bl, 02AH ; bl op 0, geen Z geen C op 6502 niveau FSTSW AX ; status in ax, update flags sahf ; store C0 in carry, c2 in par, en c3 in zero flag JZ neequal mov bl, 0 ; doe alsof er een Carry en een Z is voor de 6502 neequal: WAIT MOV AL, bl ; ALLES 0 CALL ZENDBYTE ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO ; FPGT vergelijkt twee waarden op de stack en geeft in geval van ; een gelijke waarde een 0 terug en anders een 1 ; bits C0, 1 en 3 bevatten relevante informatie: ; C3 C2 C0 ; 0 0 0 st > source (JA, JAE) ; 0 0 1 st < source (JB, JBE) ; 1 0 0 st = source (JZ) ; 1 1 1 st is geen nummer FPGT: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR CALL LEESREAL ; put number on top of stack FLD INTEL FCOMPP ; sleur 2 waardes van de stack mov bl, 0 ; bl op 0, geen Z geen C op 6502 niveau FSTSW AX ; status in ax, update flags sahf ; store C0 in carry, c2 in par, en c3 in zero flag JNC gethan mov bl, 02BH ; doe alsof er een Carry en een Z is voor de 6502 gethan: WAIT MOV AL, bl ; ALLES 0 CALL ZENDBYTE ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO ; FPGE vergelijkt twee waarden op de stack en geeft in geval van ; een gelijke waarde een 0 terug en anders een 1 ; bits C0, 1 en 3 bevatten relevante informatie: ; C3 C2 C0 ; 0 0 0 st > source (JA, JAE) ; 0 0 1 st < source (JB, JBE) ; 1 0 0 st = source (JZ) ; 1 1 1 st is geen nummer FPGE: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR CALL LEESREAL ; put number on top of stack FLD INTEL FCOMPP ; sleur 2 waardes van de stack mov bl, 02AH ; bl op 0, geen Z geen C op 6502 niveau FSTSW AX ; status in ax, update flags sahf ; store C0 in carry, c2 in par, en c3 in zero flag Jbe geequal mov bl, 0 ; doe alsof er een Carry en een Z is voor de 6502 geequal: WAIT MOV AL, bl ; ALLES 0 CALL ZENDBYTE ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO ; FPLT vergelijkt twee waarden op de stack en geeft in geval van ; een gelijke waarde een 0 terug en anders een 1 ; bits C0, 1 en 3 bevatten relevante informatie: ; C3 C2 C0 ; 0 0 0 st > source (JA, JAE) ; 0 0 1 st < source (JB, JBE) ; 1 0 0 st = source (JZ) ; 1 1 1 st is geen nummer FPLT: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR CALL LEESREAL ; put number on top of stack FLD INTEL FCOMPP ; sleur 2 waardes van de stack mov bl, 02CH ; bl op 0, geen Z geen C op 6502 niveau FSTSW AX ; status in ax, update flags sahf ; store C0 in carry, c2 in par, en c3 in zero flag JBE let mov bl, 0 ; doe alsof er een Carry en een Z is voor de 6502 let: WAIT MOV AL, bl ; ALLES 0 CALL ZENDBYTE ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO ; FPLE vergelijkt twee waarden op de stack en geeft in geval van ; een gelijke waarde een 0 terug en anders een 1 ; bits C0, 1 en 3 bevatten relevante informatie: ; C3 C2 C0 ; 0 0 0 st > source (JA, JAE) ; 0 0 1 st < source (JB, JBE) ; 1 0 0 st = source (JZ) ; 1 1 1 st is geen nummer FPLE: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR CALL LEESREAL ; put number on top of stack FLD INTEL FCOMPP ; sleur 2 waardes van de stack mov bl, 02AH ; bl op 0, geen Z geen C op 6502 niveau FSTSW AX ; status in ax, update flags sahf ; store C0 in carry, c2 in par, en c3 in zero flag Jbe leeq mov bl, 0 ; doe alsof er een Carry en een Z is voor de 6502 leeq: WAIT MOV AL, bl ; ALLES 0 CALL ZENDBYTE ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO ; HTN(x)- Berekent de hyperbolische tangens van hoek x in radialen. ; Maakt gebruik van een formule, omdat de functie niet als ; implied instructie beschikbaar is. ; ; htn(x) = (exp(x) - exp(-x) / exp(x) + exp(-x) ). ; FPHTN: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR call exp ; bereken exponent (e tot de macht (arg)) FLD INTEL ; LEES IN PROCESSOR fchs ; wissel het teken call exp ; bereken van -x het exponent fld st(1) ; dupliceer het eerste antwoord fld st(1) ; en dupliceer het tweede antwoord fsub ; trek beide van elkaar af. fld st(2) ; dupliceer het eerste antwoord op stack faddp st(2),st ; tel TOS en ST0 op en plaats op TOS fdiv st,st(1) ; deel deze tegen elkaar weg FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN fstp ; ruim rotzooi op (st(1)) fstp st(0) ; ruim rotzooi op WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO ; LN(x)- bereken op basis van het natuurlijk grondtal E het logarithme van x ; X moet groter zijn dan 0. ; Maakt gebruik van een formule, omdat de functie niet als ; implied instructie beschikbaar is. ; ; ln(x) = lg(x)/lg(e). FPLN: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR fld1 ; laadt constante 1 fxch ; maak er -1 van fyl2x ; bereken 1*lg(x). fldl2e ; Laadt lg(e). fdiv ; bereken lg(x)/lg(10). FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT ; sync voor de 80x86 gebruikers CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO ; LOG(x)- bereken de logaritme met 10 als grondtal. ; Gebruikelijke range voor X: >= 0 ; Maakt gebruik van een formule, omdat de functie niet als ; implied instructie beschikbaar is. ; ; LOG(x) = lg(x)/lg(10). FPLOG: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR fld1 ; laadt constante 1 fxch ; wissel TOS en ST(1) van plek fyl2x ; Bereken 1*lg(x). fldl2t ; Laadt lg(10). fdiv ; Bereken lg(x)/lg(10). FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT ; sync voor de 80x86 gebruikers CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO ; YtoX(y,x)- Berekent y**x, waarbij (y=st(1), x=st(0)). ; Deze routine vereist drie vrije registers. ; Maakt gebruik van een formule, omdat de functie niet als ; implied instructie beschikbaar is. ; Tevens wordt de subroutine Two2X aangeroepen. ; ; Y moet groter zijn dan 0. ; ; YtoX(y,x) = 2 ** (x * lg(y)) FPYTOX: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR CALL LEESREAL ; put number on top of stack FLD INTEL ; LEES IN PROCESSOR fxch ; Wissel TOS en ST(1) van plek fld1 ; laadt constante 1 fxch ; Wissel TOS en ST(1) van plek fyl2x ; bereken logaritme: fmul ; Bereken x*lg(y). call Two2X ; Bereken 2**(x*lg(y)). FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN fSTP ST(0) ; HEBBEN WE OOK NIET NODIG. WAIT ; sync voor de 80x86 gebruikers CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO ; exp(x)- Berekent e**x. ; Deze routine vereist drie vrije registers. ; Maakt gebruik van een formule, omdat de functie niet als ; implied instructie beschikbaar is. ; Tevens wordt de subroutine Two2X aangeroepen. ; ; exp(x) = 2**(x * lg(e)) FPEXP: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR fldl2e ; Plaats lg(e) op de stack. fmul ; Bereken x*lg(e). call Two2X ; Bereken 2**(x * lg(e)) FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN FSTP ST(0) ; HEBBEN WE OOK NIET NODIG. WAIT ; sync voor de 80x86 gebruikers CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO ; Two2X(x)- Berekent 2**x. ; Deze routine vereist drie vrije registers. ; Tevens wordt de subroutine Two2X aangeroepen. ; FPTWOTOX: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN CALL Two2X ; de man in kwestie FSTP ST(0) ; HEBBEN WE OOK NIET NODIG. WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO ; TenToX(x)- Berekent 10**x. ; Deze routine vereist drie vrije registers. ; Maakt gebruik van een formule, omdat de functie niet als ; implied instructie beschikbaar is. ; Tevens wordt de subroutine Two2X aangeroepen. ; ; TenToX(x) = 2**(x * lg(10)) FPTENTOX: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR fldl2t ; Zet lg(10) op de stack fmul ; Bereken x*lg(10) call Two2X ; Bereken 2**(x * lg(10)). FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN FSTP ST(0) ; HEBBEN WE OOK NIET NODIG. WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO ; Two2X(x)- Berekent 2**x. ; Dit wordt bereikt door het volgende regeltje toe te passen: ; ; 2**x = 2**int(x) * 2**frac(x). ; We kunnen eenvoudig berekenen 2**int(x) met fscale en ; 2**frac(x) door gebruik te maken van f2xm1. ; ; Deze routine vereist drie vrije registers. ; Modificeer het control word om af te kappen indien er afgerond moet worden Two2X proc near fstcw SaveCW fstcw MaskedCW or byte ptr MaskedCW+1, 1100b fldcw MaskedCW fld st(0) ;Dupliceer tos. fld st(0) frndint ;Bereken integer deel fxch ;Swap FP en INT waardes fsub st(0), st(1) ;Bereken fractional deel f2xm1 ;Bereken 2**frac(x)-1. fld1 fadd ;Bereken 2**frac(x). fxch ;Get integer deel fld1 ;Bereken 1*2**int(x). fscale fstp st(1) ;Verwijder st(1) (wat hier 1 is). fmul ;Bereken 2**int(x) * 2**frac(x). fldcw SaveCW ;Terug naar de afrond mode. ret Two2X endp ; exp(x)- Berekent e**x. ; Deze routine vereist drie vrije registers. ; Maakt gebruik van een formule, omdat de functie niet als ; implied instructie beschikbaar is. ; Tevens wordt de subroutine Two2X aangeroepen. ; ; exp(x) = 2**(x * lg(e)) exp proc near fldl2e ;Zet lg(e) op de stack. fmul ;Bereken x*lg(e). call Two2X ;Bereken 2**(x * lg(e)) fstp st(1) ;Zooi opruimen ret exp endp ; ATN(x)- Berekent de arctangent van st(0) en laat zet resultaat ; in st(0). ; X <> 0 ; Ten minste een vrij register is noodzakelijk voor deze functie ; ; acot(x) = atan(x/1) FPATN: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR fld1 ; fpatan Berekening fpatan ; we willen de atan(st(0)/st(1)). FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO ; ACOT(x)- Berekent de arctangent van st(0) en laat zet resultaat ; in st(0). ; X <> 0 ; Ten minste een vrij register is noodzakelijk voor deze functie ; ; acot(x) = atan(1/x) FPACOT: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR fld1 ; fpatan Berekens fxch ; atan(st(1)/st(0)). fpatan ; we willen atan(st(0)/st(1)). FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO ; ACOS(x)- Berekent de arccosinus van st(0). Resultaat in ST(0) ; Toegestane reekse: -1<=x<=+1 ; Deze routine vereist twee vrije registers. ; Maakt gebruik van een formule, omdat de functie niet als ; implied instructie beschikbaar is. ; ; acos(x) = atan(sqrt((1-x*x)/(x*x))) FPACOS: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR fld st(0) ; Dupliceer X op tos. fmul ; Bereken X**2. fld st(0) ; Dupliceer X**2 op tos. fld1 ; Bereken 1-X**2. fsubr fdivr ; Bereken (1-x**2)/X**2. fsqrt ; Bereken sqrt((1-X**2)/X**2). fld1 ; Om volledgige arctangens te berekenen fpatan ; Bereken atan van de bovenstaande FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO ; ASIN(x)- Berekent de arcsinus van st(0). Berg resultaat op in ST(0) ; Toegestane reekse: -1<=x<=+1 ; Deze routine vereist twee vrije registers. ; Maakt gebruik van een formule, omdat de functie niet als ; implied instructie beschikbaar is. ; ; asin(x) = atan(sqrt(x*x/(1-x*x))) FPASIN: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR fld st(0) ; Dupliceer X op tos. fmul ; Bereken X**2. fld st(0) ; Dupliceer X**2 on tos. fld1 ; Bereken 1-X**2. fsubr fdiv ; Bereken X**2/(1-X**2). fsqrt ; Bereken sqrt(x**2/(1-X**2)). fld1 ; Om volledgige arctangens te berekenen fpatan ; Bereken atan van de bovenstaande FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO ; hiero ; SEC(x) - Berekent het secant van st(0). Resultaat in ST0 ; st(0) bevat x (in radialen) en moet liggen in de reeks ; -2**63 and +2**63. ; Het secant van x is ongedefineerd voor elke waarde van cos(x) wat ; oplevert 0 (b.v. pi/2 radialen). ; Deze routine vereist drie vrije registers. ; Maakt gebruik van een formule, omdat de functie niet als ; implied instructie beschikbaar is. ; ; sec(x) = 1/cos(x) P386 ; DEZE FUNCTIES ALLEEN VOOR 80386 P387 FPSEC: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR FCOS ; bepaal cosinus fld1 ; laadt 1 als constante fdivr ; deel koos en miep FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO ; CSC(x) - Berekent de cosecant van st(0). Resultaat in ST0 ; st(0) bevat x (in radialen) en moet liggen in de reeks ; -2**63 and +2**63. ; Het cosecant van x is ongedefineerd voor elke waarde van sin(x) wat ; oplevert 0 (b.v. 0 of pi radialen). ; Deze routine vereist drie vrije registers. ; Maakt gebruik van een formule, omdat de functie niet als ; implied instructie beschikbaar is. ; ; csc(x) = 1/sin(x) P386 ; DEZE FUNCTIES ALLEEN VOOR 80386 P387 FPCSC: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR FSIN ; bepaal sinus fld1 ; laadt 1 als constante fdivr ; deel koos en miep FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO ; COT(x) - Berekent the cotangens van st(0). Resultaat in ST0 ; st(0) bevat x (in radialen) en moet liggen in de reeks ; -2**63 and +2**63 ; Deze routine vereist drie vrije registers. ; Maakt gebruik van een formule, omdat de functie niet als ; implied instructie beschikbaar is. ; ; cot(x) = 1/tan(x) P386 ; DEZE FUNCTIES ALLEEN VOOR 80386 P387 FPCOT: CALL LEESREAL ; LEES GETAL FLD INTEL ; LEES IN PROCESSOR FSINCOS ; bereken sinus en cosinus fdivr ; het 1 complement FSTP INTEL ; ZET RESULTAAT IN GEHEUGEN WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE COMMANDO ; Power(x,y) Berekent y**x, waarbij (y=st(1), x=st(0)). ; ; Y moet groter zijn dan 0. ; Routine van Roland, die dus alleen al om die reden niet in ; deze source mag ontbreken. Wordt vervangen door de FPYTOX routine ; die sneller en eenvoudiger is. FPOWER: CALL LEESREAL ; LEES GETAL FLD INTEL ; put power on top of stack CALL LEESREAL ; put number on top of stack FLD INTEL fabs ; make sure it's not negative ftst ; is it's zero .... fstsw AX sahf jne not_zero jmp get_out ; ...yes, so get out with 0.0 on TOS not_zero: ; now st(1) = power, st = number fyl2x ; st = number * log power base 2 fstcw TEMP+2 ; save the control word to restore later fstcw WORD PTR temp ; to change rounding control to round-down and WORD PTR temp,0F33FH ; clear out RoundingControl bits or WORD PTR temp,0400H ; set for Round-down fldcw WORD PTR temp ; put it in control word fld st(0) ; push copy of number frndint ; st = z1, st(1) = z fldcw TEMP+2 ; restore initial control word fsub st(1), st ; st(1) = z2 = (z-z1) fxch ; st = z2, st(1) = z1 fld half ; 1/2 -> top of stack fxch ; st = z2, st(1) = 1/2 fprem ; st is z2 or z2=1/2; if z2=1/2, c1=1 fstsw TEMP+2 fstp st(1) ; now flags are set, so get rid of the half f2xm1 ; st is now ((2 to the st) - 1) fld1 faddp st(1), st test TEMP+3,00000010B; st has z2 if bit 1 on jz was_z2 ; else it had z2 - 1/2 fld1 fadd st, st(0) fsqrt ; so multiply it by the square root of 2 fmulp st(1), st was_z2: fscale ; just need to scale by 2**st(1) get_out: fstp st(1) fstp INTEL ; BERG RESULTAAT OP WAIT CALL ZENDREAL ; STUUR NAAR ATOM JMP LEESCOM ; EINDE ROUTINE