我必须回答以下关于6502汇编语言的问题:
“在堆栈上,有以下值(顶部元素在前):
0x01, 0x02, 0x03, 0x04, 0x05, 0x06
地址0xc000
处是指令jsr 0xABCD
。在获取/执行周期之后哪个值将存储在程序计数器中以及堆栈的顶部元素是什么?”
我知道程序计数器将是
0xABCD
,但我对堆栈元素感到困惑。我知道在6502架构中,堆栈是从顶部到底部增长的(从0x01FF
到0x0100
)。所以,我假设,堆栈指针指向元素0x01
,对吗?
现在,返回地址应该是
program counter + 3
,因为有next
命令,所以我想说,0xc003
将被压入堆栈,但是按照小端顺序,所以c0
将是顶部元素。这是正确的吗?
从
S
寄存器等于 $F9
开始,这意味着 $0100
页面中之后的所有内容都是堆栈。内存内容如下:
$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
JSR
指令压入该指令的最后一个字节的地址。在这种情况下,最后一个字节的地址是$C002
。先压入高字节,使低字节位于低地址:压入$C0
,然后压入$02
,然后跳转到$ABCD
。之后,堆栈看起来像这样,顶部是小端字节顺序的$C002
,S
变成了$F7
。
$01F8: 02 C0 01 02 03 04 05 06
$ABCD
处的子程序将以RTS
指令结束,如$AC03
所示。该指令拉取程序计数器的低字节和高字节。然后因为返回地址指向上一条指令的最后一个字节,所以它加1。 $C002
加一就是$C003
,调用者中下一条指令的第一个字节的地址。
我相信 jsr 上发生的事情是
stack[stack_pointer] = return_high
stack_pointer--
stack[stack_pointer] = return_low
stack_pointer--
pc = jsr address
因此,如果您声称堆栈指针指向 0x01,而 0x02 是较低/较小的地址,那么 0x01 和 0x02 将被覆盖,当您执行子例程时,堆栈将指向 0x03。
我很确定这就是它的工作原理:
首先获取到子程序的距离。如果是向后的,它就会通过非门。然后,它递减该数字并将其推入堆栈,并向上或向下移动那么远。当你想返回时,它从堆栈中取出,递增并移回起点,然后继续程序。
例如:
jsr do_stuff
brk
do_stuff:
lda #$00
rts
首先我们向前跳转
02
,并将 01
(02
- 1) 压入堆栈。然后我们lda #$00
。当我们 rts
时,我们从堆栈中取出 01
,向其添加 1 (02
),然后跳回那么远。现在我们退出。