I wrote a new monitor ROM for the Z80, called umonz, which can provide some basic monitor functionality even if there is no working RAM. In other words, it doesn't use a stack or store any variables in RAM. It supports reading and writing memory, I/O ports, and loading and dumping Intel hex format.
https://github.com/brouhaha/umonz It's tricky to write any non-trivial Z80 code without a stack. I used IX and IY as subroutine return address registers, allowing two levels of subroutines, though a subroutine that uses IX can't call another subroutine using IX, and similarly for IY. The background is that John Doran built a custom Z80 (equivalent) computer system which he calls the Z80/M. It doesn't use an actual Z80 CPU; there is an Altera (now Intel) MAX 10 FPGA on the control panel board, and a Z80-equivalent core, along with the front panel logic, is in the FPGA. There is a 16-slot expansion bus using 96-pin DIN 41612 connectors. The cards are Eurocard 3U x 220mm. https://www.flickr.com/photos/_brouhaha_/52032832163/in/album-72177720298429134/ There's an expansion card that provides 512K of flash, 512K of SRAM, page mapping, a Z80 SIO for two serial ports, and a CF card, all compatible with the equivalent RC2014 cards. He expected that ROMWBW and CP/M or ZSystem would "just work". However we had to track down several minor hardware design issues to get it to work. After writing a few simple one-off test programs, I got tired of the assemble, sneakernet, program flash chip, test in target loop, so I decided to write a monitor. That definitely sped up the debug process.