Skip to content

Latest commit

 

History

History
1181 lines (1047 loc) · 23.9 KB

INIT8087.md

File metadata and controls

1181 lines (1047 loc) · 23.9 KB

Initialize 8087/80287/80387

Initializes FPU routines in System Library.

SYS02E5: CALL 074C

Test for presence of FPU and identify the FPU with a call to SYS:074C Identify 8087/80287/80387 FPU.

SYS02E8: OR AL,AL
SYS02EA: JZ 02F5

Check whether an FPU is present then exit when there is none.

SYS02EC: MOV SI,0613
SYS02EF: MOV DI,0693
SYS02F2: JMP 07D9

Initialize FPU handlers and routines with a jump to SYS:07D9.

SYS02F5: PUSH DS
SYS02F6: MOV DX,0306
SYS02F9: PUSH CS
SYS02FA: POP DS
SYS02FB: MOV AH,09
SYS02FD: INT 21
SYS02FF: POP DS
SYS0300: MOV AX,00FF
SYS0303: JMP 0116

Prints the error message (SYS:306) and exits with a runtime error FFh/255 Unknown Error.

Data block (string)

SYS0306:      4E 75-6D 65 72 69 63 20 63 6F         Numeric co
SYS0310: 3 65 73 73-6F 72 20 72 65 71 75 69   -processor requi
SYS0320: A 24                                 red..$

Data block (DWORD/TBYTE)

TBYTE (SYS:0326-032F)

SYS0326: 2 DA 0F C9 FE 3F

TBYTE (SYS:0330-0339)

SYS0330: 2 DA 0F C9-FF 3F

DWORD (SYS:033A-033D)

SYS033A:  00 42 C0 FF

DWORD (SYS:033E-0341)

SYS033E:  00 48
SYS0340:  C0 FF

DWORD (SYS:0342-0345)

SYS0342:  00 4A C0 FF

DWORD (SYS:0346-0349)

SYS0346:  00 00-00 3F

TBYTE (SYS:034A-0353)

SYS034A: 3 F3
SYS0350:  04 B5 FF 3F

DWORD (SYS:0354-0357)

SYS0354:  00 00 80 7F

Handler called by SYS:06AC on offset = ECh/EEh/F0h (see SYS:0693 Handler for INT 3Eh below)

Called by SYS:06AC on offset = ECh (see SYS:0693 Handler for INT 3Eh below)

SYS0358: MOV CL,00
SYS035A: JMP 0362

Called by SYS:06AC on offset = EEh (see SYS:0693 Handler for INT 3Eh below)

SYS035C: MOV CL,02
SYS035E: JMP 0362

Called by SYS:06AC on offset = F0h (see SYS:0693 Handler for INT 3Eh below)

SYS0360: MOV CL,04

Common code used by SYS:0358, SYS:035C, SYS:0360

SYS0362: WAIT
SYS0363: FXAM
SYS0365: PUSH BP
SYS0366: MOV BP,SP
SYS0368: LEA SP,[BP-02]
SYS036B: WAIT
SYS036C: FSTSW [BP-02]
SYS036F: WAIT
SYS0370: MOV AH,[BP-01]
SYS0373: SAHF
SYS0374: JB 0385
SYS0376: JNZ 03A6
SYS0378: CMP CL,02
SYS037B: JNZ 0383
SYS037D: WAIT
SYS037E: FSTP ST(0)
SYS0380: WAIT
SYS0381: FLD1
SYS0383: JMP 03A3
SYS0385: JZ 0395
SYS0387: JPO 0395
SYS0389: WAIT
SYS038A: FSTP ST(0)
SYS038C: WAIT
SYS038D: CS:
SYS038E: FLD DWORD PTR [033A]
SYS0392: WAIT
SYS0393: FTST
SYS0395: JMP 03A3
SYS0397: WAIT
SYS0398: FCOMPP ST(1)
SYS039A: WAIT
SYS039B: CS:
SYS039C: FLD DWORD PTR [033A]
SYS03A0: WAIT
SYS03A1: FTST
SYS03A3: JMP 044D
SYS03A6: WAIT
SYS03A7: FABS
SYS03A9: WAIT
SYS03AA: CS:
SYS03AB: FLD TBYTE PTR [0326]
SYS03AF: WAIT
SYS03B0: FXCH ST(1)
SYS03B2: WAIT
SYS03B3: FPREM
SYS03B5: MOV CH,02
SYS03B7: AND CH,AH
SYS03B9: SHR CH,1
SYS03BB: WAIT
SYS03BC: FSTSW [BP-02]
SYS03BF: WAIT
SYS03C0: MOV AH,[BP-01]
SYS03C3: SAHF
SYS03C4: JPE 0397
SYS03C6: MOV AL,03
SYS03C8: AND AL,AH
SYS03CA: SHL AH,1
SYS03CC: SHL AH,1
SYS03CE: RCL AL,1
SYS03D0: ADD AL,FC
SYS03D2: RCL AL,1
SYS03D4: CMP CL,02
SYS03D7: JNZ 03DD
SYS03D9: ADD AL,CL
SYS03DB: MOV CH,00
SYS03DD: AND AL,07
SYS03DF: TEST AL,01
SYS03E1: JZ 03E8
SYS03E3: WAIT
SYS03E4: FSUBP ST(1),ST
SYS03E6: JMP 03EB
SYS03E8: WAIT
SYS03E9: FSTP ST(1)
SYS03EB: WAIT
SYS03EC: FPTAN
SYS03EE: CMP CL,04
SYS03F1: JZ 041C
SYS03F3: TEST AL,03
SYS03F5: JPE 03FA
SYS03F7: WAIT
SYS03F8: FXCH ST(1)
SYS03FA: WAIT
SYS03FB: FLD ST(1)
SYS03FD: WAIT
SYS03FE: FMUL ST,ST(0)
SYS0400: WAIT
SYS0401: FXCH ST(1)
SYS0403: WAIT
SYS0404: FMUL ST,ST(0)
SYS0406: WAIT
SYS0407: FADDP ST(1),ST
SYS0409: WAIT
SYS040A: FSQRT
SYS040C: SHR AL,1
SYS040E: SHR AL,1
SYS0410: XOR AL,CH
SYS0412: JZ 0417
SYS0414: WAIT
SYS0415: FCHS
SYS0417: WAIT
SYS0418: FDIVP ST(1),ST
SYS041A: JMP 044D
SYS041C: MOV AH,AL
SYS041E: SHR AH,1
SYS0420: AND AH,01
SYS0423: XOR AH,CH
SYS0425: JZ 042A
SYS0427: WAIT
SYS0428: FCHS
SYS042A: TEST AL,03
SYS042C: JPE 044A
SYS042E: WAIT
SYS042F: FXCH ST(1)
SYS0431: WAIT
SYS0432: FTST
SYS0434: WAIT
SYS0435: FSTSW [BP-02]
SYS0438: WAIT
SYS0439: TEST BYTE PTR [BP-01],40
SYS043D: JZ 044A
SYS043F: WAIT
SYS0440: FCOMPP ST(1)
SYS0442: WAIT
SYS0443: CS:
SYS0444: FLD DWORD PTR [0354]
SYS0448: JMP 044D
SYS044A: WAIT
SYS044B: FDIVP ST(1),ST
SYS044D: MOV SP,BP
SYS044F: POP BP
SYS0450: RET

Called by SYS:06AC on offset = F2h (see SYS:0693 Handler for INT 3Eh below)

SYS0451: WAIT
SYS0452: FXAM
SYS0454: PUSH BP
SYS0455: MOV BP,SP
SYS0457: LEA SP,[BP-02]
SYS045A: WAIT
SYS045B: FSTSW [BP-02]
SYS045E: WAIT
SYS045F: MOV AH,[BP-01]
SYS0462: SAHF
SYS0463: XCHG CX,AX
SYS0464: JB 046A
SYS0466: JNZ 0484
SYS0468: JMP 04B6
SYS046A: JZ 04B6
SYS046C: JPO 04B6
SYS046E: WAIT
SYS046F: FSTP ST(0)
SYS0471: WAIT
SYS0472: CS:
SYS0473: FLD TBYTE PTR [0330]
SYS0477: JMP 04AE
SYS0479: WAIT
SYS047A: FCOMPP ST(1)
SYS047C: WAIT
SYS047D: CS:
SYS047E: FLD TBYTE PTR [0326]
SYS0482: JMP 04AE
SYS0484: WAIT
SYS0485: FABS
SYS0487: WAIT
SYS0488: FLD1
SYS048A: WAIT
SYS048B: FCOM ST(1)
SYS048D: WAIT
SYS048E: FSTSW [BP-02]
SYS0491: WAIT
SYS0492: MOV AH,[BP-01]
SYS0495: SAHF
SYS0496: JZ 0479
SYS0498: JNB 049D
SYS049A: WAIT
SYS049B: FXCH ST(1)
SYS049D: WAIT
SYS049E: FPATAN
SYS04A0: JNB 04AE
SYS04A2: WAIT
SYS04A3: CS:
SYS04A4: FLD TBYTE PTR [0330]
SYS04A8: WAIT
SYS04A9: FSUBP ST(1),ST
SYS04AB: XOR CH,02
SYS04AE: TEST CH,02
SYS04B1: JZ 04B6
SYS04B3: WAIT
SYS04B4: FCHS
SYS04B6: MOV SP,BP
SYS04B8: POP BP
SYS04B9: RET

Handler called by SYS:06AC on offset = F4h/F6h/F8h (see SYS:0693 Handler for INT 3Eh below)

Called by SYS:06AC on offset = F6h (see SYS:0693 Handler for INT 3Eh below)

SYS04BA: WAIT
SYS04BB: FLD1
SYS04BD: JMP 04C7

Called by SYS:06AC on offset = F8h (see SYS:0693 Handler for INT 3Eh below)

SYS04BF: WAIT
SYS04C0: FLDLG2
SYS04C2: JMP 04C7

Called by SYS:06AC on offset = F4h (see SYS:0693 Handler for INT 3Eh below)

SYS04C4: WAIT
SYS04C5: FLDLN2

Common code used by SYS:04BA, SYS:04BF, SYS:04C4

SYS04C7: WAIT
SYS04C8: FXCH ST(1)
SYS04CA: PUSH BP
SYS04CB: MOV BP,SP
SYS04CD: WAIT
SYS04CE: FXAM
SYS04D0: LEA SP,[BP-0A]
SYS04D3: WAIT
SYS04D4: FSTSW [BP-0A]
SYS04D7: WAIT
SYS04D8: MOV AH,[BP-09]
SYS04DB: SAHF
SYS04DC: JB 04EA
SYS04DE: JZ 04E5
SYS04E0: TEST AH,02
SYS04E3: JZ 04FF
SYS04E5: WAIT
SYS04E6: FSTP ST(0)
SYS04E8: JMP 04F1
SYS04EA: WAIT
SYS04EB: FSTP ST(0)
SYS04ED: JZ 04FA
SYS04EF: JPO 04FA
SYS04F1: WAIT
SYS04F2: FSTP ST(0)
SYS04F4: WAIT
SYS04F5: CS:
SYS04F6: FLD DWORD PTR [033E]
SYS04FA: WAIT
SYS04FB: FTST
SYS04FD: JMP 0523
SYS04FF: WAIT
SYS0500: FLD ST(0)
SYS0502: WAIT
SYS0503: FSTP TBYTE PTR [BP-0A]
SYS0506: WAIT
SYS0507: CMP WORD PTR [BP-02],3FFF
SYS050C: JNZ 0520
SYS050E: CMP WORD PTR [BP-04],8000
SYS0513: JNZ 0520
SYS0515: WAIT
SYS0516: FLD1
SYS0518: WAIT
SYS0519: FSUBP ST(1),ST
SYS051B: WAIT
SYS051C: FYL2XP1
SYS051E: JMP 0523
SYS0520: WAIT
SYS0521: FYL2X
SYS0523: MOV SP,BP
SYS0525: POP BP
SYS0526: RET

Handler called by SYS:06AC on offset = FAh/FCh/FEh (see SYS:0693 Handler for INT 3Eh below)

Called by SYS:06AC on offset = FAh (see SYS:0693 Handler for INT 3Eh below)

SYS0527: WAIT
SYS0528: FLDL2E
SYS052A: MOV CL,01
SYS052C: JMP 0539

Called by SYS:06AC on offset = FCh (see SYS:0693 Handler for INT 3Eh below)

SYS052E: SUB CX,CX
SYS0530: JMP 0539

Called by SYS:06AC on offset = FEh (see SYS:0693 Handler for INT 3Eh below)

SYS0532: WAIT
SYS0533: FLDL2T
SYS0535: MOV CL,01
SYS0537: JMP 0539

Common code used by SYS:0527, SYS:052E, SYS:0532

SYS0539: JCXZ 053E
SYS053B: WAIT
SYS053C: FXCH ST(1)
SYS053E: WAIT
SYS053F: FXAM
SYS0541: PUSH BP
SYS0542: MOV BP,SP
SYS0544: LEA SP,[BP-06]
SYS0547: WAIT
SYS0548: FSTSW [BP-06]
SYS054B: JCXZ 0550
SYS054D: WAIT
SYS054E: FXCH ST(1)
SYS0550: WAIT
SYS0551: MOV AH,[BP-05]
SYS0554: SAHF
SYS0555: XCHG BX,AX
SYS0556: JB 0568
SYS0558: JNZ 0580
SYS055A: WAIT
SYS055B: FSTP ST(0)
SYS055D: JCXZ 0562
SYS055F: WAIT
SYS0560: FSTP ST(0)
SYS0562: WAIT
SYS0563: FLD1
SYS0565: JMP 060F
SYS0568: JCXZ 056D
SYS056A: WAIT
SYS056B: FSTP ST(0)
SYS056D: JZ 057A
SYS056F: JPO 057A
SYS0571: WAIT
SYS0572: FSTP ST(0)
SYS0574: WAIT
SYS0575: CS:
SYS0576: FLD DWORD PTR [0342]
SYS057A: WAIT
SYS057B: FTST
SYS057D: JMP 060F
SYS0580: JCXZ 0585
SYS0582: WAIT
SYS0583: FMULP ST(1),ST
SYS0585: WAIT
SYS0586: FABS
SYS0588: WAIT
SYS0589: CS:
SYS058A: FCOM DWORD PTR [0346]
SYS058E: WAIT
SYS058F: FSTSW [BP-06]
SYS0592: WAIT
SYS0593: TEST BYTE PTR [BP-05],41
SYS0597: JZ 05A4
SYS0599: WAIT
SYS059A: F2XM1
SYS059C: WAIT
SYS059D: FLD1
SYS059F: WAIT
SYS05A0: FADDP ST(1),ST
SYS05A2: JMP 0604
SYS05A4: WAIT
SYS05A5: FLD1
SYS05A7: WAIT
SYS05A8: FLD ST(1)
SYS05AA: WAIT
SYS05AB: FSTCW [BP-06]
SYS05AE: WAIT
SYS05AF: FSCALE
SYS05B1: OR BYTE PTR [BP-05],0F
SYS05B5: WAIT
SYS05B6: FLDCW [BP-06]
SYS05B9: WAIT
SYS05BA: FRNDINT
SYS05BC: AND BYTE PTR [BP-05],F3
SYS05C0: WAIT
SYS05C1: FLDCW [BP-06]
SYS05C4: WAIT
SYS05C5: FIST DWORD PTR [BP-04]
SYS05C8: WAIT
SYS05C9: FXCH ST(1)
SYS05CB: WAIT
SYS05CC: FCHS
SYS05CE: WAIT
SYS05CF: FXCH ST(1)
SYS05D1: WAIT
SYS05D2: FSCALE
SYS05D4: WAIT
SYS05D5: FSTP ST(1)
SYS05D7: WAIT
SYS05D8: FSUBP ST(1),ST
SYS05DA: CMP WORD PTR [BP-02],+00
SYS05DE: JG 0571
SYS05E0: WAIT
SYS05E1: F2XM1
SYS05E3: WAIT
SYS05E4: FLD1
SYS05E6: WAIT
SYS05E7: FADDP ST(1),ST
SYS05E9: SHR WORD PTR [BP-04],1
SYS05EC: JNB 05F7
SYS05EE: WAIT
SYS05EF: CS:
SYS05F0: FLD TBYTE PTR [034A]
SYS05F4: WAIT
SYS05F5: FMULP ST(1),ST
SYS05F7: WAIT
SYS05F8: FILD WORD PTR [BP-04]
SYS05FB: WAIT
SYS05FC: FXCH ST(1)
SYS05FE: WAIT
SYS05FF: FSCALE
SYS0601: WAIT
SYS0602: FSTP ST(1)
SYS0604: TEST BH,02
SYS0607: JZ 060F
SYS0609: WAIT
SYS060A: FLD1
SYS060C: WAIT
SYS060D: FDIVRP ST(1),ST
SYS060F: MOV SP,BP
SYS0611: POP BP
SYS0612: RET

Handler for INT 34h-3Dh

SYS0613: PUSH BP
SYS0614: MOV BP,SP

Use BP to address items on the stack

The stack after SYS:0614

Index Contents
BP Old BP value
BP+02 Return address (OFFSET)
BP+04 Return address (SEGMENT)
BP+06 Flags Register
SYS0616: PUSH AX
SYS0617: PUSH SI
SYS0618: PUSH DS

Save these registers.

SYS0619: TEST BYTE PTR [BP+07],02
SYS061D: JZ 0620
SYS061F: STI

Check if interrupts are enabled (IF, Bit 9 of Flags/Bit 1 of high byte).

SYS0620: LDS SI,[BP+02]

Load return address into DS:SI.

Return address in DS:SI

Index OpCode
SI-02 CDh
SI-01 3xh
SI OpCode Byte 00
SI+01 OpCode Byte 01
... ...
SYS0623: MOV AX,[SI-01]
SYS0626: SUB AL,34
SYS0628: CMP AL,08
SYS062A: JNB 0638

Inspect OpCode and check if it is 3Ch and above. Note: OpCodes at DS:[SI-02] would be CD xx (see above) where xx (at DS:[SI-01]) is the byte being inspected.

SYS062C: SUB SI,+02
SYS062F: ADD WORD PTR [SI],A3CE
SYS0633: MOV [BP+02],SI
SYS0636: JMP 065B

Change OpCode to 9B Dx, where 9B = WAIT and Dx is an x87 OPCODE.

SYS0638: JA 0660

Check if second byte is above 3Ch (OpCode - 34h > 08h).

SYS063A: TEST AH,20
SYS063D: JNZ 066D
SYS063F: SUB SI,+02
SYS0642: MOV [BP+02],SI

Move return address by 2 bytes.

SYS0645: MOV BYTE PTR [SI],9B

Change OpCode in new DS:[SI] to 9Bh = FWAIT.

SYS0648: INC SI
SYS0649: MOV AL,AH
SYS064B: AND AX,07C0
SYS064E: SHR AL,1
SYS0650: SHR AL,1
SYS0652: SHR AL,1
SYS0654: XOR AL,18
SYS0656: ADD AX,D826
SYS0659: MOV [SI],AX
SYS065B: POP DS
SYS065C: POP SI
SYS065D: POP AX
SYS065E: POP BP
SYS065F: IRET

Restore saved registers and return and pop Flags off the stack.

SYS0660: CMP AL,09
SYS0662: JA 066D

Check if OpCode is > 3Dh then exit. Int 3Eh is handled separately in SYS:0693.

SYS0664: SUB SI,+02
SYS0667: MOV WORD PTR [SI],9B90
SYS066B: JMP 0633

Insert OpCodes 909Bh into DS:SI top replace OpCodes CD3xh. OpCode 90h = WAIT, 9Bh = FWAIT.

SYS066D: JMP 065B

Jump to exit routine.

SYS:0693 Handler for INT 3Eh

Lookup table of offsets (called by SYS:06AC below)

OFFSET SI+0693 [SI+0693] TARGET
DC SYS:066F B5 06 SYS:06B5
DE SYS:0671 C9 06 SYS:06C9
E0 SYS:0673 DA 06 SYS:06DA
E2 SYS:0675 DF 06 SYS:06DF
E4 SYS:0677 16 07 SYS:0716
E6 SYS:0679 28 07 SYS:0728
E8 SYS:067B 32 07 SYS:0732
EA SYS:067D 37 07 SYS:0737
EC SYS:067F 58 03 SYS:0358
EE SYS:0681 5C 03 SYS:035C
F0 SYS:0683 60 03 SYS:0360
F2 SYS:0685 51 04 SYS:0451
F4 SYS:0687 C4 04 SYS:04C4
F6 SYS:0689 BA 04 SYS:04BA
F8 SYS:068B BF 04 SYS:04BF
FA SYS:068D 27 05 SYS:0527
FC SYS:068F 2E 05 SYS:052E
FE SYS:0691 32 05 SYS:0532
SYS0693: STI
SYS0694: CLD
SYS0695: PUSH AX
SYS0696: PUSH SI
SYS0697: PUSH ES
SYS0698: PUSH BP

The stack after SYS:0698

Index Contents
BP Old BP value
BP+02 Old ES value
BP+04 Old SI value
BP+06 Old AX value
BP+08 Return address (OFFSET)
BP+0A Return address (SEGMENT)
BP+0C Flags Register
SYS0699: MOV BP,SP
SYS069B: LES SI,[BP+08]

Load return addresss into ES:SI.

SYS069E: ES:
SYS069F: LODSW
SYS06A0: MOV [BP+08],SI

Load Bytes in return address into AX then modify offset part of return address (in stack) to new location (usually, the new location points to a RETF OpCode).

SYS06A3: CMP AL,DC
SYS06A5: JB 06B0

Check whether the value in AL is an offset (>= DCh) or an OpCode. If AL is an OpCode, then return immediately.

SYS06A7: MOV SI,AX
SYS06A9: CBW
SYS06AA: XCHG SI,AX
SYS06AB: CS:
SYS06AC: CALL [SI+0693]

Since AL is an offset, sign extend it into AX by setting AH = FFh using CBW (convert byte to word). SI then becomes a negative offset, and is used a lookup ([SI+0693]) to a WORD at SYS:066F to 0692. Each of the WORD contains an offset address in the System Library.

SYS06B0: POP BP
SYS06B1: POP ES
SYS06B2: POP SI
SYS06B3: POP AX
SYS06B4: IRET

Restore saved registers and return to the code which triggered INT 3Eh.

Called by SYS:06AC on offset = DCh (see SYS:0693 Handler for INT 3Eh above)

SYS06B5: DEC AH
SYS06B7: JL 06C7
SYS06B9: MOV AL,0A
SYS06BB: MUL AH
SYS06BD: XCHG SI,AX
SYS06BE: WAIT
SYS06BF: FSTP TBYTE PTR [BP+SI+0E]
SYS06C2: SUB SI,+0A
SYS06C5: JGE 06BE
SYS06C7: WAIT
SYS06C8: RET

Called by SYS:06AC on offset = DEh (see SYS:0693 Handler for INT 3Eh above)

SYS06C9: SUB SI,SI
SYS06CB: DEC AH
SYS06CD: JL 06D8
SYS06CF: WAIT
SYS06D0: FLD TBYTE PTR [BP+SI+0E]
SYS06D3: ADD SI,+0A
SYS06D6: JMP 06CB
SYS06D8: WAIT
SYS06D9: RET

Called by SYS:06AC on offset = E0h (see SYS:0693 Handler for INT 3Eh above)

SYS06DA: MOV AL,00
SYS06DC: JMP 06E1
SYS06DE: NOP

Called by SYS:06AC on offset = E2h (see SYS:0693 Handler for INT 3Eh above)

SYS06DF: MOV  AL,02

Common code used by SYS:06DA, SYS:06DF

SYS06E1: PUSH BP
SYS06E2: PUSH AX
SYS06E3: MOV BP,SP
SYS06E5: WAIT
SYS06E6: FSTCW [BP+00]
SYS06E9: WAIT
SYS06EA: MOV SI,[BP+00]
SYS06ED: AND BYTE PTR [BP+01],FC
SYS06F1: OR [BP+01],AL
SYS06F4: WAIT
SYS06F5: FLDCW [BP+00]
SYS06F8: WAIT
SYS06F9: FLDZ
SYS06FB: WAIT
SYS06FC: FSUB ST(2),ST
SYS06FE: WAIT
SYS06FF: FADDP ST(1),ST
SYS0701: MOV [BP+00],SI
SYS0704: WAIT
SYS0705: FLDCW [BP+00]
SYS0708: WAIT
SYS0709: FCOMPP ST(1)
SYS070B: WAIT
SYS070C: FSTSW [BP+00]
SYS070F: WAIT
SYS0710: POP AX
SYS0711: POP BP
SYS0712: MOV [BP+0C],AH
SYS0715: RET

Called by SYS:06AC on offset = E4h (see SYS:0693 Handler for INT 3Eh above)

SYS0716: WAIT
SYS0717: FCOMPP ST(1)
SYS0719: MOV AH,[BP+0D]
SYS071C: WAIT
SYS071D: FSTSW [BP+0C]
SYS0720: WAIT
SYS0721: MOV AL,[BP+0D]
SYS0724: MOV [BP+0C],AX
SYS0727: RET

Called by SYS:06AC on offset = E6h (see SYS:0693 Handler for INT 3Eh above)

SYS0728: WAIT
SYS0729: FCOMP    ST(1)
SYS072B: JMP 0719
SYS072D: WAIT
SYS072E: FCOM ST(1)
SYS0730: JMP 0719

Called by SYS:06AC on offset = E8h (see SYS:0693 Handler for INT 3Eh above)

SYS0732: WAIT
SYS0733: FTST
SYS0735: JMP 0719

Called by SYS:06AC on offset = EAh (see SYS:0693 Handler for INT 3Eh above)

SYS0737: WAIT
SYS0738: FXAM
SYS073A: WAIT
SYS073B: FSTSW [BP+06]
SYS073E: WAIT
SYS073F: RET
SYS0740: 0 00 00 00-00 80 FF 7F

FPU Interrupt Handlers Initialization

Initializes various handlers for various FPU-related interrupts.

SYS07D9: PUSH DS
SYS07DA: PUSH CS
SYS07DB: POP DS

Save DS then copy CS into DS.

SYS07DC: MOV AX,2534
SYS07DF: MOV CX,000A
SYS07E2: MOV DX,SI
SYS07E4: INT 21
SYS07E6: INC AX
SYS07E7: LOOP 07E4

Set handlers for interrupts INT 34h-3Dh to SYS:0613 using DOS INT 21h AH=35h set interrupt vector service.

SYS07E9: MOV DX,DI
SYS07EB: INT 21

Set handler for INT 3Eh to SYS:0693.

SYS07ED: MOV DX,081F
SYS07F0: MOV AL,02
SYS07F2: INT 21

Set handler for INT 02h (Non-Maskable Interrupt) to SYS:081F.

SYS07F4: MOV DX,0813
SYS07F7: MOV AL,75
SYS07F9: INT 21

Set handler for INT 75h (FPU Interrupt) to SYS:081F.

SYS07FB: POP DS
SYS07FC: MOV AX,[SaveInt02.Segment]
SYS07FF: CS:
SYS0800: MOV [0884],AX
SYS0803: MOV AX,[SaveInt02.Offset]
SYS0806: CS:
SYS0807: MOV [0886],AX
```nasm

Set **FAR** call in **SYS:0883** to old **INT 02h** handler stored in [**DATA**:[**SaveInt02**]](../DATA.md).

```nasm
SYS080A: FNINIT
SYS080D: FLDCW WORD PTR [FPU.ControlWord]
SYS0812: RETF

Initialize FPU then get the Control Word. Store Control Word at [FPU.ControlWord] then return.

Handler for INT 02h (SYS:0813) and INT 75h (SYS:081F)

SYS0813: PUSH AX

Save AX.

SYS0814: XOR AL,AL
SYS0816: OUT F0,AL

Clear FPU busy latch.

SYS0818: MOV AL,20
SYS081A: OUT A0,AL
SYS081C: OUT 20,AL

Configure 8259 Programmable interrupt controller.

SYS081E: POP AX
SYS081F: PUSH AX
SYS0820: PUSH DS

Save registers.

SYS0821: MOV AX,DATA
SYS0824: MOV DS,AX
SYS0826: CMP BYTE PTR [Test8087],00
SYS082B: JNZ 0834

Check if an FPU is present (Test8087).

SYS082D: FNSTENV [FPUEnvironment]
SYS0832: JMP 0839

Get FPU environment. FNSTENV does not check nor handle any pending unmasked floating-point exceptions.

SYS0834: FSTENV [FPUEnvironment]
SYS0838: WAIT
SYS0839: MOV AL,[FPUEnvironment.ControlWord]
SYS083C: NOT AL
SYS083E: AND AL,[FPUEnvironment.StatusWord]
SYS0842: JNS 0881

Check ControlWord and StatusWord exception masks in FPUEnvironment. If none are set, then proceed to original INT 02h interrupt handler (FAR call in SYS:0883).

SYS0844: STI
SYS0845: TEST AL,3D
SYS0847: JNZ 084F
SYS0849: CALL 08AF
SYS084C: POP DS
SYS084D: POP AX
SYS084E: IRET
SYS084F: FNINIT
SYS0852: FLDCW   WORD PTR [FPU.ControlWord]
SYS0857: CALL 0888
SYS085A: POP  CX
SYS085B: POP CX
SYS085C: POP CX
SYS085D: POP BX
SYS085E: CMP BYTE PTR [Test8087],00
SYS0863: JZ 087E
SYS0865: MOV DX,[FPUEnvironment.IP]
SYS0869: MOV CL,04
SYS086B: SHR DX,CL
SYS086D: MOV BX,[FPUEnvironment.OpCode]
SYS0871: AND BX,F000
SYS0875: ADD BX,DX
SYS0877: MOV CX,[FPUEnvironment.IP]
SYS087B: AND CX,+0F
SYS087E: JMP 011A
SYS0881: POP DS
SYS0882: POP AX

Restore modified registers.

SYS0883: JMP 0000:0000

Jump to original INT 02h interrupt handler. Initialliy set to a place holder value (0000:0000). The FAR address is modified in SYS:0800 and SYS:0807.

SYS0888: TEST AL,01
SYS088A: JNZ 089E
SYS088C: MOV AH,C8
SYS088E: TEST AL,04
SYS0890: JNZ 08A0
SYS0892: MOV AH,CD
SYS0894: TEST AL,08
SYS0896: JNZ 08A0
SYS0898: MOV AH,CE
SYS089A: TEST AL,10
SYS089C: JNZ 08A0
SYS089E: MOV AH,CF
SYS08A0: MOV AL,AH
SYS08A2: XOR AH,AH
SYS08A4: RET
SYS08A5: PUSH DS
SYS08A6: LDS BX,[FPUEnvironment.DataPointer]
SYS08AA: WAIT
SYS08AB: NOP
SYS08AC: NOP
SYS08AD: POP DS
SYS08AE: RET
SYS08AF: PUSH BX
SYS08B0: MOV AX,[FPUEnvironment.OpCode]
SYS08B3: MOV BL,AL
SYS08B5: AND BL,C0
SYS08B8: CMP BL,C0
SYS08BB: JZ 08C1
SYS08BD: AND AL,38
SYS08BF: OR AL,07
SYS08C1: XCHG AL,AH
SYS08C3: AND AL,07
SYS08C5: OR AL,D8
SYS08C7: CS:
SYS08C8: MOV [08AB],AX
SYS08CB: CMP AX,07D9
SYS08CE: JZ 0920
SYS08D0: CMP AX,07DD
SYS08D3: JZ 0920
SYS08D5: CMP AX,2FDB
SYS08D8: JZ 0920
SYS08DA: CMP AX,17D8
SYS08DD: JZ 0923
SYS08DF: CMP AX,17DC
SYS08E2: JZ 0923
SYS08E4: CMP AX,1FD8
SYS08E7: JZ 0923
SYS08E9: CMP AX,1FDC
SYS08EC: JZ 0923
SYS08EE: CMP AX,37D8
SYS08F1: JZ 0900
SYS08F3: CMP AX,37DC
SYS08F6: JZ 0900
SYS08F8: WAIT
SYS08F9: FCLEX
SYS08FB: CALL 08A5
SYS08FE: JMP 0913
SYS0900: CS:
SYS0901: SUB WORD PTR [08AB],2FFF
SYS0907: CALL 08A5
SYS090A: CALL 0932
SYS090D: WAIT
SYS090E: FCLEX
SYS0910: WAIT
SYS0911: FDIVP ST(1),ST
SYS0913: WAIT
SYS0914: FSTSW [FPU.StatusWord]
SYS0918: WAIT
SYS0919: MOV AL,[FPU.StatusWord]
SYS091C: OR [FPUEnvironment.StatusSword],AL
SYS0920: CALL 0932
SYS0923: WAIT
SYS0924: FCLEX
SYS0926: AND BYTE PTR [FPUEnvironment.StatusSword],FD
SYS092B: WAIT
SYS092C: FLDENV [FPUEnvironment]
SYS0930: POP BX
SYS0931: RET
SYS0932: WAIT
SYS0933: FXAM
SYS0935: WAIT
SYS0936: FSTSW   [FPU.StatusWord]
SYS093A: WAIT
SYS093B: MOV AX,[FPU.StatusWord]
SYS093E: TEST AX,4500
SYS0941: JZ 0954
SYS0943: TEST AX,4000
SYS0946: JZ 0963
SYS0948: TEST AX,0400
SYS094B: JZ 0963
SYS094D: WAIT
SYS094E: FSTP ST(0)
SYS0950: WAIT
SYS0951: FLDZ
SYS0953: RET
SYS0954: WAIT
SYS0955: CS:
SYS0956: FLD TBYTE PTR [0742]
SYS095A: WAIT
SYS095B: FXCH ST(1)
SYS095D: WAIT
SYS095E: FPREM
SYS0960: WAIT
SYS0961: FSTP ST(1)
SYS0963: RET
SYS0964: OR AL,AL
SYS0966: JZ 098A
SYS0968: XOR CL,CL
SYS096A: MOV CH,AH
SYS096C: MOV AH,DH
SYS096E: AND AH,80
SYS0971: ADD AX,3F7E
SYS0974: OR DH,80
SYS0977: PUSH AX
SYS0978: PUSH DX
SYS0979: PUSH BX
SYS097A: PUSH CX
SYS097B: XOR CX,CX
SYS097D: PUSH CX
SYS097E: MOV BX,SP
SYS0980: FLD  SS:TBYTE PTR [BX]
SYS0984: FWAIT
SYS0986: ADD SP,+0A
SYS0989: RETF
SYS098A: FLDZ
SYS098D: RETF

See also: Test8087 (Variable), Identify 8087/80287/80387 FPU, 8087/80287/80387 Control Word, 8087/80287/80387 Status Word, 8087/80287/80387 x87 FPU Evironment, 8087/80287/80387 Temporary data, or go back