Help needed with a bit of code...

edited October 2014 in Development
My minds gone blank again I'm afraid, I'm having trouble with this routine that loads variables into memory then calls the corresponding routine.

Theres 3 variables which makes it awkward. I'm sure theres an easy way, but I just cant see the wood for the trees at the minute...

Thanks in advance...
ld b,3
	ld hl, cor
	ld de,adds
loop
	ld a,(de)
	ld (caller+1),a
	inc de
	ld a,(de)
	ld (caller+2),a; loads address to be called in de
	inc de

	;ld a,(hl)	;hl stores variables
			;now i need to load the variables into the address stored in de ???

	push af
	push de
	push bc
caller
	call 56003	;routine to be  called 
	pop bc
	pop de
	pop af
	djnz loop
	ret


adds
	defw 58239
	defw 56003
	defw 51173	;start adress of routines

cor 
	defb 2,2,4
	defb 10,10,4
	defb 12,14,6	;variables for routine 3 bytes prior to start
Post edited by daveysludge on

Comments

  • edited October 2014
    My first thought is that using CALL ... JP (HL) would be better than poking the call address. That is, calling a fixed point (there's one in the ROM somewhere, which I'll find in a minute) then using HL to redirect to the required address.

    There's a JP (HL) at $1715, but it only takes one byte, so it might as well just be in your own code. Still thinking about the variables question ...

    --

    OK, here's my other thought. Store each sub-routine address followed by its three variables: address, byte, byte, byte. Point HL to the one you want, then:

    LD E,(HL) : INC HL : LD D,(HL) : INC HL : EX DE,HL : CALL $1715

    then when the sub-routine is entered DE will be pointing to its first variable.
  • edited October 2014
    I note you're not PUSHing HL to keep it safe when you do the CALL.

    If you need that 'adds' table to point to your routines, why not have them point three bytes earlier? And instead of programming the addresses, just refer to a label for each routine like:

    defw routine_1 - 3
    defw routine_2 - 3
    defw routine_3 - 3

    Then you load the address you get from the table into DE, point HL at your numerical data, then do LDI three times to copy three bytes from (HL) to (DE). PUSH everything you want to preserve, then EX HL,DE to swap the pointers over and CALL (HL), since it will now be pointing to the start of your routine. When you POP those values again, DE and HL will be back as they were.

    And don't forget, if you run out of address pointers, you can use IX and IY in most places where you use HL, it'll just be a fraction slower. They can be very convenient though to use as table pointers, freeing up DE and HL for different tasks. And EX DE,HL can come in very handy when using one address to look up another. And don't forget you can always PUSH DE and later POP the value into HL instead later, for example.
    Joefish
    - IONIAN-GAMES.com -
  • edited October 2014
    Still flummoxed!

    The poking the call routine isn't the problem, that works fine, its the variables, particularly this bit:
    ld a,(HL)
    ld (address stored in DE (less 3)),a
    inc hl
    ld a,(HL)
    ld (address stored in DE (less 2)),a
    inc hl
    ld a,(HL)
    ld (address stored in DE (less 1)),a
    inc hl
    

    I need to load a register with the value of the contents of DE and then load that address with the contents of HL.

    I cant seem to find the right command,
  • edited October 2014
    If that's really what you mean, then why not:
     ex hl, de
     ld c,(hl)
     inc hl
     ld b,(hl)
     dec hl ; assuming you need to preserve 'DE'
     ex hl, de
     dec bc
     dec bc
     dec bc
     ld a,(hl)
     ld (bc),a
     inc hl
     inc bc
     ld a,(hl)
     ld (bc),a
     inc hl
     inc bc
     ld a,(hl)
     ld (bc),a
     inc hl
    
    Although that doesn't seem terribly efficient and looks like it would trash your address table (unless there is some in-between code missing). I can't help but feel if it were clearer what you were trying to achieve overall, there'd be a better approach. Calling a parameterized jump block for example.
  • edited October 2014
    @ AndyC...

    I'm basically trying to avoid typing out loads of this...
    ld a,10
    ld (56000),a
    ld a,14
    ld (56001),a
    ld a,6
    ld (56002),a
    call 56003
    
    ld a,12
    ld (56000),a
    ld a,24
    ld (56001),a
    ld a,3
    ld (56002),a
    call 56003
    
    ;ad infinitum!
    
  • edited October 2014
    Use a macro to save typing? Although jp (hl) is probably what you want.
  • edited October 2014
     call 56003
     defb 10,14,6
     call 56003
     defb 12,24,3
      
     56003:
     pop hl
     ld de,56000
     ldi
     ldi
     ldi
     push hl
    

    Stack abuse FTW. :-)
  • edited October 2014
    Sorted!

    37 bytes, can anyone improve on it?
    ld b,2
    	ld hl,dat
    loop	ld e,(hl)
    	inc hl
    	ld d,(hl) 
    	inc hl
    	ld a,(hl)
    	ld (de),a
    	inc hl
    	inc de
    	ld a,(hl)
    	ld (de),a
    	inc hl
    	inc de
    	ld a,(hl)
    	ld (de),a
    	inc hl
    	inc de
    	ld (caller+1),de
    	push de
    	push hl
    	push bc
    caller	call 56000
    	pop bc
    	pop hl
    	pop de
    	djnz loop
    	ret
    
    dat	defw 56000
    	defb 14,20,3
    
    	defw 56000
    	defb 5,5,6
    
  • edited October 2014
    If you do your PUSH BC at the start of the loop, you can (as AndyC indicated) probably replace:
    ld a,(hl)
    ld (de),a
    inc hl
    inc de
    

    with
    ldi
    

    http://z80-heaven.wikidot.com/instructions-set:ldi
  • edited October 2014
    31 bytes, assuming the caller function doesn't wreck the shadow registers:
    org 32000
    	ld b,2
    	ld hl,dat
    loop	exx
    	ld e,(hl)
    	inc hl
    	ld d,(hl) 
    	inc hl
    	ldi
    	ldi
    	ldi
    	ld (caller+1),de
    	push de
    	push hl
    caller	call 56000
    	pop hl
    	pop de
    	exx
    	djnz loop
    	ret
    
    dat	defw 56000
    	defb 14,20,3
    
    	defw 56000
    	defb 5,5,6       
    
  • edited October 2014
    Cheers guys!

    Memory is getting tight so any saving is essential!
  • edited October 2014
    Actually Ignore mine, duno what i was smoking. :)

    You could use the af/'af for the count, that was in my mind originally then went off on a merry road of insanity with the exx.
    	ld a,2
    	ld hl,dat
    loop	
            ex af,af'
    	ld e,(hl)
    	inc hl
    	ld d,(hl) 
    	inc hl
    	ldi
    	ldi
    	ldi
    	ld (caller+1),de
    	push de
    	push hl
    caller	call 56000
    	pop hl
    	pop de
    	ex af,af'
    	dec a
            jr nz,  loop
    	ret
    
    dat	defw 56000
    	defb 14,20,3
    
    	defw 56000
    	defb 5,5,6
    
Sign In or Register to comment.