Nice! For modifying the SP is the best way. A bit slower is to load SP into IX. Maybe the faster and safer is:
; sub sp,4 ld hl,-4 add hl,sp ld sp,hl add hl, 4 push hl pop ix
IX/IY is needed because they allow indexing, and HL not.
local? ohw like they only are inside the loop.
use sublabels:
program: ld a,2 ld (.variable),a .variable: db 0
or you use IX as pointer for local
;trow pointer of IX wherever needed. ld ix,adress ld (ix+xobject),5 ld (ix+yobject),6 xobject: equ 1 yobject: equ 2 localvariables: ;active?, xobject, yobject db 0, 0, 0 lenghtvariableslist: equ $ - localvariables db 0, 0, 0 db 0, 0, 0 db 0, 0, 0 db 0, 0, 0 db 0, 0, 0
'add hl,4' is not a Z80 instruction. I also don't see why you need it. I guess you want to set IX to the original value of SP so you can index your local variables from there? Why not set IX to the new value of SP and take this difference into account in the offset of the 'LD r,(IX+n)' instructions. So something like this:
; allocate space for local variables ld ix,-4 add ix,sp ld sp,ix ; use local vars ... ld (ix+0),1 ... ld a,(ix+3) ... ; deallocate stack frame ld hl,4 ; or use IX instead of HL if you want to preserve HL add hl,sp ; e.g. because HL contains the return value of your function ld sp,hl
I must be missing something, because, frankly, I don't see the point in all this.
It seems to me you're trying too hard to mimic the OOP way of doing things.
@Daemos if you define local variables using RAM space, maybe the space is not shared. Using the stack you get when you need and free when finished.
@Metalion avoid side-effects (using globals), or trying not to overlap when you have dozens of functions.
@wouter_ that seems the best option.
In addition, allocating local variables in stack is the best approach to implement recursive and reentrant functions.
Interesting point, using the stack to temp store bytes. But it's tricky and takes a few extra cycles, which slows down your code. For such approach I use a defined buffer of 256 bytes. That buffer gets shared in all my code. Tho I like the SP method, it's not really practical on Z80.
my 0,02euros
Stack for local variables is the common practice for compilers when you need to assure recursion and reentrancy.
Hitech C crosscompiler allocates room on the stack at the beginning of each function and accesses to the variables using IX.
https://www.msx.org/forum/msx-talk/development/allocation-stack
I love using the OOP pattern in assembly btw. Though I myself mostly allocate my objects either on the heap or statically, the stack is a great and relatively fast alternative to get past the registers limit for temporary data, without fragmenting the heap. Do your awesome stuff and ignore the naysayers! ;p Usually structure and ease of development is 10x more important than a few ms better performance, and you can always optimise the critical parts later.
Btw, all my MSX projects are programmed in OOP fashion. Gunzip beat every other archiver by a mile in terms of performance.
I love using the OOP pattern in assembly btw.
...
Gunzip beat every other archiver by a mile in terms of performance.
To be honest you should probably add that if you do give up on OOP it is possible to make msx-gunzip 10% faster
But this is also very Z80 specific. On modern CPUs local variables on the stack typically are faster than global variables.