Forum: Mikrocontroller und Digitale Elektronik Wieso müssen beim Z-Pointer ZL und ZH beide multipliziert werden?


von SemiTech (Gast)


Lesenswert?

Microchip schrieb:
> "...Thus, the least significant bit of the Z pointer selects either low byte 
(ZLSB = 0) or high byte (ZLSB = 1)."

Also wird das LSB von ZL als Schlater für den Z-Pointer verwendet.
Es entscheidet, welcher Teil vom Datenwort geladen werden soll.
Deshalb macht es irgendwie auch Sinn den ZP beim initialisieren mit 2 zu 
multiplizieren. Aber für mich macht es keinen Sinn ZH und ZL einzeln zu 
multiplizieren/shiften, da beim multiplizieren mit dem ZH das Carry-bit 
von ZL nicht mit rein geshiftet wird. Ein Bit geht dann so zusagen 
verloren.
Trotzdem wird das so gemacht und es scheint auch zu funktionieren.
Wie es "alle" machen:
1
ldi ZL, LOW(text*2)         ; Adresse des Strings in den
2
ldi ZH, HIGH(text*2)        ; Z-Pointer laden
Und so würde es für mich Sinn machen:
1
ldi temp, LOW(text)
2
mul temp, 0x02 ;der entfallene Bit im Carry lagern
3
mov ZL, temp
4
ldi temp, HIGH(text)
5
mul temp, 0x02
6
adc temp, 0x00 ;Add with Carry
7
mov ZH, temp

Wie muss ich das verstehen?

Danke

von Karl M. (Gast)


Lesenswert?

Hallo,

das sieht nach AVR Mnemonics aus.

Du weisst schon, dass (text*2) Konstant ist?
Da wird zur Laufzeit nichts gerechnet!
Und die Macros/Anweisungen LOW(n), bzw. HIGH(n) "lesen" nur das 
jeweilige Byte aus.

von SemiTech (Gast)


Lesenswert?

Karl M. schrieb:
> Du weisst schon, dass (text*2) Konstant ist?
> Da wird zur Laufzeit nichts gerechnet!
> Und die Macros/Anweisungen LOW(n), bzw. HIGH(n) "lesen" nur das
> jeweilige Byte aus.

Sicher ist mir dass bewusst...

von Karl M. (Gast)


Lesenswert?

Beim AVR sind alle Flash-Adressen Zeiger auf Worte (16Bit),
eine Flash Byte-Adresse, hat dem nach den Wert (Pointer*2).
Steht auch so im Datenblatt eines AVR µC.
Bei manchen Zugriffen auf das Flash, muss man mit 20 Bit Adressen 
hantieren, da ḱommt dann ein weiteres Byte hinzu.

von Karl M. (Gast)


Lesenswert?

SemiTech schrieb:
> Karl M. schrieb:
>> Du weisst schon, dass (text*2) Konstant ist?
>> Da wird zur Laufzeit nichts gerechnet!
>> Und die Macros/Anweisungen LOW(n), bzw. HIGH(n) "lesen" nur das
>> jeweilige Byte aus.
>
> Sicher ist mir dass bewusst...

Dann ist deine Frage nicht sinnvoll.

von SemiTech (Gast)


Lesenswert?

SemiTech schrieb:
> Karl M. schrieb:
>> Du weisst schon, dass (text*2) Konstant ist?
>> Da wird zur Laufzeit nichts gerechnet!
>> Und die Macros/Anweisungen LOW(n), bzw. HIGH(n) "lesen" nur das
>> jeweilige Byte aus.
>
> Sicher ist mir dass bewusst...

Ehm... habs jetzt verstanden, danke.
Ich dachte erstmal du willst auf etwas anderes hinaus

von Karl M. (Gast)


Lesenswert?

Vielleicht noch eine Anmerkung:
wer mit 2 multipliziert, hat noch nie etwas von einem Verschieben nach 
Links   ins Carry "shl" und anschließendem rotieren nach Links mit Carry 
"rol" gehört.

von SemiTech (Gast)


Lesenswert?

Karl M. schrieb:
> Vielleicht noch eine Anmerkung:
> wer mit 2 multipliziert, hat noch nie etwas von einem Verschieben nach
> Links   ins Carry "shl" und anschließendem rotieren nach Links mit Carry
> "rol" gehört.

Doch klar, aber als ich letztens einen Beitrag über die Umwandlung von 
Assembler zu OP-Code gelesen habe und herausfand, das es zu rol und lsl 
keine OP Codes gibt, sondern dass diese vom Assembler durch andere 
Instruktionen ersetzt werden. Z.B. rol tmp == adc tmp, tmp, fand ich das 
sinnvoller, weil ich dem Assembler damit die Arbeit erspare.
Aber trotzdem danke für den Hinweis

von c-hater (Gast)


Lesenswert?

SemiTech schrieb:

> Microchip schrieb:
>> "...Thus, the least significant bit of the Z pointer selects either low byte
> (ZLSB = 0) or high byte (ZLSB = 1)."
>
> Also wird das LSB von ZL als Schlater für den Z-Pointer verwendet.

Bullshit. Das Zitat stammt aus der Beschreibung der beim Schreiben von 
Flash relevanten Funktionalität, konkret: der beim Füllen des 
Flashbuffers relevanten.

Das gilt dort UND NUR DORT. Dus unterste Bit von ZL wählt da aus, ob das 
Datum aus R0 oder R1 kommt. Das ist schon alles.

von Rolf M. (rmagnus)


Lesenswert?

SemiTech schrieb:
> Deshalb macht es irgendwie auch Sinn den ZP beim initialisieren mit 2 zu
> multiplizieren. Aber für mich macht es keinen Sinn ZH und ZL einzeln zu
> multiplizieren/shiften, da beim multiplizieren mit dem ZH das Carry-bit
> von ZL nicht mit rein geshiftet wird. Ein Bit geht dann so zusagen
> verloren.

Wie kommst du darauf?

> Wie es "alle" machen:
> ldi ZL, LOW(text*2)         ; Adresse des Strings in den
> ldi ZH, HIGH(text*2)        ; Z-Pointer laden

Es wird also die (16-bittige) Adresse als Ganzes mit 2 multipliziert, 
dann der LOW-Teil davon nach ZL geladen. Und das entsprechende wird dann 
mit dem HIGH-Byte und ZL gemacht. Wo willst du da irgendein Carry-Bit 
verlieren?

: Bearbeitet durch User
von SemiTech (Gast)


Lesenswert?

Rolf M. schrieb:
> Es wird also die (16-bittige) Adresse als Ganzes mit 2 multipliziert,
> dann der LOW-Teil davon nach ZL geladen. Und das entsprechende wird dann
> mit dem HIGH-Byte und ZL gemacht. Wo willst du da irgendein Carry-Bit
> verlieren?

Das hatte mir doch Karl M. schon gut erklärt.
Thema gegessen :D

von M. Н. (Gast)


Lesenswert?

SemiTech schrieb:
> das es zu rol und lsl
> keine OP Codes gibt, sondern dass diese vom Assembler durch andere
> Instruktionen ersetzt werden. Z.B. rol tmp == adc tmp, tmp, fand ich das
> sinnvoller, weil ich dem Assembler damit die Arbeit erspare.

Bitte... was? Dem Assembler die Arbeit ersparen. Habe selten so gelacht. 
Danke dafür. Wie viele Tage Urlaub bekommt der Assembler bei dir?

von M. Н. (Gast)


Lesenswert?

Und um deine Frage noch zu beantworten:

Das label 'text' liefert die 16 bit Wort-Adresse zurück. Aber der lpm 
Befehl erwartet eine Byte-Adresse im Z_Pointer. Deswegen wird text mit 2 
multipliziert (vom Assembler, da statischer Ausdruck) und diese Adresse 
wird dann verwendet.

Anzumerken ist dabei, dass dir .db vom Assembler aus diesem Grund immer 
an eine 16bit Wortadresse gelegt wird.
Diese zwei Bytes:
1
text: .db 0x10 ; <= Adresse text*2
2
      .db 0x11 ; <= Adresse (text+1)*2
liegen im Speicher nicht hintereinander. Es wird vom Assembler ein 
Pufferbyte eingefügt, sodass 0x11 wieder an einer wort adresse liegt. In 
diesem Fall warnt dich der Assembler aber. Will man die Bytes 
kontinuierlich im Speicher haben muss man
1
text: .db 0x10,0x11 ; <= Adressen text*2,text*2+1
schreiben.

von Opensource _. (opensource)


Lesenswert?

M. H. schrieb:
> Bitte... was? Dem Assembler die Arbeit ersparen. Habe selten so gelacht.
> Danke dafür.
sicherlich genial etwas knapp daneben, aber so ganz genau könnte der 
Opcode für mul Rd,k ["wer mit 2 multipliziert",..] auch nicht passen.
1
/*a*/ mul temp, 0x02;   früher: R1:R0 ← (tmp x Rr)  << 1
2
      ; rol tmp == adc tmp, tmp 
3
/*b*/ lsl tmp       ; tmp*2
4
/*c*/ add tmp, tmp  ; tmp+tmp
5
;     ....
6
      adc temp, 0x00 ;Add with Carry
/*c*/ könnte sich aufgrund der vielen Buchstaben als Mehrbeit für den 
Assembler herausstellen und hoffentlich findet SemiTech  auch etwas zum 
schmunzeln daran. Interessant wäre ob add tmp,tmp vs. lsl tmp dem 
programmierenden Denker Arbeit erspart, wenn der nicht aus Gewohnheit 
mit lsl vorbelastet ist.

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.