Welcome to Schneider / Amstrad CPC Forum. Please login or sign up.

29. March 2024, 06:39:31

Login with username, password and session length

Shoutbox

TFM

2024-01-15, 17:06:57
Momentan billige Farbbänder auf Ebay für PCW

Devilmarkus

2023-07-09, 10:37:40
Zweiter 👋😂🤣

TFM

2023-06-13, 14:21:49
Sommerloch!

TFM

2023-05-30, 17:00:20
Erster ;-)

Recent

Members
Stats
  • Total Posts: 11,655
  • Total Topics: 1,329
  • Online today: 109
  • Online ever: 1,724
  • (16. January 2020, 00:18:45)
Users Online
Users: 1
Guests: 102
Total: 103

102 Guests, 1 User
xesrjb

Z80 - 16 Bit Pointer auf einen 16 Bit-Wert dereferenzieren

Started by LambdaMikel, 29. June 2021, 19:35:47

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

LambdaMikel

Und mal wieder eine Frage an unsere Z80-Experten: da habe ich eine 16 Bit-Addresse im Speicher, die einen Pointer, also selbst eine 16 Bit-Addresse beinhaltet. Diese Addresse steht am label "pointer". Der Inhalt von "pointer" (= "(pointer)") ist also selbst eine 16 Bit-Addresse. Und nun möchte ich das 16-Bit Wort, auf das der Zeiger zeigt, in HL oder DE laden (oder IX oder IY).

Frage - gibt es was besseres als das?


pointer:  word &5678 ; example address

ld hl,(pointer)     
ld e,(hl)
inc hl
ld d,(hl)
...
jetzt habe ich in DE das Wort (Pointer+1)(Pointer), also den dereferenzierten Zeiger,
also D = RAM(&5678 + 1), E = RAM(&5678)


Idealerweise möchte ich also soetwas wie


LD DE,(HL)


haben, aber das gibt's nicht.  :motz:



HAL6128

LD DE,(pointer)
funktioniert, oder denke ich hier falsch?

Ne, quatsch, da bekommt DE ja auch nur die Adresse mit und nicht den Inhalt auf die referenzierte Speicherstelle.

Eventuell mit dem Stack arbeiten?
Irgendwie so, ohne dass dabei der Rechner NICHT abgeschossen wird (bin leider kein MC-Profi)?

ld hl,pointer
ex (sp),hl
pop de
ld a,(de)


LambdaMikel

Quote from: HAL6128 on 30. June 2021, 20:36:24
LD DE,(pointer)
funktioniert, oder denke ich hier falsch?

Ne, quatsch, da bekommt DE ja auch nur die Adresse mit und nicht den Inhalt auf die referenzierte Speicherstelle.

Eventuell mit dem Stack arbeiten?
Irgendwie so, ohne dass dabei der Rechner abgeschossen wird (bin leider kein MC-Profi)?

ld hl,pointer
ex (sp),hl
pop de
ld a,(de)


Hmm, das ist ja ne Bombe, muss ich mir mal genauer ansehen... besten Dank!

Na, ich mache das jetzt mal so - falls die Assembler-Profis Verbessrungsvorschläge haben, immer her damit. Ich mache Z80 nur alle 35 bis 40 Jahre  ;D

Hier also mein Testprogramm, das einen Speicherbereich mit <numbytes> (16 Bit) von 0 bis 255 füllt, über einen Pointer. Getestet mit Winape. Im BASIC dann call &4006. Im Debugger kann ich dann sehen, dass die Bytes richtig geschrieben wurden. Wäre nett wenn die Z80-Profis mal rübergucken könnten, ob man das besser / einfacher / schöner machen kann.



org &4000

; demonstrate how to fill a memory region based on a pointer

.counter defw 0
.numbytes defw &1000   

.pointer defb 0
.pointerh defb 0

; pointer contains is a memory address that points to a block of memory that
; we are writing to - starts at .memram

ld hl, pointer
ld (hl), memram mod 256
inc hl
ld (hl), memram / 256

; write numbytes from 0 to 255 starting at memram

ld a, 0

.loop

; compare 16 bit counter with 16 bit numbytes

ld hl,(counter)
ld de,(numbytes)

sbc hl,de

jr z,done

call inccounter

; dereference the pointer - store the accumulator to (*pointer) and (*pointer+1)

ld hl,(pointer)
ld (hl), a
inc hl

; now, update the pointer

push hl
pop de

ld hl,pointer
ld (hl), e
inc hl
ld (hl), d

; next round with incremented accu

inc a
jr loop

; done, wait for keypress

.done

ld a, '!'
call &bb5d
call &bb18

ret

; subroutine - increment the counter at a fixed address:

.inccounter

ld hl,(counter)
inc hl
push hl
pop de
ld hl, counter
ld (hl), e
inc hl
ld (hl), d

ret

; memory block to which we are writing:

.memram defb 0


TFM

Michael, da hast Du schon die ideale Programmierung gefunden. So etwas wie LD rr,(rr) gibt es leider nicht. Nur LD rr,(addr).

Helfen könnten hier IX und IY (anstatt RAM nutzen), aber die sind nicht gerade schnell.


Anstatt LD A,0 bitte XOR A,A verwenden, ist doppelt so schnell und halb so lang.
TFM of FutureSoft
http://www.futureos.de --> Das Betriebssystem FutureOS (Update: 20.12.2023)
http://futureos.cpc-live.com/files/LambdaSpeak_RSX_by_TFM.zip --> RSX ROM für LambdaSpeak (Update: 26.12.2021)

LambdaMikel

Quote from: TFM on 01. July 2021, 11:40:22
Michael, da hast Du schon die ideale Programmierung gefunden. So etwas wie LD rr,(rr) gibt es leider nicht. Nur LD rr,(addr).

Helfen könnten hier IX und IY (anstatt RAM nutzen), aber die sind nicht gerade schnell.


Anstatt LD A,0 bitte XOR A,A verwenden, ist doppelt so schnell und halb so lang.

Danke! Ja, das vergesse ich immer... allerdings muss ich sagen, dass mir die "direkte Lesbarkeit" (0 wird geladen) im Code meist wichtiger ist als 2 oder 3 Cycles zu sparen. Aber ja, für eine Optimierung sollte man das machen.  :smiley027:

Das Problem mit IX, IY + offset ist dass ich dann nur 256 Bytes addressieren kann, und IX, IY Tabellenbasis dann immer umladen muss alles 256 Bytes, aber das wäre noch einmal einen Versuch wert. Es scheint so aber auch schnell genug zu sein, insofern ist meine Motivation gering.

TFM

Also ich mach's immer mit HL, ist schön schnell und gut zu handhaben.
TFM of FutureSoft
http://www.futureos.de --> Das Betriebssystem FutureOS (Update: 20.12.2023)
http://futureos.cpc-live.com/files/LambdaSpeak_RSX_by_TFM.zip --> RSX ROM für LambdaSpeak (Update: 26.12.2021)