Assembly 6502汇编程序-RTS命令和堆栈
关于6502汇编语言,我必须回答以下问题: 在堆栈上,有以下值(首先是顶部元素):Assembly 6502汇编程序-RTS命令和堆栈,assembly,subroutine,6502,Assembly,Subroutine,6502,关于6502汇编语言,我必须回答以下问题: 在堆栈上,有以下值(首先是顶部元素):0x01、0x02、0x03、0x04、0x05、0x06 地址0xc000是指令jsr 0xABCD。在获取/执行周期后,哪个值将存储在程序计数器中,堆栈的顶部元素是什么?” 我知道程序计数器将是0xABCD,但我对堆栈元素感到困惑。我知道在6502体系结构中,堆栈从上到下增长(从0x01FF到0x0100)。因此,我假设堆栈指针指向元素0x01,对吗 现在,返回地址应该是程序计数器+3,因为有下一个命令,所以我
0x01、0x02、0x03、0x04、0x05、0x06
地址0xc000
是指令jsr 0xABCD
。在获取/执行周期后,哪个值将存储在程序计数器中,堆栈的顶部元素是什么?”
我知道程序计数器将是0xABCD
,但我对堆栈元素感到困惑。我知道在6502体系结构中,堆栈从上到下增长(从0x01FF
到0x0100
)。因此,我假设堆栈指针指向元素0x01
,对吗
现在,返回地址应该是
程序计数器+3
,因为有下一个
命令,所以我想说,0xc003
将被推到堆栈上,但以小端顺序,因此c0
将是顶部元素。这是正确的吗?我相信jsr上发生的是
stack[stack_pointer] = return_high
stack_pointer--
stack[stack_pointer] = return_low
stack_pointer--
pc = jsr address
因此,如果您声称堆栈指针指向0x01,0x02是较低/较小的地址,则0x01和0x02将被覆盖,当您点击子例程时,堆栈将指向0x03。从等于
$F9
的S
寄存器开始,这意味着$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
,调用者中下一条指令的第一个字节的地址。我将堆栈的起点(0x1ff)称为底部,0x100称为顶部。在LE机器中,一致性模型是将“03”存储在一个较小的地址中。只是一个警告:在6502中,JSR将(返回地址-1)推送到堆栈中。也就是说,RTS会在拉动后增加它。@cyco130这种设计背后有什么理由吗?我发现存储地址-1而不是下一条指令的实际地址是非常奇怪的,执行将从中继续。@BarbaraKwarc我没有一个明确的答案,我只能推测:我知道6502总是在每条指令的前两个周期获取两个字节。对于1字节的操作码,它会丢弃多余的一个,并且不会进一步增加PC(PC已经被增加以获取丢弃的第二个字节)。对于2字节操作码,它同时使用两个字节并增加PC。对于3字节操作码,它增加PC,获取最后一个字节,使用它,并再次增加PC。在JSR(一种3字节操作码)中,它必须在最后一次递增PC之前将程序计数器推送到堆栈中。是的,我猜递增PC是每个机器周期的最后一个阶段,硬编码,因此它无论如何都必须这样做(从堆栈中弹出后),为了补偿这一点,它将地址推送1(这并不难,如果它在最后阶段增加PC之前推动它)。但如果有一些官方文件支持,那就太好了。而且,条件跳转使用下一条指令的地址来计算偏移量,这一事实让我有点偏离了这一推测:qanswer将更清晰,有一个表…地址->值