📄 fp.asm
字号:
jae BadSEFPA
test fpacc.Sign, 80h
jz StoreSEFPA
or ah, 80h
StoreSEFPA: mov es:[di]+8, ax
mov ax, fpacc.Mantissa [0]
mov es:[di], ax
mov ax, fpacc.Mantissa [2]
mov es:[di] + 2, ax
mov ax, fpacc.Mantissa [4]
mov es:[di] + 4, ax
mov ax, fpacc.Mantissa [6]
mov es:[di] + 6, ax
clc
jmp SEFPADone
;
BadSEFPA: stc
SEFPADone: pop fpacc.Exponent
pop fpacc.Mantissa[6]
pop fpacc.Mantissa[4]
pop fpacc.Mantissa[2]
pop fpacc.Mantissa[0]
pop ax
pop ds
ret
assume ds:nothing
sl_SEFPA endp
;
;
;
; sl_LSFPO- Loads a single precision (32-bit) IEEE format number into
; the floating point operand. ES:DI points at the # to
; load into FPOP.
;
public sl_LSFPO
sl_LSFPO proc far
push ax
push bx
mov ax, es:[di]
mov word ptr StdGrp:fpop.mantissa[5], ax
mov ax, es:2[di]
mov bx, ax
shl ax, 1
mov al, ah
mov ah, 0
add ax, 32767-127 ;Adjust exponent bias.
mov word ptr StdGrp:fpop.exponent, ax
mov StdGrp:fpop.sign, bh ;Save sign away.
mov al, es:2[di]
and al, 7fh ;Strip out L.O. exp bit.
or al, 80h ;Add in implied bit.
mov byte ptr StdGrp:fpop.mantissa[7], al
xor ax, ax
mov word ptr StdGrp:fpop.mantissa, ax
mov word ptr StdGrp:fpop.mantissa[2], ax
mov byte ptr StdGrp:fpop.mantissa[4], al
pop bx
pop ax
ret
sl_LSFPO endp
;
;
;
;
;
; sl_LDFPO- Loads the double precision (64-bit) IEEE format number pointed
; at by ES:DI into FPOP.
;
public sl_LDFPO
sl_LDFPO proc far
push ax
push bx
push cx
mov ax, es:6[di]
mov StdGrp:fpop.sign, ah ;Save sign bit.
mov cl, 4
shr ax, cl ;Align exponent field.
and ah, 111b ;Strip the sign bit.
add ax, 32767-1023 ;Adjust bias
mov word ptr StdGrp:fpop.exponent, ax
;
; Get the mantissa bits and left justify them in the FPOP.
;
mov ax, es:5[di]
and ax, 0fffh ;Strip exponent bits.
or ah, 10h ;Add in implied bit.
mov cl, 3
shl ax, cl
mov bx, es:3[di]
rol bx, cl
mov ch, bl
and ch, 7
or al, ch
mov word ptr StdGrp:fpop.mantissa[6], ax
;
and bl, 0f8h
mov ax, es:1[di]
rol ax, cl
mov ch, al
and ch, 7
or bl, ch
mov word ptr StdGrp:fpop.mantissa[4], bx
;
and al, 0f8h
mov bh, es:[di]
rol bh, cl
mov ch, bh
and ch, 7
or al, ch
mov word ptr StdGrp:fpop.mantissa[2], ax
and bh, 0f8h
mov bl, 0
mov word ptr StdGrp:fpop.Mantissa[0], bx
;
pop cx
pop bx
pop ax
ret
sl_LDFPO endp
;
;
;
;
;
; sl_LEFPO- Loads an extended precision (80-bit) IEEE format number
; into the floating point operand. ES:DI points at the
; number to load into FPACC.
;
public sl_LEFPO
sl_LEFPO proc far
push ax
mov ax, es:8[di]
mov StdGrp:fpop.Sign, ah
and ah, 7fh
add ax, 4000h
mov StdGrp:fpop.Exponent, ax
mov ax, es:[di]
mov StdGrp:fpop.Mantissa, ax
mov ax, es:2[di]
mov StdGrp:fpop.Mantissa[2], ax
mov ax, es:4[di]
mov StdGrp:fpop.Mantissa[4], ax
mov ax, es:6[di]
mov StdGrp:fpop.Mantissa[6], ax
pop ax
ret
sl_LEFPO endp
;
;
;
;
; sl_LEFPOL- Loads an extended precision (80-bit) IEEE format number
; into the floating point operand. The number to load
; follows the call instruction in the code stream.
;
public sl_LEFPOL
sl_LEFPOL proc far
push bp
mov bp, sp
push es
push di
push ax
les di, 2[bp]
;
mov ax, es:8[di]
mov StdGrp:fpop.Sign, ah
and ah, 7fh
add ax, 4000h
mov StdGrp:fpop.Exponent, ax
mov ax, es:[di]
mov StdGrp:fpop.Mantissa, ax
mov ax, es:2[di]
mov StdGrp:fpop.Mantissa[2], ax
mov ax, es:4[di]
mov StdGrp:fpop.Mantissa[4], ax
mov ax, es:6[di]
mov StdGrp:fpop.Mantissa[6], ax
;
add word ptr 2[bp], 10 ;Skip rtn adrs past #.
;
pop ax
pop di
pop es
pop bp
ret
sl_LEFPOL endp
;
;
;
;
;
;
;
;--------------------------------------------------------------------------
; Integer <=> FP Conversions
;--------------------------------------------------------------------------
;
;
;
; ITOF- Converts 16-bit signed value in AX to a floating point value
; in FPACC.
;
public sl_itof
sl_itof proc far
assume ds:stdgrp
push ds
push ax
push cx
mov cx, StdGrp
mov ds, cx
;
mov cx, 800Fh ;Magic exponent value (65536).
;
; Set the sign of the result:
;
mov fpacc.Sign, 0 ;Assume a positive value.
or ax, ax ;Special case for zero!
jz SetFPACC0
jns DoUTOF ;Take care of neg values.
mov fpacc.sign, 80h ;This guy is negative!
neg ax ;Work with abs(AX).
jmp DoUTOF
sl_ITOF endp
;
;
; UTOF- Like ITOF above except this guy works for unsigned 16-bit
; integer values.
;
public sl_utof
sl_UTOF proc far
push ds
push ax
push cx
;
;
mov cx, StdGrp
mov ds, cx
mov cx, 800Fh ;Magic exponent value (65536).
or ax, ax
jz SetFPACC0
mov fpacc.Sign, 0
;
sl_UTOF endp
;
;
; Okay, convert the number to a floating point value:
; Remember, we need to end up with a normalized number (one where the H.O.
; bit of the mantissa contains a one). The largest possible value (65535 or
; 0FFFFh) is equal to 800E FFFF 0000 0000 0000. All other values have an
; exponent less than or equal to 800Eh. If the H.O. bit of the value is
; not one, we must shift it to the left and dec the exp by 1. E.g., if AX
; contains 1, then we will need to shift it 15 times to normalize the value,
; decrementing the exponent each time produces 7fffh which is the proper
; exponent for "1".
;
; Note: this is not a proc! Making it a proc makes it incompatible with
; one or more different assemblers (TASM, OPTASM, MASM6).
; Besides, this has to be a near label with a far return!
;
DoUTOF:
UTOFWhlPos: dec cx
shl ax, 1
jnc UTOFWhlPos
rcr ax, 1 ;Put bit back.
mov fpacc.Exponent, cx ;Save exponent value.
mov fpacc.Mantissa [6], ax ;Save Mantissa value.
xor ax, ax
mov fpacc.Mantissa [4], ax ;Zero out the rest of the
mov fpacc.Mantissa [2], ax ; mantissa.
mov fpacc.Mantissa [0], ax
jmp UTOFDone
;
; Special case for zero, must zero all bytes in FPACC. Note that AX already
; contains zero.
;
SetFPACC0: mov fpacc.Exponent, ax
mov fpacc.Mantissa [6], ax
mov fpacc.Mantissa [4], ax
mov fpacc.Mantissa [2], ax
mov fpacc.Mantissa [0], ax
mov fpacc.Sign, al
;
UTOFDone: pop cx
pop ax
pop ds
retf
;
;
;
;
;
;
; LTOF- Converts 32-bit signed value in DX:AX to a floating point
; value in FPACC.
;
public sl_ltof
sl_ltof proc far
assume ds:stdgrp
push ds
push ax
push cx
push dx
mov cx, StdGrp
mov ds, cx
;
; Set the sign of the result:
;
mov fpacc.Sign, 0 ;Assumed a positive value.
mov cx, dx
or cx, ax
jz SetUL0
or dx, dx ;Special case for zero!
jns DoULTOF ;Take care of neg values.
mov fpacc.sign, 80h ;This guy is negative!
neg dx ;Do a 32-bit NEG operation
neg ax ; (yes, this really does
sbb dx, 0 ; work!).
jmp DoULTOF
sl_LTOF endp
;
;
; ULTOF- Like LTOF above except this guy works for unsigned 32-bit
; integer values.
;
public sl_ultof
sl_ULTOF proc far
push ds
push ax
push cx
push dx
;
mov cx, StdGrp
mov ds, cx
;
mov cx, dx
or cx, ax
jz SetUL0
mov fpacc.Sign, 0
;
sl_ULTOF endp
;
;
;
DoULTOF:
mov cx, 801Fh ;Magic exponent value (65536).
ULTOFWhlPos: dec cx
shl ax, 1
rcl dx, 1
jnc ULTOFWhlPos
rcr dx, 1 ;Put bit back.
rcr ax, 1
mov fpacc.Exponent, cx ;Save exponent value.
mov fpacc.Mantissa [6], dx ;Save Mantissa value.
mov fpacc.Mantissa [4], ax
xor ax, ax ;Zero out the rest of the
mov fpacc.Mantissa [2], ax ; mantissa.
mov fpacc.Mantissa [0], ax
jmp ULTOFDone
;
; Special case for zero, must zero all bytes in FPACC. Note that AX already
; contains zero.
;
SetUL0: mov fpacc.Exponent, ax
mov fpacc.Mantissa [6], ax
mov fpacc.Mantissa [4], ax
mov fpacc.Mantissa [2], ax
mov fpacc.Mantissa [0], ax
mov fpacc.Sign, al
;
ULTOFDone: pop dx
pop cx
pop ax
pop ds
retf
;
;
;
;
; FTOI- Converts the floating point value in FPACC to a signed 16-bit
; integer and returns this integer in AX.
; Returns carry set if the number is too big to fit into AX.
;
public sl_FTOI
sl_FTOI proc far
assume ds:stdgrp
push ds
push cx
mov cx, StdGrp
mov ds, cx
;
mov cx, fpacc.Exponent
cmp cx, 800eh
jb FTOIok
;
; Handle special case of -32768:
;
call DoFToU
cmp ax, 8000h
je FtoiOk2
stc
jmp TooBig
;
FTOIok: call DoFTOU
FtoiOk2: cmp fpacc.Sign, 0
jns FTOIJustRight
neg ax
FTOIJustRight: clc
TooBig: pop cx
pop ds
ret
sl_FTOI endp
;
;
;
;
; FTOU- Like FTOI above, except this guy converts a floating point value
; to an unsigned integer in AX.
; Returns carry set if out of range (including negative numbers).
;
public sl_FTOU
sl_FTOU proc far
assume ds:stdgrp
push ds
push cx
mov cx, StdGrp
mov ds, cx
;
mov cx, fpacc.Exponent
cmp cx, 800fh
jb FTOUok
BadU: stc
jmp UTooBig
;
FTOUok: call DoFTOU
cmp fpacc.Sign, 0
js BadU
;
FTOUJustRight: clc
UTooBig: pop cx
pop ds
ret
sl_FTOU endp
;
;
; DoFTOU- This code does the actual conversion!
;
DoFTOU proc near
mov ax, fpacc.Mantissa [6]
cmp cx, 7fffh
jb SetFTOU0
sub cx, 800eh
neg cx
shr ax, cl
ret
;
SetFTOU0: xor ax, ax
ret
DoFTOU endp
;
;
;
;
;
; FTOL- Converts the floating point value in FPACC to a signed 32-bit
; integer and returns this integer in DX:AX.
; Returns carry set if the number is too big to fit into DX:AX.
;
public sl_FTOL
sl_FTOL proc far
assume ds:StdGrp
push ds
push cx
mov cx, StdGrp
mov ds, cx
;
mov cx, fpacc.Exponent
cmp cx, 801eh
jb FTOLok
stc
jmp LTooBig
;
FTOLok: call DoFTOUL
cmp fpacc.Sign, 0
jns FTOLJustRight
neg dx ;32-bit negate operation.
neg ax
sbb dx, 0
FTOLJustRight: clc
LTooBig: pop cx
pop ds
ret
sl_FTOL endp
;
;
;
;
; FTOUL-Like FTOL above, except this guy converts a floating point value
; to a 32-bit unsigned integer in DX:AX.
; Returns carry set if out of range (including negative numbers).
;
public sl_FTOUL
sl_FTOUL proc far
assume ds:StdGrp
push ds
push cx
mov cx, StdGrp
mov ds, cx
;
mov cx, fpacc.Exponent
cmp cx, 801fh
jb FTOULok
BadUL: stc
jmp ULTooBig
;
FTOULok: call DoFTOUL
cmp fpacc.Sign, 0
js BadUL
;
clc ;If the # is okay.
ULTooBig: pop cx
pop ds
ret
sl_FTOUL endp
;
;
; DoFTOUL- This code does the actual conversion!
;
DoFTOUL proc near
mov dx, fpacc.Mantissa [6]
mov ax, fpacc.Mantissa [4]
cmp cx, 7fffh
jb SetFTOUL0
sub cx, 801eh
neg cx
jcxz SetFTOULDone
FTOULLp: shr dx, 1
rcr ax, 1
loop FTOULLp
SetFToULDone: ret
;
SetFTOUL0: xor ax, ax
xor dx, dx
ret
DoFTOUL endp
;
;
;
;
;
;
;
;
;
;
;
;
;
;---------------------------------------------------------------------------
; Floating Point Addition & Subtraction
;---------------------------------------------------------------------------
;
;
;
;
; FADD- Adds FOP to FACC
; FSUB- Subtracts FOP from FACC
; These routines destroy the value in FPOP!
;
public sl_fsub
public sl_fadd
;
assume ds:nothing
sl_fsub proc far
xor StdGrp:fpop.sign, 80h
sl_fsub endp
;
assume ds:StdGrp
sl_fadd proc far
push ds
push ax
push bx
push cx
push dx
push si
; Use the current CS as the data segment to get direct access to
; the floating point accumulator and operands.
mov ax, StdGrp
mov ds, ax
; Kludge Alert! Check to see if either operand is zero. This code doesn't
; deal with zero very gracefully, so we have to specially check for zero
; here.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -