Forum: Mikrocontroller und Digitale Elektronik Bitvergleiche in Assembler durchführen


von Magische Fee (Gast)


Lesenswert?

Ich will nicht zwei ganze Register miteinander vergleichen, wie in 
diesem Beispiel aus dem Tutorial, sondern ich möchte z.B. r17(BIT3) mit 
r16(BIT0) vergleichen, aber ich weis nicht, wie ...

cp     r17, r16         ; vergleiche r17 mit r16, ich will aber zwei 
Bits
                        ; miteinander vergleichen aus den Registern
    brne    nicht_gleich
    ...
    rjmp    weiter
nicht_gleich:
    ...
weiter:

von frühaufsteher (Gast)


Lesenswert?

andi r16,(1<<bit)
andi r17,(1<<bit)
cp r16,17
brne ...

von frühaufsteher (Gast)


Lesenswert?

Achso, die Registerwerte sollen nicht verändert werden? Schmeiß sie mit 
push auf den Stack und hole sie mit pop wieder runter oder mache mit mov 
ne Kopie.

von spess53 (Gast)


Lesenswert?

Hi

>andi r16,(1<<bit)
>andi r17,(1<<bit)
>cp r16,17
>brne ...

Das funktioniert nicht.

>Achso, die Registerwerte sollen nicht verändert werden? Schmeiß sie mit
>push auf den Stack und hole sie mit pop wieder runter oder mache mit mov
>ne Kopie.

Geht auch ohne:
1
           ldi r16,0b00001000
2
           ldi r17,0b00000001
3
           
4
           bst r17,0          Bit ins T-Flag
5
6
           sbrs r16,3
7
           brtc gleich        wenn beide Bits = 0
8
9
           sbrc r16,3
10
           brts gleich        wenn beide Bits = 1
11
12
ungleich:  nop
13
14
gleich:    nop

MfG Spess

von frühaufsteher (Gast)


Lesenswert?

spess53 schrieb:
> Hi
>
>>andi r16,(1<<bit)
>>andi r17,(1<<bit)
>>cp r16,17
>>brne ...
>
> Das funktioniert nicht.
Wieso? Wenn beide Bits an der selben Stelle sind geht das doch prima.

> Geht auch ohne:
Ja ok, war ja auch noch früh.

von spess53 (Gast)


Lesenswert?

Hi

>Wieso? Wenn beide Bits an der selben Stelle sind geht das doch prima.

Magische Fee schrieb:
> ich möchte z.B. r17(BIT3) mit r16(BIT0) vergleichen,

Sind halt nicht an der gleichen Bitposition.

MfG Spess

von Magische Fee (Gast)


Lesenswert?

Hallo Spess53,

hab ich das jetzt richtig verstanden - ich kopiere aus Register 17 mein 
gewünschtes Bit in das T-Flag und mit den Befehlen sbrs/sbrt wird dann 
mein gewünschtes Bit des Registers 16 mit dem T-Flag verglichen?

Sorry, aber da muss man erstmal echt drauf kommen, ich habe gestern über 
drei Stunden versucht, das hinzubekommen und habe als die 
Assemblerbefehle angeschaut und versucht, mir eine Lösung 
zurechtzubiegen, was nicht klappte.

Herzlichen Dank für Deine Ausführungen und auch danke an Frühaufsteher, 
ich werde beides einfach mal im AVR-Studio ausprobieren und schauen, was 
passiert.

von frühaufsteher (Gast)


Lesenswert?

spess53 schrieb:
> Hi
>
>>Wieso? Wenn beide Bits an der selben Stelle sind geht das doch prima.
>
> Magische Fee schrieb:
>> ich möchte z.B. r17(BIT3) mit r16(BIT0) vergleichen,
>
> Sind halt nicht an der gleichen Bitposition.
>
> MfG Spess

Ach verflixt, das hab ich überlesen. Man sollte halt nicht vor dem 
ersten Kaffee im Forum posten. ;-)

von Magische Fee (Gast)


Lesenswert?

Ich möchte bitte wissen - sind die beiden Befehle identisch:

andi r16,(1<<bit)
andi r16, 0b000000010

oder

andi r16,(7<<bit)
andi r16, 0b100000000

von spess53 (Gast)


Lesenswert?

Hi

>hab ich das jetzt richtig verstanden - ich kopiere aus Register 17 mein
>gewünschtes Bit in das T-Flag und mit den Befehlen sbrs/sbrt wird dann
>mein gewünschtes Bit des Registers 16 mit dem T-Flag verglichen?

Nicht direkt verglichen. Aber zu den Sprungbefehlen kommst du nur, wenn 
das Bit in r16 einen bestimmten Zustand hat.

Ich habe das ganze mal in ein Macro gepackt:
1
            .macro cp_bits   ; Register1,Bitnummer1,Register2,Bitnummer2
2
              clz
3
              bst @2,@3
4
              sbrs @0,@1
5
              brts not_equal
6
              sbrc @0,@1
7
              brtc not_equal
8
              sez
9
not_equal:
10
            .endmacro
11
12
; Aufruf (dein Beispiel):
13
14
         cp_bits r16,3,r17,0
15
         breq ...               ; wenn gleich
16
         brne ...               ; wenn nicht gleich

MfG Spess

von Peter D. (peda)


Lesenswert?

Oder:
1
            .macro cp_bits   ; Register1,Bitnummer1,Register2,Bitnummer2
2
              clr  r0
3
              sbrc @0,@1
4
              inc  r0
5
              sbrc @2,@3
6
              inc  r0
7
              ror  r0
8
            .endmacro
9
10
; Aufruf (dein Beispiel):
11
12
         cp_bits r16,3,r17,0
13
         brcc ...               ; wenn gleich
14
         brcs ...               ; wenn nicht gleich


Peter

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Magische Fee schrieb:
> Ich möchte bitte wissen - sind die beiden Befehle identisch:
>
> andi r16,(1<<bit)
> andi r16, 0b000000010

Möglicherweise, nämlich für bit==1

> andi r16,(7<<bit)
> andi r16, 0b100000000

Nein.

von Peter D. (peda)


Lesenswert?

Oder:
1
            .macro cp_bits   ; Register1,Bitnummer1,Register2,Bitnummer2
2
              clr  r0
3
              sbrc @0,@1
4
              inc  r0
5
              sbrc @2,@3
6
              dec  r0
7
            .endmacro
8
9
; Aufruf (dein Beispiel):
10
11
         cp_bits r16,3,r17,0
12
         breq ...               ; wenn gleich
13
         brne ...               ; wenn nicht gleich

Peter

von Magische Fee (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Oder:            .macro cp_bits   ; Register1,Bitnummer1,Register2,Bitnummer2
>               clr  r0
>               sbrc @0,@1
>               inc  r0
>               sbrc @2,@3
>               inc  r0
>               ror  r0
>             .endmacro
>
> ; Aufruf (dein Beispiel):
>
>          cp_bits r16,3,r17,0
>          brcc ...               ; wenn gleich
>          brcs ...               ; wenn nicht gleich
>
>
> Peter

cool, danke für die Idee mit dem Makro. Eine Frage hab ich noch zu 
Makros, die Teile &0,&1,&2,&3 entsprechen ja so wie ich es sehe z.B.

int macro (int a, int b, int c, int d)
{
  int returnwert;
  jetzt kann ich a,b,c und d verwenden - Integer nur als Beispiel.
  Wenn ich nun einen Wert zurückliefern möchte

  return(returnwert)
}

geht das auch in assembler, dass ich beispielsweise schreibe:

cp_bits r20,r16,0,r17,5

und nun könnte das Makro die Variable r20 praktisch als Rueckgabewert 
zurückliefern, dass wäre sehr praktisch.

von Magische Fee (Gast)


Lesenswert?

Magische Fee schrieb:
> und nun könnte das Makro die Variable r20 praktisch als Rueckgabewert
> zurückliefern, dass wäre sehr praktisch.

ich hab mich unpraktisch ausgedrückt, ich möchte, dass ich mit dem 
übergebenen Wert in r20 in dem Makro auch etwas rechnen kann und der 
veränderte Wert zurückgeliefert wird, was in c wahrscheinlich so wäre

int makro (int Zaehler, int Reg1, int Bit1, int Reg2, int Bit2)
{

 Bitvergleichsoperationen...

 Zaehler++;
 return Zaehler;
}

int main ()
{
 int Anzahl=0;

 ...

 Anzahl = makro (Anzahl, Register1, Bit1, Register2, Bit2);
}

dass halt in Assembler.

von spess53 (Gast)


Lesenswert?

Hi

>geht das auch in assembler, dass ich beispielsweise schreibe:
>cp_bits r20,r16,0,r17,5

Ja. Aber was soll das für ein Rückgabewert sein? In den Macros von Peter 
und mir wird das Z-Flag als Rückgabewert verwendet. Du kannst also mit 
breq/brne sofort auf das Ergebnis reagieren.

MfG Spess

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Nein, ein Makro ist keine Funktion bzw. ein Unterprogramm!

Statt eines Funktionsaufrufes erfolgt nämlich eine Ersetzung des Makros 
zur Kompilierzeit. Zwar machen dies einige Compiler auch bei Funktionen, 
dies aber nur dann, wenn es keine Seiteneffekte geben kann.

Das Äquivalent zum Assembler-Makro ist in C das Makro des Präprozessors:
1
#define CP_BITS(a, b, c, d) \
2
  ... \
3
  ... \
4
  ....

von Magische Fee (Gast)


Lesenswert?

spess53 schrieb:
> Ja. Aber was soll das für ein Rückgabewert sein? In den Macros von Peter
> und mir wird das Z-Flag als Rückgabewert verwendet. Du kannst also mit
> breq/brne sofort auf das Ergebnis reagieren.

Ja, Du hast recht, dass ist der Befehl in Euren Makros clz/sez

Mein Gedankensprung war grad, wenn ich eine Vergleichsoperation oft 
aufrufen muss und eine Registervariable bearbeite, dann muss ich immer 
wieder mit den zwei Befehlen im Hauptprogramm breq/brne wieder 
auswerten, Sprungmarken setzen ..., wenn ich das gleich auch noch in dem 
Makro erledigen könnte, dann würde das Schreibaufwand sparen. Auch würd 
ich gleich lernen, wie das  noch geht. In den Lernunterlagen von mir, 
die ich als Drucksache zu Haus liegen hab, gibt es z.B. den Befehl 
.makro garnicht drinnen, dass wird dort garnicht erwähnt.

von Magische Fee (Gast)


Lesenswert?

Ich finde z.B. die Anweisung .macro auch garnicht in dem Datenblatt von 
dem verwendeten uC Atmega48. Ich find da auch garnicht Befehle wie 
.cseg, .exit, .include ..., stehen diese Anweisungen bei Atmel in einem 
gesonderten Schriftstück?

von spess53 (Gast)


Lesenswert?

Hi

>stehen diese Anweisungen bei Atmel in einem gesonderten Schriftstück?

Das sind auch keine Befehle sondern Assembler Direktiven. Beschreibung 
findest du unter AVR Studio Hilfe->AVR Assembler->User's 
Guide->Directives

oder AVR Studio-> Help -> Assembler Help

Weiter Interessant: AVR Assembler 2 ->Preprocessor.

MfG Spess

von Magische Fee (Gast)


Lesenswert?

Jetzt hab ich Dank Eurer Hilfe mein erstes Assembler-Programm 
fertigbeommen, und es funktioniert, dafuer danke ich Euch recht 
herzlich.
1
 Programm zum Zaehlen von Impulsen 
2
3
.include "m48def.inc"
4
5
6
.def Neuzustand = r16
7
.def Altzustand = r17
8
.def Zaehler_Bit0 = r20
9
.def Zaehler_Bit1 = r21
10
.def Zaehler_Bit2 = r22
11
.def Zaehler_Bit3 = r23
12
.def Zaehler_Bit4 = r24
13
.def Zaehler_Bit5 = r25
14
.def Zaehler_Bit6 = r26
15
.def Zaehler_Bit7 = r27
16
17
.def temp1 = r31
18
19
/* *****************************************************************************************
20
 * Makro Counter_Set
21
 *
22
 * Dient zum Zaehlen von von steigenden Flanken. Counter wird inkrementiert, wenn steigende
23
 * Flanke festgestellt wurde
24
 *
25
 * @0: Counter
26
 * @1: Register1 (IstZustand)
27
 * @2: Bit1
28
 * @3: Register2 (AltZustand)
29
 * @4: Bit2
30
 * *****************************************************************************************/
31
32
.macro Counter_Set
33
   bst @3,@4         ;Speicher Bit@4 aus Register@3 im Transferbit
34
35
   sbrs @1,@2        ;Ueberspringe naechsten Befehl, wenn Istzustand = 1
36
   brts _not_equal   ;gehe zu "Adresse", wenn Transferbit = 1
37
38
   sbrc @1,@2        ;Ueberspringe naechsten Befehl, wenn Istzustand = 0
39
   brtc _not_equal   ;gehe zu "Adresse", wenn Transferbit = 0
40
   rjmp _equal
41
      
42
_not_equal:
43
   sbrc @1,@2        ;bei steigender Flanke @0 inkrementieren
44
      inc @0
45
_equal:
46
.endmacro
47
48
/* Initialisieren */
49
/* ************** */
50
  
51
   ldi Zaehler_Bit0, 0x00 ; Zaehler auf NULL setzen
52
   ldi Zaehler_Bit1, 0x00
53
54
   ldi temp1, 0x00 ; PortB Eingang
55
   out DDRB, temp1
56
57
/* Hauptprogramm */
58
/* ************* */
59
60
   in Altzustand, PINB
61
62
Schleife:
63
   in Neuzustand, PINB
64
   
65
   Counter_Set Zaehler_Bit0, Neuzustand, 0, Altzustand, 0
66
   Counter_Set Zaehler_Bit1, Neuzustand, 1, Altzustand, 1
67
   Counter_Set Zaehler_Bit2, Neuzustand, 2, Altzustand, 2
68
   Counter_Set Zaehler_Bit3, Neuzustand, 3, Altzustand, 3
69
   Counter_Set Zaehler_Bit4, Neuzustand, 4, Altzustand, 4
70
   Counter_Set Zaehler_Bit5, Neuzustand, 5, Altzustand, 5
71
   Counter_Set Zaehler_Bit6, Neuzustand, 6, Altzustand, 6
72
   Counter_Set Zaehler_Bit7, Neuzustand, 7, Altzustand, 7
73
74
   mov Altzustand, Neuzustand
75
rjmp Schleife

von spess53 (Gast)


Lesenswert?

Hi

Bei dieser Aufgabenstellung kann man sich das Vergleichen sparen:
1
/* Hauptprogramm */
2
/* ************* */
3
   clr r16
4
   mov r2,r16                  ; r2 = Null
5
6
   in Altzustand, PINB
7
8
Schleife:
9
   in Neuzustand, PINB
10
11
   mov r18,Neuzustand          ; Kopie erstellen
12
   eor r18,Altzustand          ; geändert Bits auf 1
13
   and r18,Neuzustand          ; nur Bits 0->1
14
   mov Altzustand,Neuzustand
15
16
   lsr r18                     ; Bit ins Carry-Flag
17
   adc Zaehler_Bit0,r2         ; Bitzähler + 0 + Carry
18
19
   ....
20
21
   lsr r18
22
   adc Zaehler_Bit7,r2
23
24
   rjmp Schleife

MfG Spess

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.