Forum: Mikrocontroller und Digitale Elektronik Assembler Programm Frage


von Bert S. (kautschuck)


Angehängte Dateien:

Lesenswert?

Hi,

warum ist für obiges Programm die Antwort (4,500) falsch? Dies führt 
doch auch zu 1000 Ausführungen, genauso wie (16,125)?

Gruss Bert

von Bert S. (kautschuck)


Lesenswert?

Sorry

: Bearbeitet durch User
von Pandur S. (jetztnicht)


Lesenswert?

Das AVR Studio hat einen Simulator. Ich empfehl das mal da laufen zu 
lassen. Man muss dort nicht die 1000 Loops machen, sondern kann einen 
Breakpoint setzen, nachdem man ein paar Loops per single-step 
durchgestept ist.

von Th. B. (thbaum)


Lesenswert?

Bert Siegfried schrieb:
> Hi,
>
> warum ist für obiges Programm die Antwort (4,500) falsch? Dies führt
> doch auch zu 1000 Ausführungen, genauso wie (16,125)?
>
> Gruss Bert

Hallo Bert,

das Listing ist sehr wahrscheinlich ein Assembler Programm für einen 
8bit AVR µC. r18 und r19 sind somit 8bit Register. Damit ist das laden 
von 500 nicht möglich. So mal die Vermutung.

Der Vergleich mit brne in Zusammenhang mit dem subi r18, 2 setzt eine 
gerade Zahl für Value1 vorraus.

Somit kann nur Antwort 2 (16,125) richtig sein

Gruß Thomas

von Bert S. (kautschuck)


Lesenswert?

Hallo, der uC sollte eigentlich wie im Labor ein Atmega128 sein.
Value1 ist in beiden Fällen jeweils eine gerade Zahl, value2 nicht, doch 
value2 wird ja auch immer nur subi r19, 0x01. Muss das mal mit dem 
Simulator testen.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Bert Siegfried schrieb:
> value2 wird ja auch immer nur subi r19, 0x01. Muss das mal mit dem
> Simulator testen.

 Brauchst du nicht, Thomas hat es dir schon erklart, aber hier
 nochmal:

 1) 4, 500 - geht nicht, auch ein ATMega 128 hat nur 8-bit Register.
 2) 16, 125 - Richtig, weil: 16/2 = 8*125 = 1000
 3) 200, 5 - Falsch, weil: 200/2 = 100 * 5 = 500
 4) 125, 16 - 125 ist ungerade Zahl, geht auch nicht
    (und aus diesem Loop kommst du nie raus).

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Immer diese praxisfernen Beispiele.
So würde das ein Programmierer nie schreiben, sondern so:
1
#define val 1000
2
  ldi r18, low(val)
3
  ldi r19, high(val)
4
m1:
5
  subi r18, low(1)
6
  sbci r19, high(1)
7
  brne m1

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Peter Dannegger schrieb:
> Immer diese praxisfernen Beispiele.
> So würde das ein Programmierer nie schreiben, sondern so:#define val
> 1000
>   ldi r18, low(val)
>   ldi r19, high(val)
> m1:
>   subi r18, low(1)
>   sbci r19, high(1)
>   brne m1

 Süß, aber beim AVR unnötig.
1
#define val 1000
2
  ldi r24, low(val)
3
  ldi r25, high(val)
4
m1:
5
  sbiw  r24, 1
6
  brne  m1

 Trotzdem cute, gefällt mir.

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

Peter Dannegger schrieb:

> Immer diese praxisfernen Beispiele.

Harharhar...

> So würde das ein Programmierer nie schreiben, sondern so:
[...]

Jetzt wird mir klar, warum du unfähig bist, gestaffelte Zählschleifen 
korrekt zu bewerten. Du machst es einfach immer so, wie es dein 
geliebter Compiler machen würde...

Aber nein, in manchen Fällen ist eine gestaffelte Schleife halt die 
bessere Lösung, z.B. wenn man in der inneren Schleife die eine Sache mit 
der Häufigkeit X erledigen will, in der äußeren Schleife aber eine 
andere Sache mit der Häufigkeit Y.

Übrigens ein sehr schönes Beispiel für die mangelnde Intelligenz von 
Compilern. KEINER ist in der Lage, die Ambition zweier Quasi-Parallel 
laufender Vorgänge mit unterschiedlicher Häufigkeit in einer Schleife 
aus dem C-Code zu erahnen und die Optimierung als gestaffelte Schleife 
zu wählen. Ich liebe es, wenn die C-Lover selber die Munition liefern, 
mit denen ich sie beschiessen kann...

von Heinz L. (ducttape)


Lesenswert?

Peter Dannegger schrieb:
> Immer diese praxisfernen Beispiele.
> So würde das ein Programmierer nie schreiben, sondern so:
>
1
> #define val 1000
2
>   ldi r18, low(val)
3
>   ldi r19, high(val)
4
> m1:
5
>   subi r18, low(1)
6
>   sbci r19, high(1)
7
>   brne m1
8
>

Peter, ich bin sicher nicht derjenige der grad Deinen Code in Frage 
stellen würde, aber bricht das nicht bei 0xFF bereits ab? Wegen

(bei val 0x100, d.h. r18=0x00, r19=0x01)

subi r18, 1 -> r18=0xff, CF=1, ZF=0
sbci r19, 0 -> r19=0x00, CF=0, ZF=1
brne -> false wegen ZF=1 -> Kein Sprung.


Ich hätte gemeint, dass ein dec r18 vor der Schleife (mit vorherigem 
oder implizitem Sicherstellen von val>=1 beim Start) mit brsh als 
Schleifenbedingung korrekt wäre. Also, Abbruch auf CF=1 statt ZF=1, und 
das dec halt weil wir bis "-1" statt bis 0 zählen müssen.

Oder wo hab ich den Denkfehler?

: Bearbeitet durch User
von M. P. (phpmysqlfreak)


Lesenswert?

Heinz L. schrieb:
> subi r18, 1 -> r18=0xff, CF=1, ZF=0
> sbci r19, 0 -> r19=0x00, CF=0, ZF=1
> brne -> false wegen ZF=1 -> Kein Sprung.
>
> Ich hätte gemeint, dass ein dec r18 vor der Schleife (mit vorherigem
> oder implizitem Sicherstellen von val>=1 beim Start) mit brsh als
> Schleifenbedingung korrekt wäre. Also, Abbruch auf CF=1 statt ZF=1, und
> das dec halt weil wir bis "-1" statt bis 0 zählen müssen.

Wird ZF bei gesetztem CF denn 1?

Datenblatt sagt:
SBCI Rd, K => "Rd ← Rd - K - C"

Heißt für mich:
r19 ← 0x00 - 0 - 1

r19 ← 0xFF

Woraus doch folgt:
CF = 1, ZF = 0

: Bearbeitet durch User
von Heinz L. (ducttape)


Lesenswert?

r19 ist vor der Schleife ja 1, nicht 0. 0x100 ist der Wert von val vor 
dem Schleifendurchgang, mit r19=1, r18=0. r18 wird mit "subi r18, 1" um 
1 erniedrigt, damit das CF gesetzt. Mit "sbci r19, 0" wird von r19 0 und 
das CF (gesetzt) abgezogen, also 1 - 0 - 1 = 0, damit dann CF=0 und 
ZF=1.

von M. P. (phpmysqlfreak)


Lesenswert?

Heinz L. schrieb:
> r19 ist vor der Schleife ja 1, nicht 0. 0x100 ist der Wert von val vor
> dem Schleifendurchgang, mit r19=1, r18=0. r18 wird mit "subi r18, 1" um
> 1 erniedrigt, damit das CF gesetzt. Mit "sbci r19, 0" wird von r19 0 und
> das CF (gesetzt) abgezogen, also 1 - 0 - 1 = 0, damit dann CF=0 und
> ZF=1.

Ok, mein Fehler.
Ich habe nicht alles bedacht, als ich meine Ausführung schrieb.

Heinz L. schrieb:
> (bei val 0x100, d.h. r18=0x00, r19=0x01)
>
> subi r18, 1 -> r18=0xff, CF=1, ZF=0
> sbci r19, 0 -> r19=0x00, CF=0, ZF=1
> brne -> false wegen ZF=1 -> Kein Sprung.

Hier nochmal, aber diesmal (hoffentlich) richtig bedacht. Ich habe
r18 bzw. r19 durch den jeweils aktuellen Wert ersetzt
angefangen bei 0x102.

subi 0x02, 0x01 -> 0x01, CF=0, ZF=0
sbci 0x01, 0x00 -> 0x01, CF=0, ZF=0
brne => Sprung

subi 0x01, 0x01 -> 0x00, CF=0, ZF=1
sbci 0x01, 0x00 -> 0x01, CF=0, ZF=0
brne => Sprung

subi 0x00, 0x01 -> 0xff, CF=1, ZF=0
sbci 0x01, 0x00 -> 0x00, CF=0, ZF=1
brne => kein Sprung

also kein weiterer Durchlauf.

von ThomasK (Gast)


Lesenswert?

wo bleibt c-hater wenn man ihn mal braucht?

Marcel Papst schrieb:
> subi 0x00, 0x01 -> 0xff, CF=1, ZF=0
> sbci 0x01, 0x00 -> 0x00, CF=0, ZF=1
> brne => kein Sprung

das ist falsch, weil laut der Beschreibung zum SBCI-Befehl:
1
[the Z-flag] remains unchanged when the result is zero; cleared otherwise

Oder auf deutsch: der SBCI-Befehl lässt das Z-Flag unverändert wenn das 
Resultat null ist und löscht das Z-Flag wenn das Resultat nicht null 
ist.

Dies genau aus diesem Grund: damit bei einer Subtraktion über 2 oder 
mehr Bytes das Z-Flag genau dann gesetzt ist, wenn alle Teilergebnisse 
null sind (und damit das Gesamtresultat null ist.)

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Marcel Papst schrieb:
> subi 0x02, 0x01 -> 0x01, CF=0, ZF=0
> sbci 0x01, 0x00 -> 0x01, CF=0, ZF=0
> brne => Sprung
>
> subi 0x01, 0x01 -> 0x00, CF=0, ZF=1
> sbci 0x01, 0x00 -> 0x01, CF=0, ZF=0
> brne => Sprung
>
> subi 0x00, 0x01 -> 0xff, CF=1, ZF=0
> sbci 0x01, 0x00 -> 0x00, CF=0, ZF=1
> brne => kein Sprung

 Flags und Registerwerte nach Befehlsbearbeitung.
1
  r18 = 2, r19 = 1
2
;==========================================
3
   subi r18, 1      ; r18 = 1 / ZF = 0 / CF = 0
4
   sbci r19, 0      ; r19 = 1 / ZF = 0 / CF = 0  => Sprung
5
6
   subi r18, 1      ; r18 = 0 / ZF = 1 / CF = 0
7
   sbci r19, 0      ; r19 = 1 / ZF = 0 / CF = 0  => Sprung
8
9
   subi r18, 1      ; r18 = FF / ZF = 0 / CF = 1
10
   sbci r19, 0      ; r19 =  0 / ZF = 0 / CF = 0  => Sprung
11
;===========================================

 Also doch weiterer Durchlauf.

 Und ThomasK hat dir erklart, warum das so ist.

: Bearbeitet durch User
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.