user66875
user66875

Reputation: 2618

6502 Assembler - The RTS command and the stack

I have to answer the following question about the 6502 assembly language:

"On the stack, there are the following values (top element first): 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 At address 0xc000 is the instruction jsr 0xABCD. Which value will be stored in the program counter after the fetch/execute cycle and what will be the top element of the stack?"

I know that the program counter will be 0xABCD, but I'm confused about the stack elements. I know that in the 6502 architecture, the stack grows from the top to the bottom (from 0x01FF to 0x0100). So, I assume, the stack pointer is pointing to the element 0x01, right?

Now, the return address should be program counter + 3, because there is the next command, so I would say, 0xc003 will be pushed on the stack, but in little endian order, so c0 will be the top element. Is that correct?

Upvotes: 4

Views: 4032

Answers (3)

Miro
Miro

Reputation: 1

I'm pretty sure that this is how it works:

First it takes the distance to the subroutine. If it's backwards, it puts it through a not gate. It then decrements and pushes that number to the stack, and moves up or down that far. When you want to return, it pulls from the stack, increments and moves back to the starting point and then continues the program.

For example:

jsr do_stuff
brk

do_stuff:
  lda #$00
  rts

First we jump forward 02, and push 01 (02 - 1) to the stack. We then lda #$00. When we rts we pull 01 from the stack, add 1 to it (02), then jump back that far. And now we exit.

Upvotes: -2

Damian Yerrick
Damian Yerrick

Reputation: 4664

Start with the S register equal to $F9, meaning everything after that in the $0100 page is the stack. Memory contents are as follows:

$01FA: 01 02 03 04 05 06

$ABCD: A6 23       LDX $23
; rest of the body of the subroutine
$AC03: 60          RTS

$C000: 20 CD AB    JSR $ABCD
$C003: BD 40 06    LDA $0640,X

The JSR instruction pushes the address of the last byte of the instruction. In this case, the address of the last byte is $C002. The high byte is pushed first so that the low byte is in the lower address: push $C0, then push $02, then jump to $ABCD. After this, the stack looks like this, with $C002 in little-endian byte order at the top, and S has become $F7.

$01F8: 02 C0 01 02 03 04 05 06

The subroutine at $ABCD will end with the RTS instruction, here shown at $AC03. This instruction pulls the low and high bytes of the program counter. And then because the return address points at the last byte of the previous instruction, it adds 1. $C002 plus one is $C003, the address of the first byte of the next instruction in the caller.

Upvotes: 9

old_timer
old_timer

Reputation: 71576

I believe what happens on a jsr is

stack[stack_pointer] = return_high
stack_pointer--
stack[stack_pointer] = return_low
stack_pointer--
pc = jsr address

so if you are claiming that your stack pointer is pointing at the 0x01 and 0x02 is a lower/smaller address then 0x01 and 0x02 will be overwritten and when you hit your subroutine the stack will be pointing at 0x03.

Upvotes: 1

Related Questions