Forums

Sega Master System / Mark III / Game Gear
SG-1000 / SC-3000 / SF-7000 / OMV
Home - Forums - Games - Scans - Maps - Cheats - Credits
Music - Videos - Development - Hacks - Translations - Homebrew

View topic - Pointer incrementation in asm

Reply to topic
Author Message
  • Joined: 18 Jul 2019
  • Posts: 30
Reply with quote
Pointer incrementation in asm
Post Posted: Mon Aug 05, 2019 1:48 pm
Last edited by Yuguzu on Mon Aug 05, 2019 2:07 pm; edited 1 time in total
Hello guys.

I'm currently looking at the code in asm generated and I see this everywere:
   ld   a, -2 (ix)
   add   a, #0x02
   ld   -2 (ix), a
   jr   NC,00155$
   inc   -1 (ix)


This happen when I do a basic:
myPointer++;


Can someone tell why do I have:
   jr   NC,00155$
   inc   -1 (ix)


Thanks
  View user's profile Send private message
  • Joined: 24 Sep 2013
  • Posts: 141
Reply with quote
Post Posted: Mon Aug 05, 2019 2:02 pm
It looks like a 16 bit increment taking carry into account (the correct way to increment a 16bit integer)

Expected behaviour provided pointers are 16bit.
  View user's profile Send private message Visit poster's website
  • Joined: 18 Jul 2019
  • Posts: 30
Reply with quote
Post Posted: Mon Aug 05, 2019 2:15 pm
NeonMan wrote
It looks like a 16 bit increment taking carry into account (the correct way to increment a 16bit integer)

Expected behaviour provided pointers are 16bit.


I see. So the only way to bypass this is to be sure the pointer adress low byte will never go beyond 0xFF.
  View user's profile Send private message
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 14685
  • Location: London
Reply with quote
Post Posted: Mon Aug 05, 2019 6:26 pm
Does preincrement (++myPointer) make any difference? The code here seems to be operating on a pointer in memory via ix, which is about the slowest way possible...
  View user's profile Send private message Visit poster's website
  • Joined: 18 Jul 2019
  • Posts: 30
Reply with quote
Post Posted: Mon Aug 05, 2019 11:12 pm
Maxim wrote
Does preincrement (++myPointer) make any difference? The code here seems to be operating on a pointer in memory via ix, which is about the slowest way possible...

Same with preincrement. There are "ix" everywere :).
I guess I have no choice but to convert my c code to asm.
  View user's profile Send private message
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 14685
  • Location: London
Reply with quote
Post Posted: Mon Aug 05, 2019 11:41 pm
Classical C style calling conventions and stack layout really don't go well with the Z80...
  View user's profile Send private message Visit poster's website
  • Joined: 24 Sep 2013
  • Posts: 141
Reply with quote
Post Posted: Tue Aug 06, 2019 12:20 pm
The IX increment happens because the pointer is on the stack and IX is convenient to make stack access. I'm unsure if making it `static` (move it to bss) would make a difference
  View user's profile Send private message Visit poster's website
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 14685
  • Location: London
Reply with quote
Post Posted: Tue Aug 06, 2019 4:23 pm
Certainly, but in assembly we would strive never to use the stack for variables. Making it global could make it generate simpler code. If your pointer cannot cross a 256 byte boundary then it can allow much simpler code but I don’t think SDCC can deal with that.
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 3758
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Tue Aug 06, 2019 4:40 pm
(if you're lucky) you'd probably get

inc hl
inc hl

using a global variable, if the function isn't complex...
  View user's profile Send private message Visit poster's website
  • Joined: 18 Jul 2019
  • Posts: 30
Reply with quote
Post Posted: Tue Aug 06, 2019 6:30 pm
Last edited by Yuguzu on Wed Aug 07, 2019 7:14 am; edited 1 time in total
sverx wrote
(if you're lucky) you'd probably get

inc hl
inc hl

using a global variable, if the function isn't complex...


Yes it does. Thanks guys! You saved me lot of time.
I still got "ix" and "iy" here and there but it's lot better now. It's weird though. Sometime there is absolutely no reasons to use the stack. I think the compiler loves to use ix and iy for conditional statements:
   ld   iy, #_myGlobalVariable
   ld   a, 0 (iy)
   sub   a, #0x0f
   jr   NZ,00106$

At this point of the code there is no value stored in "hl".
  View user's profile Send private message
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 14685
  • Location: London
Reply with quote
Post Posted: Wed Aug 07, 2019 6:20 am
Using the stack for storage is fine if it’s as fast as using fixed memory addresses, or if you are writing a relocatable program so you have no choice. Conversely, global are evil :) and your code will be harder to read if you use them.

In the end, the C language is not a good fit to Z80 and you have to accept the assembly is quite poor compared to hand written stuff - but accept that as the cost of not having to actually write it yourself.
  View user's profile Send private message Visit poster's website
  • Joined: 14 Aug 2000
  • Posts: 740
  • Location: Adelaide, Australia
Reply with quote
Pointer incrementation in asm
Post Posted: Thu Aug 08, 2019 3:12 am
Man, that syntax with the offset number outside of the brackets is just awful to look at.

If you cast or use a BYTE instead of an INT does the resulting code look any better? Because if, say, the pointer is pointing to your game level variable and you only have 8 level in your game, then why use 2 bytes of RAM to hold that 1 byte of info?

Quote
The code here seems to be operating on a pointer in memory via ix, which is about the slowest way possible...


True that. IX and IY instructions are very slow. But when you're working with data structures they are money. If you have to increment the pointer more than twice when reading data from the structure then you're worse off using HL instead of IX or IY.
  View user's profile Send private message
  • Joined: 18 Jul 2019
  • Posts: 30
Reply with quote
Post Posted: Thu Aug 08, 2019 9:05 am
asynchronous wrote
If you cast or use a BYTE instead of an INT does the resulting code look any better?


Yes it's better. Actually I found tricks to force the compiler to use available register instead of the stack. One of them is to to write this:
unsigned char* tmp = (unsigned char*)my16bitPtr;
myIncrement += myIncrement;
tmp += myIncrement


What I also so found is that the compiler doesn't organize registers use very well. Sometime it will store a value in a register where it's not very optimum. Exemple:
myGlobal16BitVar = XXXX;
myGlobal16BitVarSave = myVar;
unsigned int* myPtr = (unsigned int*)myGlobalPtr;
for(unsigned int i=XX; i>0; i--){
   *myPtr++ = myVar++;
}
myGlobal16BitVar = myGlobal16BitVarSave;


In this case there is a good chance that "myGlobal16BitVarSave" will be stored in a register. And this register will not be available in the loop. Therefore the stack will be used instead in the loop.


So what I do is this. I remove this line:
myGlobal16BitVar = myGlobal16BitVarSave;


And I put this instead:
__asm
   ld   hl, #myGlobal16BitVarSave
   ld   (myGlobal16BitVar), hl
   __endasm;


So now the compiler think that "myGlobal16BitVarSave" is never use and don't use a register to store it.

That's the best I found for now :)
  View user's profile Send private message
Reply to topic



Back to the top of this page

Back to SMS Power!