Stack instructions interfering with Subroutines and RTS??

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Stack instructions interfering with Subroutines and RTS??
by on (#196320)
So I've been having trouble implementing subroutines because of this strange problem. Supposedly its implied that the stack shouldn't be written to during subroutines, right? Since JSR writes the address of the next instruction to the stack and RTS reads that address to return, the stack shouldn't be written to, or should be trimmed so that the net effect is that the address written by JSR is at the top of the stack by the end of the subroutine. At least, this is what I'm assuming. Below are the instructions in the subroutine, and as you can see, several instructions push to the stack, but none pop off it except for RTS. After each instruction that changes the stack, I'll list an output of the stack at that point.

JSR cbaa abs
[200, 7]
LDA 00 imm
STA 04 zp
LDA ff imm
JMP f0a1 abs
STA 03 zp
LDA 0f imm
PHA
[15, 200, 7]
STA 0f zp
TXA
PHA
[255, 15, 200, 7]
TYA
PHA
[0, 255, 15, 200, 7]
LDA 00 zp
PHA
[0, 0, 255, 15, 200, 7]
LDA 05 zp
PHA
[0, 0, 0, 255, 15, 200, 7]
LDA 06 zp
PHA
[0, 0, 0, 0, 255, 15, 200, 7]
LDA 07 zp
PHA
[0, 0, 0, 0, 0, 255, 15, 200, 7]
LDA 08 zp
PHA
[0, 0, 0, 0, 0, 0, 255, 15, 200, 7]
LDA 09 zp
PHA
[0, 0, 0, 0, 0, 0, 0, 255, 15, 200, 7]
LDA 02 imm
STA 05 zp
LDA 0f zp
CMP 04 imm
BEQ 36 imm
LDA 0f imm
AND 03 zp
STA 07 zp
LDA 03 zp
LSR acc
LSR acc
LSR acc
LSR acc
STA 06 zp
TAX
LDA 00 imm
CLC
ADC 07 zp
DEX
BNE fb imm
STA 08 zp
LDA 0f zp
BNE 06 imm
ISC aea5 abs
CLC
ADC 01 imm
ASL acc
ASL acc
ASL acc
ASL acc
TAX
RTS

The initial address that was written to the stack is blocked by a bunch of values, and the program can't get to it. Can someone help?
Re: Stack instructions interfering with Subroutines and RTS?
by on (#196321)
It's possible to push a new return address manually, and pretty much every NES game I've ever written does that at least once.

But the presence of unofficial instruction ISC hints that something probably went wrong in the disassembly or in the emulation of code prior to this: memory address $000F is zero when it shouldn't have been. And how did value $00 get into X, Y, $0000, and $0005-$0009? From which program is this disassembled?
Re: Stack instructions interfering with Subroutines and RTS?
by on (#196323)
tepples wrote:
From which program is this disassembled?


I'm testing using the Japanese version of Donkey Kong. What makes you say that $000f shouldn't be zero?

This code comes from the very beginning of the ROM during the startup procedure, before a frame has even passed. So if $000f isn't 0, it's probably a startup assignment, yet I haven't seen that specific address being set in the documentation, as $0000-$0100 is general RAM, right?

Here's all the codes I've disssasembled to this point: https://pastebin.com/XNiTFmaD
I know for certain that the beginning is correct, at least. Let me know where I screwed up.
Re: Stack instructions interfering with Subroutines and RTS?
by on (#196324)
Not to be rude, but is there no reason that you can't trace the execution of this code in another emulator to find that out for yourself?
Re: Stack instructions interfering with Subroutines and RTS?
by on (#196342)
Your disassembly syntax is very non-standard, and the lack of addresses for each instruction makes it even harder to follow. Nevertheless, I've compared your output with a disassembly of the ROM and managed to work out where you're going wrong:

Code:
BNE 06 imm
ISC aea5 abs


This branch is incorrectly jumping backwards instead of forwards, into the middle of an instruction (that's why it's hitting an unofficial opcode) in a totally different routine. The operand of a branch instruction is a signed displacement. if it's between $00 and $7F it's a forward branch, if it's between $80 and $FF it's a backward branch. Your code is incorrectly turning a forward branch by 6 into a backwards branch by (6 - 256).
Re: Stack instructions interfering with Subroutines and RTS?
by on (#196343)
Ah, thanks for that. Will fix now!
Re: Stack instructions interfering with Subroutines and RTS?
by on (#196344)
AWJ wrote:
if it's between $00 and $7F it's a forward branch, if it's between $80 and $FF it's a backward branch.


Just to be clear, $80 is -127 and $FF is -1, right?
Re: Stack instructions interfering with Subroutines and RTS?
by on (#196345)
$80 is -128. There's no negative zero, so the negative range gets 1 extra unit compared to the positive range, which only goes up to 127.
Re: Stack instructions interfering with Subroutines and RTS?
by on (#196355)
This way of storing numbers is known as "two's complement", if you're interested in reading more:
Wikipedia article: Two's complement

Most signed integer number formats use two's complement, so understanding it is good general knowledge for computer sceience.