- Labornetzteil AliExpress         
Seite 2 von 3 ErsteErste 123 LetzteLetzte
Ergebnis 11 bis 20 von 22

Thema: Parameterübergabe bei Inline-Assembler

  1. #11
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    21.10.2005
    Ort
    Erde
    Alter
    57
    Beiträge
    1.195
    Anzeige

    Praxistest und DIY Projekte
    Hier mal ein schöner Vergleich:

    Code:
    uint16_t fmac16(uint16_t op1, uint16_t op2, uint16_t op3)
    {
    	uint16_t result;
    
    	// range checkto prevent overflow. It is necessary that at least one
    	// operand's high byte is != 0x80
    	op1 = (op1 != 0x8000) 
    		? (op2 = (op2 != 0x80) ? op2 : 0x81), op1 
    		: 0x8100;
    	
    	asm volatile (
    		"fmuls %B1, %B2"	"\n\t" // take high byte of op1 and op2 only
    		"add r0, %A3"		"\n\t" // do a 16 bit add
    		"adc r1, %B3" 		"\n\t"
    		"movw %0, r0"   	"\n\t"
    		"brvc 0f" 			"\n\t" // check for overflow (pos/neg) @see fadd8
    		"ldi %A0, 0xff" 	"\n\t"
    		"ldi %B0, 0x7f" 	"\n\t"
    		"brcc 0f"			"\n\t"
    		"ldi %A0, 0x00"		"\n\t"
    		"ldi %B0, 0x80"		"\n\t"
    		"0:"				"\n\t"
    		: "=&a" (result)
    		: "a" (op1), "a" (op2), "a" (op3)
    		: "r0", "r1"
    	);
    
    	return result;
    }
    Für die eigentliche MAC Operation werde hier nur 5 Takte benötigt (fmul, add, adc und movw).

    Eine direkte Implementierung in C
    Code:
    	uint16_t op161;
    	uint16_t op162;
    	uint16_t op163;
    	uint16_t result16;
    
    	op161 = 0x8000;
    	op162 = 0x8000;
    	op163 = 0x7000;
    
    	result16 = op161*op162+op163; // <- Das hier
    Ist als Assembler Code schon erheblich länger:
    Code:
    	mul r18,r24
    	movw r20,r0
    	mul r18,r25
    	add r21,r0
    	mul r19,r24
    	add r21,r0
    	clr r1
    	movw r18,r20
    	ldd r24,Y+9
    	ldd r25,Y+10
    	add r24,r18
    	adc r25,r19
    und benötigt 17 Takte, wobei die +/- Überlaufprüfung nochmal erheblich komplexer wäre.

  2. #12
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Ein Fehler ist noch drinne: R1 muss nach einer Funktion/Assembler-Schnippsel unverändert vorliegen, denn avr-gcc hält immer 0 in diesem Register!

    Wenn du es also veränderst, musst du die 0 wieder herstellen, sonst bekommst du an ganz anderer Stelle einen Fehler.
    Disclaimer: none. Sue me.

  3. #13
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    21.10.2005
    Ort
    Erde
    Alter
    57
    Beiträge
    1.195
    Super, danke für den Hinweis. Bevor ich mich jetzt wirder durchs .S File quäle: Reicht es nicht, r1 in der Clobber Liste anzugeben?

  4. #14
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Nein, das genügt nicht. Sonst hätt ich nix dazu geschrieben
    Aus den Clobbers kann es also raus. R0 ebenfalls, da wird eh von ausgegangen, daß das nichts überlebt.
    Disclaimer: none. Sue me.

  5. #15
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    21.10.2005
    Ort
    Erde
    Alter
    57
    Beiträge
    1.195
    OK, also push r1, pop r1 und gut ist.

  6. #16
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    21.10.2005
    Ort
    Erde
    Alter
    57
    Beiträge
    1.195
    Was ist dann der Effekt, wenn ich ein Register (z.B. r1) in der Clobber Liste angebe?

  7. #17
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    AFAIK sind R0 und R1 fided regs, werden also nicht vom Compiler verwendet.
    Um genau zu sein: Der Compiler reloadet z.B. keine Variablen in diese Register oder verwendet sie für Funktionsargumente oder zum temporären Speichern. Dennoch werden sie im avr-gcc-Backend verwendet, etwa wenn ein int gegen eine Konstande kleiner als 256 verglichen wird (Das highbyte wird dann mit cpc __zero_reg__ verglichen).
    Der Compiler selbst hat aber auf interner Ebene keine "Vorstellung" von diesen Registern, sondern dieser Verwendung als temp bzw. 0-Register geschehen implizit durch die Backend-Implementierung.

    Alles klar? Wahrscheinlich noch verwirrter als vorher...

    Register > 1 in der Clobber-Liste haben hatürlich einen Effekt. Mach mal eine Funktion und clobbere r2 und schau den Code an.
    Disclaimer: none. Sue me.

  8. #18
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    21.10.2005
    Ort
    Erde
    Alter
    57
    Beiträge
    1.195
    Danke jetzt ist klar. Habe r1 am Anfang der mul auf den Stack gelegt und nacher wieder restauriert. Sind halt zwei Takte mehr.

  9. #19
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Ein clr braucht einen Takt, während push/pop (Speicherzugriff!) 4 Takte braucht. Zudem braucht es 1 Byte vom Stack und das doppelte an Flash...

    Einfach
    clr r1
    oder
    clr __zero_reg__
    Disclaimer: none. Sue me.

  10. #20
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    21.10.2005
    Ort
    Erde
    Alter
    57
    Beiträge
    1.195
    Ah bestens! Danke.

Seite 2 von 3 ErsteErste 123 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen