Mathe: Integer8

WRITEME

Mathematische Basis-Operationen für 8-Byte-Integer + - * /

FIXME Auch Signed und arithmetisch über Cary ermöglichen
FIXME Mehrere Varianten ermöglichen, eine reine Integer-Mathe eine über FPU und weitere über MMX und 64Bit Prozessoren.

FIXME Bei allen Berechnungen stimmend Zero-Flags nicht. Diese müßten extra konstruiert werden wenn sie benötigt werden.

Var1&1 Bedeutet erster und Zweiter Teil der Variable, die als Doppelwort im Speicher abgelegt wird.
Var1&2
oder
Var1.(1) Als Position der Variable in einem Type

EDX:EAX Schreibweise um anzuzeigen daß das Resultat aus 2 Registern gebildet wird
EDX&EAX

+% Bedeuten in der Operation wird das Cary-Flag Berücksichtigt

Type welcher die Informationen für ein Integer8 trägt. Dies ist Vergleichbar mir dem Wert AL und AH die beide zusammen AX ergeben.
Type Integer8

  BigInt1 AS Long    ' Ist LowTeil,  Vergleichbar mit AL
  BigInt2 AS Long    ' Ist HighTeil, Vergleichbar mit AH

End Type

Integer8 struc

  Big1 DD ?
  Big2 DD ?

Integer8 ends

Basis-Operationen Float

+ - * /

;===  +, Addition
;===  Add = Val1 + Val2
 MOV       EAX, [ESP+4]        ; EAX = Var1&1
 MOV       EDX, [ESP+8]        ; EDX = Var1&2
 
 ADD       EAX, [ESP+12]       ; EAX = EAX + Var2&1
 ADC       EDX, [ESP+16]       ; EDX = EDX +% Var2&1
;@CheckOverflow
 INTO
;===  -, Subtraktion
;===  Sub = Val1 - Val2
 MOV       EAX, [ESP+4]        ; EAX = Var1&1
 MOV       EDX, [ESP+8]        ; EDX = Var1&2
 
 SUB       EAX, [ESP+12]       ; EAX = EAX - Var2&1
 SBB       EDX, [ESP+16]       ; EDX = EDX -% Var2&1
;@CheckOverflow
 INTO
;===  *, Multiplikation
;===  Mul = Val1 * Val2
 MOV       EBX, Val2           ; EBX = Val2
 MOV       EAX, Val1           ; EAX = Val2
 
 MUL       EAX, EBX            ; EAX = EAX * EBX
;@CheckOverflow
;===  /, Division (Über Float mit Rundung)
;===  Div = Val1 / Val2
 MOV       EBX, Val2           ; EBX = Val2
 MOV       EAX, Val1           ; EAX = Val2
 
 DIV       EAX, EBX            ; EAX = EAX / EBX
 ;                             ; EDX = EAX Mod EBX
;@CheckOverflow
;===  DIV, Division (Ganzzahlig ohne Rundung)
;===  Div = Val1 DIV Val2
 MOV       EBX, Val2           ; EBX = Val2
 MOV       EAX, Val1           ; EAX = Val2
 
 DIV       EAX, EBX            ; EAX = EAX / EBX
 ;                             ; EDX = EAX Mod EBX
;@CheckOverflow
;===  MOD, Modulo Divisions Rest
;===  Mod = Val1 MOD Val2
 MOV       EBX, Val2           ; EBX = Val2
 MOV       EAX, Val1           ; EAX = Val2
 
 DIV       EAX, EBX            ; EAX = EAX / EBX
 ;                             ; EDX = EAX Mod EBX
 
 MOV       EAX, EDX            ; EAX = Val2
;@CheckOverflow

WRITEME

 
.386
.model small,pascal
 
Integer8 struc
Big1 DD ?
Big2 DD ?
Integer8 ends
 
 
 
.code
 
;-----------------------------------------------------------------------------
;void pascal quadinc(Integer8* z, Integer8 x)
;compute z=z+x
 
QUADINC proc z:ptr, x:qword
 
 MOV EAX,(x).Big1
 MOV EDX,(x).Big2
 MOV EBX,z
 
 ADD [EBX].Big1,EAX
 ADC [EBX].Big2,EDX
 
;-----------------------------------------------------------------------------
;void pascal quadinca(Integer8* z, Integer8* x)
;compute z=z+x
 
public QUADINCA
QUADINCA proc z:ptr, x:ptr
 
 MOV EBX,x
 MOV EAX,[EBX].Big1
 MOV EDX,[EBX].Big2
 MOV EBX,z
 
 ADD [EBX].Big1,EAX
 ADC [EBX].Big2,EDX
 
;-----------------------------------------------------------------------------
;void pascal quaddec(Integer8* z, Integer8 x)
;compute z=z-x
 
public QUADDEC
QUADDEC proc z:ptr, x:qword
 
 MOV EAX,(x).Big1
 MOV EDX,(x).Big2
 MOV EBX,z
 
 SUB [EBX].Big1,EAX
 SBB [EBX].Big2,EDX
 
;-----------------------------------------------------------------------------
;void pascal quaddeca(Integer8* z, Integer8* x)
;compute z=z-x
 
public QUADDECA
QUADDECA proc z:ptr, x:ptr
 
 MOV EBX,x
 MOV EAX,[EBX].Big1
 MOV EDX,[EBX].Big2
 MOV EBX,z
 
 SUB [EBX].Big1,EAX
 SBB [EBX].Big2,EDX
 
;-----------------------------------------------------------------------------
;void pascal quadadd(Integer8* z, Integer8 x, Integer8 y)
;compute z=x+y
 
public QUADADD
QUADADD proc z:ptr, x:qword, y:qword
 
 MOV EAX,(x).Big1
 MOV EDX,(x).Big2
 
 ADD EAX,(y).Big1
 ADC EDX,(y).Big2
 
 MOV EBX,z
 MOV [EBX].Big1,EAX
 MOV [EBX].Big2,EDX
 
;-----------------------------------------------------------------------------
;void pascal quadadda(Integer8* z, Integer8* x, Integer8* y)
;compute z=x+y
 
public QUADADDA
QUADADDA proc z:ptr, x:ptr, y:ptr
 
 MOV EBX,x
 MOV EAX,[EBX].Big1
 MOV EDX,[EBX].Big2
 MOV EBX,y
 
 ADD EAX,[EBX].Big1
 ADC EDX,[EBX].Big2
 
 MOV EBX,z
 MOV [EBX].Big1,EAX
 MOV [EBX].Big2,EDX
 
;-----------------------------------------------------------------------------
;void pascal quadsub(Integer8* z, Integer8 x, Integer8 y)
;compute z=x-y
 
public QUADSUB
QUADSUB proc z:ptr, x:qword, y:qword
 
 MOV EAX,(x).Big1
 MOV EDX,(x).Big2
 
 SUB EAX,(y).Big1
 SBB EDX,(y).Big2
 
 MOV EBX,z
 MOV [EBX].Big1,EAX
 MOV [EBX].Big2,EDX
 
;-----------------------------------------------------------------------------
;void pascal quadsuba(Integer8* z, Integer8* x, Integer8* y)
;compute z=x-y
 
public QUADSUBA
QUADSUBA proc z:ptr, x:ptr, y:ptr
 
 MOV EBX,x
 MOV EAX,[EBX].Big1
 MOV EDX,[EBX].Big2
 MOV EBX,y
 
 SUB EAX,[EBX].Big1
 SBB EDX,[EBX].Big2
 
 MOV EBX,z
 MOV [EBX].Big1,EAX
 MOV [EBX].Big2,EDX
 
;-----------------------------------------------------------------------------
;void pascal quadmult(Integer8* z, Integer8 x, Integer8 y)
;compute z=x*y
 
public QUADMULT
QUADMULT proc z:ptr, x:qword, y:qword
 
 MOV EAX,(x).Big1
 MOV EBX,EAX
 
 MUL (y).Big2
 XCHG EAX,EBX
 MOV ECX,(y).Big1
 MUL ECX
 ADD EBX,EDX
 XCHG EAX,ECX
 MUL (x).Big2
 ADD EAX,EBX
 MOV EBX,z
 MOV [EBX].Big1,ECX
 MOV [EBX].Big2,EAX
 RET
 
QUADMULT endp
 
;-----------------------------------------------------------------------------
;void pascal quadmulta(Integer8* z, Integer8* x, Integer8* y)
;compute z=x*y
 
public QUADMULTA
QUADMULTA proc uses ESI, z:ptr, x:ptr, y:ptr
 
 MOV EBX,x
 MOV ESI,[EBX].Big1
 MOV ECX,[EBX].Big2
 MOV EBX,y
 MOV EAX,[EBX].Big2
 MOV EBX,[EBX].Big1
 
 MUL ESI
 XCHG EAX,ECX
 MUL EBX
 ADD ECX,EAX
 MOV EAX,EBX
 MUL ESI
 ADD EDX,ECX
 MOV EBX,z
 MOV [EBX].Big1,EAX
 MOV [EBX].Big2,EDX
 RET
 
QUADMULTA endp
 
;-----------------------------------------------------------------------------
;void pascal quaddiv(Integer8* z, Integer8 x, Integer8 y)
;compute z=x/y
 
public QUADDIV
QUADDIV proc uses ESI EDI, z:ptr, x:qword, y:qword
 
 XOR EDI,EDI  ;sign
 
 MOV EAX,(x).Big1
 MOV EDX,(x).Big2
 or EDX,EDX
 JNS quaddiv1
 
 INC EDI
 NEG EAX
 ADC EDX,0
 NEG EDX
 MOV (x).Big2,EDX
 MOV (x).Big1,EAX
quaddiv1:
 MOV EBX,(y).Big1
 MOV ESI,(y).Big2
 or ESI,ESI
 JNS quaddiv2
 
 INC EDI
 NEG EBX
 ADC ESI,0
 NEG ESI
quaddiv2:
 jnz quaddiv3 ;y >= 2^16?
 
;---------------------------------------
;y < 2^16:
 
 or EBX,EBX
 jz quaddiv9 ;divide by zero?
 
 MOV ECX,EAX
 MOV EAX,EDX
 XOR EDX,EDX
 DIV EBX
 XCHG EAX,ECX
 DIV EBX
 JMP quaddiv6
 
;---------------------------------------
;y >= 2^16:
 
quaddiv3:
 BSR ECX,ESI  ;shift right x AND y so that y<2^16
 INC CL
 PUSH EBX
 SHRD EBX,ESI,CL
 SHRD EAX,EDX,CL
 SHR EDX,CL
 
 DIV EBX  ;estimate z
 
 MOV EBX,EAX  ;multiply z with y
 MUL ESI
 MOV ECX,EAX
 POP EAX
 MUL EBX
 ADD EDX,ECX
 
 JC quaddiv4 ;compare z*y with x
 CMP EDX,(x).Big2
 JA quaddiv4
 JB quaddiv5
 CMP EAX,(x).Big1
 JBE quaddiv5
quaddiv4:
 DEC EBX  ;decrement z if z*y > x
quaddiv5:
 XOR ECX,ECX
 MOV EAX,EBX
 
;---------------------------------------
quaddiv6:
 DEC EDI
 jnz quaddiv7
 
 NEG EAX  ;change sign of result
 ADC ECX,0
 NEG ECX
 
quaddiv7:
 MOV EBX,z
 MOV [EBX].Big1,EAX
 MOV [EBX].Big2,ECX
 RET
 
quaddiv9:   ;divide error
 XOR EAX,EAX
 DEC EAX
 MOV ECX,7fffffffh
 JMP quaddiv6 ;return 7fffffffffffffffh
 
QUADDIV endp
 
;-----------------------------------------------------------------------------
;void pascal quaddiva(Integer8* z, Integer8* x, Integer8* y)
;compute z=x*y
 
public QUADDIVA
QUADDIVA proc z:ptr, x:ptr, y:ptr
 
 PUSH z
 MOV EBX,x
 PUSH [EBX].Big2
 PUSH [EBX].Big1
 MOV EBX,y
 PUSH [EBX].Big2
 PUSH [EBX].Big1
 CALL QUADDIV
 
 RET
 
QUADDIVA endp
 
;-----------------------------------------------------------------------------
end
 
 
 
 
 
 mov eax, [esp+4]
 mov edx, [esp+8]
 
 add eax, [esp+12]
 adc edx, [esp+16]
 
 sub eax, [esp+12]
 sbb edx, [esp+16]
 
Resultat auf                     EDX:EAX
Eingabezeiger auf                EBX oder ECX:EBX
Zwischenspeichern flüchtig auf   EDI:ESI
 
Bei Zeiger Operationen für FPU solte der Wert direkt aus dem Speicher geholt werden
 
;-----------------------------------------------------------------------------
;void pascal quadinc(Var1:I8:A, Var2:I4)
;compute z=z+x
 
QUADINC proc Var1:ptr, Var2:DWord
 
 MOV EAX, (Var1).Big1  ; [esp+4]
 MOV EDX, (Var1).Big2  ; [esp+8]
 
 ADD EAX, Var2         ; [esp+12]
 ADC EDX, 0
 
 
;-----------------------------------------------------------------------------
;void pascal quadinc(Var1:I8:A, Var2:I8)
;compute z=z+x
 
QUADINC proc Var1:ptr, Var2:qword
 
 MOV EAX, (Var1).Big1  ; [esp+4]
 MOV EDX, (Var1).Big2  ; [esp+8]
 MOV EBX, Var2
 
 ADD EAX, [EBX].Big1   ; [esp+12]
 ADC EDX, [EBX].Big2   ; [esp+16]
 
 
;-----------------------------------------------------------------------------
;void pascal quadinca(Var1:I8:A, Var2:I8:A)
;compute z=z+x
 
QUADINCA proc Var1:ptr, Var2:ptr
 
 MOV EBX, Var1
 MOV EAX, [EBX].Big1
 MOV EDX, [EBX].Big2
 MOV EBX, Var2
 
 ADD EAX, [EBX].Big1
 ADC EDX, [EBX].Big2
 
 
 
 
 
 pushfd
 and byte ptr [esp+0], 191 ;/* (type byte [esp]) */
 or eax, [ebx+0] ;/* [ebx] */
 setz al
 shl al, 6
 or [esp+0], al ;/* [esp] */
 popfd

Runtime/Mathe-Integer8.txt · Zuletzt geändert: 2009/02/15 14:44 (Externe Bearbeitung)