Logarithmus Instruktion neben FYL2X



  • Hallo,

    ich berechne in einer Funktion den Logarithmus mit beliebiger Basis wie folgt:

    global _log
    
    ; _log(
    ;	_in_ long double base, 
    ;	_in_ long double num
    ; );
    _log:
    	push ebp                            ; save old frame pointer
    	mov  ebp, esp                       ; new frame pointer
    	add  esp, -8                        ; allocate local variables
    
    	fld1                                ; st0 = 1.0
    	fld  base                           ; st0 = base | st1 = 1.0
    	fyl2x                               ; st1 = result
    	fstp QWORD PTR [esp]                ; [esp] = result
    
    	fld1                                ; st0 = 1.0
    	fld  num                            ; st0 = num | st1 = 1.0
    	fyl2x                               ; st1 = result
    
    	fdiv QWORD PTR [esp]                ; st1 = result
    
    	mov  esp, ebp
    	pop  ebp
    	ret
    

    Beispielhafter Aufruf:

    BASE   DQ 04024000000000000r	; 10.0
    NUM    DQ 0408f400000000000r	; 1000.0
    RESULT DQ ?
    
    sub  esp, 8
    fld  QWORD PTR [NUM]
    fstp QWORD PTR [esp]
    
    sub  esp, 8
    fld  QWORD PTR [BASE]
    fstp QWORD PTR [esp]
    
    call _log
    add  esp, 16
    
    fstp QWORD PTR [RESULT]
    

    So, meine Frage ist jetzt, ob jemand von euch eine Instruktion kennt, die lediglich log2(x) durchführt und nicht y * log2(x) wie fyl2x. Ehrlich gesagt verbirgt sich mir gerade auch der Sinn des Ganzen.



  • Ich glaube, sowas kann die FPU nicht. KA, ob evtl. irgendeine der tausend Befehlserweiterungen entsprechende Befehle bietet.
    Ansonsten ist dieser Befehl so IMHO aber auch recht praktisch. Dass du das Produkt von einem Logarithmus mit irgendwas ausrechnen willst, kommt in der Praxis gar nicht mal so selten vor. Das klappt natuerlich nicht so gut, wenn du mit solchen Funktionen versuchst Funktionen zu kapseln, fuer die die fpu nicht unbedingt optimiert ist. Insofern hast du dort ein schoenes Beispiel, wie man moeglichst nicht Assembler programmieren sollte...

    Nur um ein Anwendungsbeispiel zu geben: Du haettest auch zuerst 1/ld(base) berechnen und das so mit dem ld(num) multiplizieren koennen. Und um die Sache noch besser zu nutzen, koenntest du auch gleich noch einen Faktor zum Ranmultiplizieren an die Funktion uebergeben.



  • y*log2(x) wird z.B. zur Berechnung von x^y benötigt.



  • Nobuo T schrieb:

    Insofern hast du dort ein schoenes Beispiel, wie man moeglichst nicht Assembler programmieren sollte...

    Wie würdest du es denn machen? Das was du weiter unten beschreibst ist ja nicht so viel anders.



  • Oben steht bereits ein Vorschlag, wie du die Funktion modifizieren kannst, um zumindest jeweils die Multiplikationen mitbenutzen zu koennen. Das koennte IMHO schon durchaus etwas bringen.
    Ansonsten gilt fuer solche Optimierungen kleiner Funktionen ganz allgemein zB.: Schau, ob du die Funktion inline machen oder zumindest die Parameter ueber den fpu-Stack uebergeben kannst und ob du diese log-Funktion in der Form wirklich brauchst oder ob du das Problem evtl. auch irgendwie anders oder eleganter in Hinblick auf die fpu-Architektur loesen kannst. Da ist eben etwas Kreativitaet gefragt. 🙂



  • Kurze Zwischenfrage:

    Wenn ld(x^y) = y * ld(x) ist, dann muss x^y = 2^(y * ld(x)) sein oder nicht? Will mir nicht so ganz gelingen:

    fld exp								// st0 = exp	
    		fld base							// st0 = base | st1 = exp
    		fyl2x								// st1 = result
    
    		fxch								// st0 <=> st1
    		f2xm1
    


  • deine Annahme ist richtig, hier eine Realisierung für x >= 0 und beliebiges y:
    (die fpu kann nur mit Integers 2^x bilden - fscale richtet das)

    ;st(0) = st(1)^st(0) = 2^(st(0)*ld(st(1)))
    fyl2x
    fld st(0)
    frndint
    fsub st(1),st(0)
    fxch
    f2xm1
    fadd const_r4_one ; alternativ fld1,faddp
    fscale
    


  • ach, bevor ichs noch vergesse, diese Seite hier ist zu diesem Thema wohl auch
    recht lesenswert:

    http://www.xsession.de/uni/assembler/index.html


Anmelden zum Antworten