0

I am trying to make a subroutine that prints a null terminated string, but it doesn't work. in my first attempt:

PRINTLN:   ld   a, (bc)     // set bc to start of string before calling
           add  a, 0        // update zero flag
           jp   z, endprint // if the character at (bc) is a null, terminate loop
           out  1, a        // output to port 0 (TTY in emulator)
           inc  bc          // point to next character
           jp   println     // rinse and repeat
ENDPRINT:  ret              // end of subroutine

it just repeated the string until it stopped for some reason. My emulator won't let me view the stack. The next attempt was to put the address of PRINTLN to de before the loop and then just push de and use ret instead of jp:

PRINTLN:   ld   de, printloop // attempt to get rid of jp's effect on the stack
PRINTLOOP: ld   a, (bc)       // set bc to start of string before calling
           add  a, 0          // update zero flag
           jp   z, endprint   // if the character at (bc) is a null, terminate loop
           out  1, a          // output to port 0 (TTY in emulator)
           inc  bc            // point to next character
           push de            // I hope this works
           ret                // rinse and repeat
ENDPRINT:  ret                // end of subroutine

This ended in a failure too, because it kept repeating the first character of the string for some reason. What is going on and what do I do to fix it?

  • `jp` doesn't alter the stack. Please post a complete minimal example, including the code that calls this function. – Michael Dec 19 '18 at 16:43
  • Code looks correct. My best guess is that your stack is not pointing at RAM. Can you step through the code? What emulator are you using? – George Phillips Dec 19 '18 at 19:34
  • @Michael https://pastebin.com/ma9V4CDe – Michal Nemecek Dec 21 '18 at 20:11
  • @GeorgePhillips I stepped through the code at least 20 times. I'm using ZEMU ([link](http://www.z80.info/z80emu.htm#EMU_CPU_W32)) – Michal Nemecek Dec 21 '18 at 20:13
  • 1
    Are you sure that the `HALT` actually halts forever? If an interrupt is triggered, execution will continue past `HALT`, which would be bad. What if you replace it with an infinite loop? – Michael Dec 21 '18 at 21:04
  • In the emulator, the interrupts are buttons. I didn't press them. Also, I noticed that the emulator may be badly written, because I stepped through the code and saw the stack pointer decrease by 2 each time the emulator executed the `jp` instruction. – Michal Nemecek Dec 22 '18 at 09:47
  • Also, adding an infinite loop doesn't fix the problem. The problem is that it `ret`'s to `0x0000`, not that it goes past `halt`. – Michal Nemecek Dec 22 '18 at 10:25
  • Confirmed, the emulator is inaccurate. In ZEMU (the emulator I've been using) the stack pointer decreases and the code loops, but in ASM80.ORG the stack pointer doesn't decrease and the code halts like expected. – Michal Nemecek Dec 22 '18 at 10:38

1 Answers1

0

The emulator is inaccurate. it alters the stack when it executes a jp instruction, even though it shouldn't. I'll look for a different emulator. Don't use the ZEMU emulator.