;Zu übersetzen mit YASM; ml64 weigert sich, x87-Kode zu übersetzen
global sincos,llrint,hypotf,mydiv, exp,sin,cos,tan,atan,atan2,log,fmod, sqrt,fsincos
;****************************************************************
;* Integer-Sinus/Kosinusberechnung (fehlt in der Win32-API) *
;* Parameter: int Radius, int Winkel in Zehntelgrad *
;* Ergebnis: POINT-Struktur mit *
;* x=lrint(cos(Winkel*PI/1800)*Radius) und y=lrint(sin(... *
;****************************************************************
v180 dw 1800
sincos:
shl rcx,32 ;Radius
or rcx,rdx ;Winkel in Zehntelgrad
push rcx ;es können nur 64 Bits gepusht werden
fild dword[rsp+4] ;Radius laden
fild dword[rsp] ;Winkel laden
fldpi ;PI laden
fmulp st1,st0
fidiv word[rel v180] ;jetzt st0 = Winkel im Bogenmaß, st1 = Radius
fsincos ;st0 = Kosinus, st1 = Sinus, st2 = Radius
fmul st0,st2
fxch st1 ;st0 = Sinus, st1 = Kosinus, st2 = Radius
fmulp st2,st0 ;st0 = Kosinus, st1 = Sinus
fistp dword[rsp] ;Kosinuswert
fistp dword[rsp+4] ;Sinuswert
pop rax
ret
;****************************************
;* double -> __int64 mit Rundung *
;* Standard: Mathematische Rundung, *
;* also 0,5 -> 0, 1,5 -> 2 *
;* Ersetzt (int)floor(x+0.5) *
;****************************************
llrint:
cvtpd2dq xmm0,xmm0 ;umwandeln
movq rax,xmm0 ;dorthin, wo's C erwartet
ret
;********************************************************
;* Division mit Rest *
;* Bitbreiten: __int64 / unsigned = int REST unsigned *
;* Besonderheit: Divisionsergebnis rundet zu -unendlich,*
;* Rest stets >= 0 (und < Divisor natürlich) *
;* Einschränkung: Divisor darf nicht > INT_MAX sein. *
;* Ergebnis muss in 32 bit (div_t) passen *
;********************************************************
mydiv:
mov eax,edx
sar rdx,32 ;mache aus rdx -> edx:eax
idiv ecx
or edx,edx ;Rest negativ?
jns .pos
dec eax ;Divisionsergebnis abrunden
add edx,ecx ;Rest positiv machen (Voraussetzung: Divisor ist positiv!)
.pos: shl rdx,32
or rax,rdx ;Returnwert in RAX!
ret
;************************
;* Hypotenuse berechnen *
;************************
hypotf: ;lohnt nicht so recht
mulss xmm0,xmm0
mulss xmm1,xmm1
addss xmm0,xmm1
sqrtss xmm0,xmm0
ret
;wird für etwas älteren C-Compiler (WinXP SDK) benötigt, nicht für MSVC 2005 und neuer
sqrt: sqrtsd xmm0,xmm0
ret
$fsincos:
movq rax,xmm1
push rax
fld qword[rsp]
fsincos
fstp qword[rcx]
fstp qword[rcx+8]
pop rax
ret
;**********************
;* Standardfunktionen *
;**********************
exp:
movq rax,xmm0
push rax
fld qword[rsp]
fldl2e
fmulp st1,st0 ;st = f * log2 e
fld st0 ;duplizieren
frndint ;st0 = ganzzahliger Teil (Rundung kaufmännisch)
fsub st1,st0 ;st1 = gebrochener Teil (± 0,5)
fxch st1
f2xm1 ;st0 = 2^gebrochener_Teil-1 (f2xm1 kann nur im Intervall ±1 arbeiten!)
fld1
faddp st1,st0 ;1 addieren: st0 = 2^gebrochener_Teil
fscale ;st0 = 2^gebrochener_Teil * 2^ganzzahliger_Teil
pop2: fstp st1 ;ganzzahligen Teil entfernen
pop1: fstp qword[rsp]
pop rax
movq xmm0,rax
ret
sin:
movq rax,xmm0
push rax
fld qword[rsp]
fsin
jmp pop1
cos:
movq rax,xmm0
push rax
fld qword[rsp]
fcos
jmp pop1
tan:
movq rax,xmm0
push rax
fld qword[rsp]
fptan
fstp st0
jmp pop1
atan:
xor eax,eax
inc eax
cvtsi2sd xmm1,eax ;1 laden
atan2:
movq rax,xmm0
push rax
fld qword[rsp]
movq [rsp],xmm1
fld qword[rsp]
fpatan
jmp pop1
log:
movq rax,xmm0
push rax
fldln2
fld qword[rsp]
fyl2x
jmp pop1
fmod:
movq rax,xmm1 ;Argumente verkehrt herum laden
push rax
fld qword[rsp]
movq [rsp],xmm0
fld qword[rsp]
fprem ;Modulo-Division, 0<=Ergebnis<Divisor (Divisor>0)
jmp pop2 ;st1 entfernen und st0 liefern
end
Vorgefundene Kodierung: ANSI (CP1252) | 4
|
|