0

I am trying to design a board for a Z80 based computer, and am having trouble designing the memory map. I have found that the Program Counter defaults to address #0000, but I cannot find where the Stack Pointer defaults to. Is it also #0000? Am I just supposed to set it to whatever I want on startup?

Thank you.

Z80 Datasheet

LukeIsMe
  • 1
  • 2
  • 1
    Yes, you set it yourself before you do any operations that require the stack, such as calling subroutines. – Dave Tweed Mar 09 '20 at 19:01

4 Answers4

4

You would normally set the stack pointer at the start of your program.

I think the usual initial value for the stack pointer would be the top of available RAM (but its a long time since I used an 8085/Z80 style microprocessor).

Peter Bennett
  • 57,014
  • 1
  • 48
  • 127
  • 3
    According to [The Undocumented Z80 Documented](http://www.z80.info/zip/z80-documented.pdf) the stack pointer is set to FFFF on power up, but this is undocumented. – Bruce Abbott Mar 09 '20 at 20:33
1

Here is a simple piece of Z80 code startup:

; Example for 32K system...
RAM_END         equ 8400h                   ; Last byte is actually 83ffh.

; Start here on power up/reset.
;
        org 0
RST0:   ld sp,RAM_END   ; Stack at the end of ram.
        jp START
        db 0, 0         ; Filler bytes...

RST8:   db 0, 0, 0, 0, 0, 0, 0, 0

RST10H: db 0, 0, 0, 0, 0, 0, 0, 0

RST18H: db 0, 0, 0, 0, 0, 0, 0, 0

RST20H: db 0, 0, 0, 0, 0, 0, 0, 0

RST28H: db 0, 0, 0, 0, 0, 0, 0, 0

RST30H: db 0, 0, 0, 0, 0, 0, 0, 0


; Mode 1 Interrupt handler.
; 
RST38H:
    di              ; Disable interrupts.
                    ; Do interrupt stuff here.
    ei              ; Enable interrupts.
    reti

    db  (0066H-$) dup (0)

; Non-maskable interrupt handler (NMI).
;
    org 0066H
NMIINT:
    ; Do NMI stuff here.
    retn

; Main monitor start,
;
START:
    im 1            ; Interrupt mode 1.
    ei              ; Enable interrupts.
    ...

Notes:

  • Stack pointer is set to end of RAM (address is always even, 1 greater than actual last address as SP is always decremented just before push).

  • After setting up stack we jump to actual start (we skip all the area we may want to use for software restarts).

  • I've also added some default code for mode 1 interrupt and NMI handling.

  • At start I set interrupt mode and enable interrupts.

So, after this code I have the stack setup, basic interrupt setup etc. It's a good idea to go and look for code examples of actual Z80 monitors etc.

ttt
  • 658
  • 1
  • 6
  • 10
0

Doesn't the stack pointer, among other CPU registers like PC,..reside in CPU?

But if you are asking to which address the stack pointer is pointing at, then is a different story. Don't know about Z80, but usually it points to the top off the available memory e.g. -1 (FFFF) and it decrements, it makes sense since you are loading static variables from bottom to the top , then the CPU can't create a stack and then clear it in the middle of allocated variables or program (von Neuman). So the only way to make a stack on top of the stack, on top of the stack.... is to store variables from top down, until the stack grows so it "touches" the allocated data on bottom - this is so called stack overflow. The stacks are built up at every function call and then nested function calls, it is purged in the reverse order.

EDIT: Swapped bottom and top.

enter image description here

Marko Buršič
  • 23,562
  • 2
  • 20
  • 33
0

The stack pointer is unknown at reset, it must be set as part of your program. Generally it is the first instruction in the code. The reason for this is if it gets an interrupt (yes the NMI) it will go off into the weeds as it has no valid address to return to. It is a pre decrement so the first stack write will be at one address less then the existing stack pointer value. Set it one above your existing high RAM address, if it is 0xFFFF then set it to zero as it is a 16 bit register and will roll back to 0xFFFF for the first write. You can push the stack pointer, pop it into HL (or others) so you can determine its value.

The lower addresses starting at zero are "special" they are for the interrupt vectors. Normally address zero contains the address of the first instruction of your program. If my memory is correct 0-0xFFH are reserved for the vector table. Peripherals can also jam an interrupt on the bus, depends on configuration.

There were several versions of the Z80 starting with Zylog, NEC (upd780) and many others. They were not all exactly the same. Another quirk is most use one less clock cycle to fetch an operand, can cause timing problems if not expected.

Gil
  • 4,951
  • 2
  • 12
  • 14