asm Anweisung vereinfachen

Gast #1940265
Lesenswert?

Hallo Fachkundige,
ich habe eine asm Anweisung geschrieben die man sicherlich noch 
vereinfachen kann. Die Anweisung stellt eine 8 auf einer 7-Segment 
Anzeige dar, welche mit einem 4511 Decodiert wird. Im Prinzip will ich 
nur wissen wie ich zB. die Pins in DDRD alle auf einmal aktivieren kann 
und nicht alle einzeln. Genauso wie alle Pins in PORT D Low setzten und 
nicht einzeln.

Quellcode:

        asm volatile (
        "sbi %0, %1" "\n\t"             /*Aktiviert den Pin2 (Enable)*/
        "sbi %2, %3" "\n\t"             /*Aktiviert den Pin3 (Input_A)*/
        "sbi %4, %5" "\n\t"             /*Aktiviert den Pin4 (Input B)*/
        "sbi %6, %7" "\n\t"             /*Aktiviert den Pin5 (Input_C)*/
        "sbi %8, %9" "\n\t"             /*Aktiviert den Pin6 (Input_D)*/
        "cbi %10, %11" "\n\t"           /*Setzt Input_A auf Low*/
        "cbi %12, %13" "\n\t"           /*Setzt Input_B auf Low*/
        "cbi %14, %15" "\n\t"           /*Setzt Input_C auf Low*/
        "cbi %16, %17" "\n\t"           /*Setzt Input_D auf Low*/
        "sbi %18, %19" "\n\t"           /*Setzt den Enable Pin auf 
High*/
        "sbi %20, %21" "\n\t"           /*Setzt Input_D auf High*/
        "cbi %22, %23" "\n\t"           /*Setzt den Enable Pin auf Low*/
        :
        : "M" (_SFR_IO_ADDR (DDRD)), "i" (2)
        , "M" (_SFR_IO_ADDR (DDRD)), "i" (3)
        , "M" (_SFR_IO_ADDR (DDRD)), "i" (4)
        , "M" (_SFR_IO_ADDR (DDRD)), "i" (5)
        , "M" (_SFR_IO_ADDR (DDRD)), "i" (6)
        , "M" (_SFR_IO_ADDR (PORTD)), "i" (3)
        , "M" (_SFR_IO_ADDR (PORTD)), "i" (4)
        , "M" (_SFR_IO_ADDR (PORTD)), "i" (5)
        , "M" (_SFR_IO_ADDR (PORTD)), "i" (6)
        , "M" (_SFR_IO_ADDR (PORTD)), "i" (2)
        , "M" (_SFR_IO_ADDR (PORTD)), "i" (6)
        , "M" (_SFR_IO_ADDR (PORTD)), "i" (2)
        );

Danke im Voraus,
Gruß, Damien.
Persönliche Seite #1940286
Lesenswert?

1
#define Enable PD2
2
// usw.
3

4
DDRD |= _BV(Enable)|_BV(Input_A)|_BV(Input_B)|_BV(Input_C)|_BV(Input_D);
5
PORTD &= ~(_BV(Input_A)|_BV(Input_B)|_BV(Input_C)|_BV(Input_D));
6
PORTD |= _BV(Enable);  // => sbi (s.u.)
7
PORTD |= _BV(Input_D); // => sbi
8
PORTD &= ~(_BV(Enable)); // => cbi

http://www.nongnu.org/avr-libc/user-manual/group__avr__sfr.html

Porting programs that use the deprecated sbi/cbi macros

Access to the AVR single bit set and clear instructions are provided via 
the standard C bit manipulation commands. The sbi and cbi macros are no 
longer directly supported. sbi (sfr,bit) can be replaced by sfr |= 
_BV(bit).

i.e.: sbi(PORTB, PB1); is now PORTB |= _BV(PB1);

This actually is more flexible than having sbi directly, as_ _the 
optimizer_ _will_ _use_ _a_ _hardware_ _sbi_ _if_ _appropriate, or a 
read/or/write operation if not appropriate. You do not need to keep 
track of which registers sbi/cbi will operate on.
#1940293
Lesenswert?

Damien schrieb:
> ich habe eine asm Anweisung geschrieben die man sicherlich noch
> vereinfachen kann.

Ja, kann man. Schreibs in C.
Assembler nimmt man nur, wenns in C nicht geht oder deutlich aufwendiger 
ist.


> Die Anweisung stellt eine 8 auf einer 7-Segment
> Anzeige dar, welche mit einem 4511 Decodiert wird.

Schau Dir dochmal andere MC-Projekte an. Du wirst da nie nen 7-Segment 
Dekoder sehen. Das kann die CPU nämlich sehr gut selber machen.


Und man macht auch nicht 10 Ausgaberoutinen für 10 Ziffern.
Ziffern sind ja quasi das, womit die CPU arbeitet, da muß man sich nicht 
umständliche Sachen ausdenken.

Eine Ziffer hat den Wert 0..9, diesen einer Routinen übergeben, die die 
10 7-Segmentmuster aus ner Tabelle liest und auf das gewünschte Digit 
ausgibt. Die Ziffer ist also der Zeiger auf den Tabelleneintrag.


Peter
Gast #1940496
Lesenswert?

Hallo,
so hatte ich mir das ungefähr gedacht:

        asm volatile (

        "ldi r16, 0xFF" "\n\t"
        "out [_DDRD], r16" "\n\t"

        "out [_PORTD], 0x00" "\n\t"

        "sbi [_PORTD], 0x04" "\n\t"             /*Setzt den Enable Pin 
auf High*/
        "sbi [_PORTD], 0x40" "\n\t"             /*Setzt Input_D auf 
High*/
        :
        : [_DDRD] "M" (_SFR_IO_ADDR (DDRD))
        , [_PORTD] "M" (_SFR_IO_ADDR (PORTD))

        );

aber das Problem ist das ich den falschen constrain benutze und er nicht 
versucht in "DDRD" sondern in "_DDRD" zu schreiben.. kann mir einer 
helfen?
Gast #1940516
Lesenswert?

Ja natürlich ist es das ^^

Ich kann C.. ich will nur ein bisschen mit den asm Befehlen rumspielen 
um ein bisschen das gefühl dafür zu bekommen.. Ich weiss schon das es in 
C einfacher ist aber mich interessiert einfach wie es in assembler läuft 
;)

Wenn mir einer mit dem Problem helfen kann wäre ich sehr dankbar
#1940605
Lesenswert?

Damien schrieb:
> Ich kann C.. ich will nur ein bisschen mit den asm Befehlen rumspielen
> um ein bisschen das gefühl dafür zu bekommen.

Oh, dann habe ich Dich mißverstanden. Ich dachte Du brauchst Hilfe bei 
einem Problem.
Aber es soll ja nur Spiel sein, da will ich Dich nicht weiter dabei 
stören.

GCC Inline Assembler gucke ich mir nicht ohne größte Not an, das ist 
einfach nur gräßlich.


Peter

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren