Stack instructions interfering with Subroutines and RTS??

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

Post Reply
PolarBITS
Posts: 21
Joined: Mon May 01, 2017 4:11 pm

Stack instructions interfering with Subroutines and RTS??

Post by PolarBITS »

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?
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Stack instructions interfering with Subroutines and RTS?

Post by tepples »

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?
PolarBITS
Posts: 21
Joined: Mon May 01, 2017 4:11 pm

Re: Stack instructions interfering with Subroutines and RTS?

Post by PolarBITS »

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.
adam_smasher
Posts: 271
Joined: Sun Mar 27, 2011 10:49 am
Location: Victoria, BC

Re: Stack instructions interfering with Subroutines and RTS?

Post by adam_smasher »

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?
AWJ
Posts: 433
Joined: Mon Nov 10, 2008 3:09 pm

Re: Stack instructions interfering with Subroutines and RTS?

Post by AWJ »

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: Select all

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).
PolarBITS
Posts: 21
Joined: Mon May 01, 2017 4:11 pm

Re: Stack instructions interfering with Subroutines and RTS?

Post by PolarBITS »

Ah, thanks for that. Will fix now!
PolarBITS
Posts: 21
Joined: Mon May 01, 2017 4:11 pm

Re: Stack instructions interfering with Subroutines and RTS?

Post by PolarBITS »

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?
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Stack instructions interfering with Subroutines and RTS?

Post by tokumaru »

$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.
User avatar
rainwarrior
Posts: 8732
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Stack instructions interfering with Subroutines and RTS?

Post by rainwarrior »

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.
Post Reply