fpuatofl.asm
来自「这是一个数字图像处理的matlab仿真程序」· 汇编 代码 · 共 361 行
ASM
361 行
; #########################################################################
;
; FpuAtoFL
;
;##########################################################################
; -----------------------------------------------------------------------
; This procedure was written by Raymond Filiatreault, December 2002
; Modified January, 2004, to eliminate .data section and remove some
; redundant code.
; Modified March 2004 to avoid any potential data loss from the FPU
; Revised January 2005 to free the FPU st7 register if necessary.
;
; This FpuAtoFL function converts a decimal number from a zero terminated
; alphanumeric string format (Src) to an 80-bit REAL number and returns
; the result as an 80-bit REAL number at the specified destination (the
; FPU itself or a memory location), unless an invalid operation is
; reported by the FPU or the definition of the parameters (with uID) is
; invalid.
;
; The source can be a string in regular numeric format or in scientific
; notation. The number of digits (excluding all leading 0's and trailing
; decimal 0's) must not exceed 18. If in scientific format, the exponent
; must be within +/-4931
;
; The source is checked for validity. The procedure returns an error if
; a character other than those acceptable is detected prior to the
; terminating zero or the above limits are exceeded.
;
; This procedure is based on converting the digits into a specific packed
; decimal format which can be used by the FPU and then adjusted for an
; exponent of 10.
;
; Only EAX is used to return error or success. All other CPU registers
; are preserved.
;
; IF the FPU is specified as the destination for the result,
; the st7 data register will become the st0 data register where the
; result will be returned (any valid data in that register would
; have been trashed).
;
; -----------------------------------------------------------------------
.386
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive
include Fpu.inc
.code
; #########################################################################
FpuAtoFL proc public lpSrc:DWORD, lpDest:DWORD, uID:DWORD
LOCAL content[108] :BYTE
LOCAL tempst :TBYTE
LOCAL bcdstr :TBYTE
fsave content
push ebx
push ecx
push edx
push esi
push edi
xor eax,eax
xor ebx,ebx
xor edx,edx
lea edi,bcdstr
stosd
stosd
mov [edi],ax
mov esi,lpSrc
mov ecx,19
@@:
lodsb
cmp al," "
jz @B ;eliminate leading spaces
or al,al ;is string empty?
jnz @F
atoflerr:
frstor content
atoflerr1:
xor eax,eax
pop edi
pop esi
pop edx
pop ecx
pop ebx
ret
;----------------------
;check for leading sign
;----------------------
@@:
cmp al,"+"
jz @F
cmp al,"-"
jnz integer
mov ah,80h
@@:
mov [edi+1],ah ;put sign byte in bcd string
xor eax,eax
lodsb
;------------------------------------
;convert the digits to packed decimal
;------------------------------------
integer:
cmp al,"."
jnz @F
test bh,1
jnz atoflerr ;only one decimal point allowed
or bh,1 ;use BH as the decimal point flag
lodsb
@@:
cmp al,"e"
jnz @F
.if cl == 19
test bh,4
jz atoflerr ;error if no digit before e
.endif
jmp scient
@@:
cmp al,"E"
jnz @F
.if cl == 19
test bh,4
jz atoflerr ;error if no digit before e
.endif
jmp scient
@@:
or al,al
jnz @F
.if cl == 19
test bh,4
jz atoflerr ;error if no digit before terminating 0
.endif
jmp laststep1
@@:
sub al,"0"
jc atoflerr ;unacceptable character
cmp al,9
ja atoflerr ;unacceptable character
or bh,4 ;at least 1 numerical character
test bh,1
jz @F
add bl,1 ;BL holds number of decimal digits
jc atoflerr ;more than 255 decimal digits
@@:
.if al == 0
test bh,2
jnz @F
lodsb
jmp integer
.endif
@@:
or bh,2 ;at least 1 non-zero numerical character
dec ecx
jnz @F
test bh,1 ;check if decimal point
jz atoflerr ;error if more than 18 integer digits in number
.if al == 0 ;if trailing decimal 0
inc ecx
dec bl
lodsb
jmp integer
.endif
jmp atoflerr
@@:
mov ah,al
integer1:
lodsb
cmp al,"."
jnz @F
test bh,1
jnz atoflerr ;only one decimal point allowed
or bh,1 ;use BH bit0 as the decimal point flag
lodsb
@@:
cmp al,"e"
jnz @F
mov al,0
rol al,4
ror ax,4
mov [edi],al
jmp scient
@@:
cmp al,"E"
jnz @F
mov al,0
rol al,4
ror ax,4
mov [edi],al
jmp scient
@@:
or al,al
jnz @F
rol al,4
ror ax,4
mov [edi],al
jmp laststep1
@@:
sub al,"0"
jc atoflerr ;unacceptable character
cmp al,9
ja atoflerr ;unacceptable character
test bh,1
jz @F
inc bl ;processing decimal digits
@@:
dec ecx
jnz @F
test bh,1 ;check if decimal point
jz atoflerr ;error if more than 18 integer digits in number
.if al == 0 ;if trailing decimal 0
inc ecx
dec bl
jmp integer1
.endif
jmp atoflerr
@@:
rol al,4
ror ax,4
mov [edi],al
dec edi
lodsb
jmp integer
laststep1:
cmp cl,19
jnz laststep
fldz
jmp laststep2
laststep:
fbld bcdstr
dec cl
add bl,cl
movzx eax,bl
sub edx,eax
call XexpY
fmul
fstsw ax ;retrieve exception flags from FPU
fwait
shr al,1 ;test for invalid operation
jc atoflerr ;clean-up and return error
laststep2:
test uID,DEST_FPU ;check where result should be stored
jnz @F ;destination is the FPU
mov eax,lpDest
fstp tbyte ptr[eax] ;store result at specified address
jmp restore
@@:
fstp tempst ;store result temporarily
restore:
frstor content ;restore all previous FPU registers
jz @F
ffree st(7) ;free it if not already empty
fld tempst
@@:
or al,1 ;to insure EAX!=0
@@:
pop edi
pop esi
pop edx
pop ecx
pop ebx
ret
scient:
cmp cl,19
jnz @F
fldz
jmp laststep2
@@:
xor eax,eax
lodsb
cmp al,"+"
jz @F
cmp al,"-"
jnz scient1
stc
rcr eax,1 ;keep sign of exponent in most significant bit of EAX
@@:
lodsb ;get next digit after sign
scient1:
push eax
and eax,0ffh
jnz @F ;continue if 1st byte of exponent is not terminating 0
scienterr:
pop eax
jmp atoflerr ;no exponent
@@:
sub al,30h
jc scienterr ;unacceptable character
cmp al,9
ja scienterr ;unacceptable character
imul edx,10
add edx,eax
cmp edx,4931
ja scienterr ;exponent too large
lodsb
or al,al
jnz @B
pop eax ;retrieve exponent sign flag
rcl eax,1 ;is most significant bit set?
jnc @F
neg edx
@@:
jmp laststep
FpuAtoFL endp
; #########################################################################
;put 10 to the proper exponent (value in EDX) on the FPU
XexpY:
push edx
fild dword ptr[esp] ;load the exponent
fldl2t ;load log2(10)
fmul ;->log2(10)*exponent
pop edx
;at this point, only the log base 2 of the 10^exponent is on the FPU
;the FPU can compute the antilog only with the mantissa
;the characteristic of the logarithm must thus be removed
fld st(0) ;copy the logarithm
frndint ;keep only the characteristic
fsub st(1),st ;keeps only the mantissa
fxch ;get the mantissa on top
f2xm1 ;->2^(mantissa)-1
fld1
fadd ;add 1 back
;the number must now be readjusted for the characteristic of the logarithm
fscale ;scale it with the characteristic
;the characteristic is still on the FPU and must be removed
fstp st(1) ;clean-up the register
ret
;##########################################################################
end
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?