Assembly 为什么在0(SP)处传递的值仅在4(SP)处可用?

Assembly 为什么在0(SP)处传递的值仅在4(SP)处可用?,assembly,68000,easy68k,Assembly,68000,Easy68k,为什么在0(SP)处传递的值仅在4(SP)处可用?例如,我需要通过0(SP)而不是4(SP)(在例程中使用)将一个数字传递到printn,否则它将无法工作。我错过了什么 MOVE #12,D0 MOVE D0,0(SP) here I use 0 offset PRINTN: MOVE 4(SP),D1 |and here 4. Shoudln't be the same? MOVE #3,D0 TRAP #15 RTS

为什么在
0(SP)
处传递的值仅在
4(SP)
处可用?例如,我需要通过
0(SP)
而不是
4(SP)
(在例程中使用)将一个数字传递到
printn
,否则它将无法工作。我错过了什么

MOVE #12,D0
MOVE D0,0(SP)   here I use 0 offset

PRINTN:
        MOVE 4(SP),D1   |and here 4. Shoudln't be the same?
        MOVE #3,D0
        TRAP #15
        RTS

如果我们假设
PRINTN
是通过
JSR
/
BSR
获得的子例程,那么
JSR
的操作说明将回答您的问题:

SP – 4 → Sp; PC → (SP); Destination Address → PC

也就是说,返回地址现在位于堆栈的顶部,在
JSR
之前位于堆栈顶部的内容现在将位于
4(SP)
,依此类推。

根据您的代码,我猜PRINTN是子例程(函数、过程等),它是使用JSR调用的。如果是这样,您应该注意JSR的功能:它

  • 使SP减少4
  • 按SP中的地址将返回地址(JSR后的指令开头)放入内存
  • 将子例程地址(来自JSR指令)放入PC
因此,在此之后,所有超出SP的偏移量都将增加4。是的,0(SP)中的值从子程序中取为4(SP),28(SP)应以相同的方式替换为32(SP),依此类推。RTS则相反,它将SP增加4

而且,每次推送和弹出都会改变它;若在堆栈上保存2个寄存器,在这些推送之后,所有偏移量将额外增加8,直到执行相应的POP。这很容易被编译器跟踪,但更难被人类跟踪;例如,这将是x86在SP之外发明BP的另一个理由