wpc115



  • Aber wie funktioniert dieser Code?
    Wo stehen die Multiplikation mit 36000, 3600, 600, 60 und 10?

    EDIT:
    Witzig ist Folgendes: wenn ich mit 36001 multipliziere, steht auf einmal folgendes im Code:

    imul	 edi, 36001
    

    Irgendwie produziert der Compiler aus der 10 die 60, aus der 60 die 600 usw.. Echt nicht übel, hätte ich nicht gedacht, dass der so gut optimiert!



  • kenn mich mit asm nicht so besonders aus, aber habe gerade per hilfe rausgefunden, dass multiplikationen wohl

    "als Folge von Schiebe- und LEA-Anweisungen zu implementieren" sind

    hatte in der hilfe einfach mal nach "lea" gesucht

    hier ein bsp. aus der hilfe!!:

    <ZITAT>

    Das nachfolgende Codebeispiel zeigt den Unterschied zwischen den Optionen Weniger Code bevorzugen (/Os) und Schnellen Code bevorzugen (/Ot):

    /* differ.c
    Dieses Programm implementiert einen Multiplikations-
    Operator.
    Mit /Os kompilieren, um Multiplizieren explizit als Multiplizieren zu implementieren.
    Mit /Ot kompilieren, um als Folge von Schiebe- und LEA-Anweisungen zu implementieren.
    */
    int differ(int x)
    {
    return x * 71;
    }

    Der nachfolgende Ausschnitt aus dem Maschinen-Code zeigt, daß der Compiler den Multiplikationsausdruck in der Return-Anweisung explizit als eine Multiplikation implementiert, um eine kurze, aber langsamere Codefolge zu erzeugen, wenn bei der Kompilierung von DIFFER.C weniger Code bevorzugt wird (/Os):

    mov eax, DWORD PTR _x$[ebp]
    imul eax, 71 ; 00000047H

    Wenn bei der Kompilierung von DIFFER.C dagegen Geschwindigkeit bevorzugt wird (/Ot), implementiert der Compiler den Multiplikationsausdruck in der Return-Anweisung als eine Folge von Schiebe- und LEA-Anweisungen, um eine schnelle, aber längere Codefolge zu erzeugen:

    mov eax, DWORD PTR _x$[ebp]
    mov ecx, eax
    shl eax, 3
    lea eax, DWORD PTR [eax+eax*8]
    sub eax, ecx

    </ZITAT>



  • Interessant ist, wie er erst eax = t2[0]-t1[0] berechnet, was ja durchaus nicht verkehrt ist, dann aber eax als Zeiger verwendet (lea eax, DWORD PTR [eax+eax*4]). Kann aber auch sein, dass ich mich verguckt habe, AT&T Syntax ist doch ein wenig anders.



  • ah jetzt habe ich das einigermaßen verstanden:

    shl eax, 3 verschiebt bitweise nach links(3 stellen)
    und lea ... ist dann eine multiplikation
    (Skalierung eines Registers; Register können nur mit den Werten 1, 2, 4 oder 8 skaliert werden.)

    also nehmen wir an, wir multiplizieren 3 mit der 71

    3= 00000011
    um 3 nach links:

    24=00011000

    und jetzt die lea anweisung

    24+24*8 = 216

    jetzt noch sub:

    216-3 = 213 =3*71

    ist ja cool

    und jetzt bei us:

    lea eax, DWORD PTR [eax+eax*4]
    00018 d1 e0 shl eax, 1

    = mal zehn

    cu



  • ERROR schrieb:

    also ich habe 6- 5+ und 5*

    also ein + weniger

    aber den unterschied macht auf jeden fall der zugriff auf die einzellnen zahlen
    da hebe ich die unterschiede meiner versuche drastisch gemerkt

    cu

    Das hatte ich im ersten Versuch auch. Im zweiten Versuch habe ich 8 Subtraktionen, 5 Multiplikationen, 6 bitweise UND, ein paar Shifts und 4 Additionen.
    Damit bin ich auf meinem PC bei 4000000000 Aufrufen ganze 4,5 Sekunden schneller 😃

    00000	8b 4c 24 08	 mov	 ecx, DWORD PTR _t2$[esp-4]
      00004	8b 54 24 04	 mov	 edx, DWORD PTR _t1$[esp-4]
      00008	56		 push	 esi
      00009	8b 01		 mov	 eax, DWORD PTR [ecx]
      0000b	8b 32		 mov	 esi, DWORD PTR [edx]
      0000d	2b c6		 sub	 eax, esi
      0000f	8b 72 04	 mov	 esi, DWORD PTR [edx+4]
      00012	05 10 10 10 10	 add	 eax, 269488144		; 10101010H
      00017	33 d2		 xor	 edx, edx
      00019	89 44 24 08	 mov	 DWORD PTR _first$[esp], eax
      0001d	8a d4		 mov	 dl, ah
      0001f	25 ff 00 00 00	 and	 eax, 255		; 000000ffH
      00024	8b 49 04	 mov	 ecx, DWORD PTR [ecx+4]
      00027	2b ce		 sub	 ecx, esi
      00029	5e		 pop	 esi
      0002a	8d 04 80	 lea	 eax, DWORD PTR [eax+eax*4]
      0002d	81 c1 10 10 10
    	10		 add	 ecx, 269488144		; 10101010H
      00033	d1 e0		 shl	 eax, 1
      00035	03 c2		 add	 eax, edx
      00037	89 4c 24 08	 mov	 DWORD PTR _second$[esp-4], ecx
      0003b	81 e1 ff 00 00
    	00		 and	 ecx, 255		; 000000ffH
      00041	8d 14 40	 lea	 edx, DWORD PTR [eax+eax*2]
      00044	33 c0		 xor	 eax, eax
      00046	8a 44 24 07	 mov	 al, BYTE PTR _first$[esp-1]
      0004a	8d 04 50	 lea	 eax, DWORD PTR [eax+edx*2]
      0004d	8d 14 80	 lea	 edx, DWORD PTR [eax+eax*4]
      00050	8d 04 51	 lea	 eax, DWORD PTR [ecx+edx*2]
      00053	33 c9		 xor	 ecx, ecx
      00055	8a 4c 24 0a	 mov	 cl, BYTE PTR _second$[esp-2]
      00059	8d 04 40	 lea	 eax, DWORD PTR [eax+eax*2]
      0005c	8d 04 41	 lea	 eax, DWORD PTR [ecx+eax*2]
      0005f	8d 14 80	 lea	 edx, DWORD PTR [eax+eax*4]
      00062	33 c0		 xor	 eax, eax
      00064	8a 44 24 0b	 mov	 al, BYTE PTR _second$[esp-1]
      00068	8d 84 50 10 2b
    	f6 ff		 lea	 eax, DWORD PTR [eax+edx*2-644336]
    

    Was mir allerdings Kopfschmerzen macht, ist das Abfangen von Überläufen: von 01:30:00 bis 02:00:00 sind es schließlich nicht 00:70:00 🙄 (und ich habe meinen Vorschlag schon abgeschickt 👎)

    /Edit: Kommando zurück. Das wird ja nicht 00:70:00, sondern 01:-30:00 und damit passt es wieder, stimmt's? 🙂



  • tag schrieb:

    Im zweiten Versuch habe ich 8 Subtraktionen, 5 Multiplikationen, 6 bitweise UND, ein paar Shifts und 4 Additionen.

    ich bin sogar auf drei multiplikationen runter. dazu 4 shifts, 6 subtraktionen und 5 additionen und zu viele zuweisungen.
    aber schneller wird's dadurch auch nicht.



  • Wie schnell ist euer Code denn?

    mfg
    v R



  • virtuell Realisticer schrieb:

    Wie schnell ist euer Code denn?

    was bringt es dir, wenn ich zeit und meinen prozessor sage? damit kannste die sache mit deinem prozessor nicht vergleichen.



  • ok



  • volkard schrieb:

    virtuell Realisticer schrieb:

    Wie schnell ist euer Code denn?

    was bringt es dir, wenn ich zeit und meinen prozessor sage? damit kannste die sache mit deinem prozessor nicht vergleichen.

    Da hast auch war, war auch nur interessenhalber 🙂

    @ERROR: Stell den Code am besten erst rein, wenn die Aufgabe vorbei ist ;).

    mfg
    v R



  • hm ERROR, hab das vorhin ganz vergessen.. aber bei deinem code is noch bissel was drin.. so optimal gekürzt war das nicht 🙂



  • man is' das lange her..

    int wpc116(char *t1, char *t2) {
    	return  t2[7]-t1[7]+10*(t2[6]-t1[6]+6*(t2[4]-t1[4]+10*(t2[3]-t1[3]+6*(t2[1]-t1[1]+10*(t2[0]-t1[0])))));
    }
    

    nach jahren mal 'ne lösung posten 😃

    hoffe das stimmt auch, hab das nu' nicht mehr getestet 🤡


Anmelden zum Antworten