Wieso müssen beim Z-Pointer ZL und ZH beide multipliziert werden?

Gast #5661088
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
Gast #5661098
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.
Gast #5661101
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.
Gast #5661102
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
Gast #5661119
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
Gast #5661228
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.
#5661292
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?
Gast #5661334
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
Gast #5661423
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?
Gast #5661568
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.
#5661792
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.

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