真正的指令集,但没关系,并且对这个真正的指令如何工作不感兴趣,它将用于演示问题。
2000: 0b 12 push r11
2002: 3b 40 21 00 mov #33, r11
2006: 3b 41 pop r11
2008: 30 41 ret
正如前面提到的,在谈论程序计数器时有一个时间概念。
超级简单的处理器,老的8位,其他的都可以这样想,新的就不一样了。
当我们输入此代码时,无论我们到达这里,都没有关系。程序计数器
是 0x2000。这告诉我们从哪里获取指令,我们必须获取它,解码它,然后执行它,重复。
这些是 16 位指令,两个字节,处理器从 pc 指向指令开始获取指令的地址。处理器读取地址 0x2000 (0x0b) 的两个字节,处理器将程序计数器递增到 0x2001,并使用它来获取地址 0x2001 (0x12) 处的指令的后半部分,并将程序计数器递增到 0x2002。因此,对于这里的每个提取,我们将其称为组成处理器,我正在描述您使用程序计数器作为地址提取的每个提取,然后递增程序计数器。
before data after
0x2000 0x0b 0x2001
0x2001 0x12 0x2002
所以现在我们解码指令,程序计数器当前显示0x2002,我们看到这是一个push r11,所以我们继续执行。
在执行该指令期间,程序计数器保持为 0x2002。寄存器 r11 的值被压入堆栈。
现在我们开始获取下一条指令。
before data after
0x2002 0x3b 0x2003
0x2003 0x40 0x2004
当我们解码这条指令 (pc == 0x2004) mov #immediate,r11 时,处理器意识到这条指令需要一个立即数,因此它需要再获取两个字节
before data after
0x2004 0x21 0x2005
0x2005 0x00 0x2006
它已经确定它现在可以通过将值 0x0021 写入寄存器 r11 来执行指令(小端序 0x0021 = 33decimal)。在执行期间,该指令的程序计数器为 0x2006。
下一个
before data after
0x2006 0x3b 0x2007
0x2007 0x41 0x2008
解码并执行 pop r11
因此您可以开始看到程序计数器实际上包含至少两个值。在获取之前的指令开始时,它包含指令的地址,在我们开始执行之前获取和解码之后,它包含该指令之后的字节的地址,如果这不是跳转,则是另一条指令。如果这是一个无条件跳转
字节可能是一条指令或一些数据,或未使用的内存。但是我们说
它“指向下一条指令”在这种情况下意味着在执行之前
该指令后面的地址通常有另一条指令。但正如我们接下来将看到的,PC 可以通过指令进行修改。但总是在END
它指向的执行(对于这个简单的处理器,它类似于
一些简单的 8 位处理器)到要执行的下一条指令。
最后
before data after
0x2008 0x30 0x2009
0x2009 0x41 0x200A
解码一个 ret,现在这个问题就问题而言是特殊的,因为 ret 将在执行期间根据该处理器的规则修改程序计数器。如果调用地址 0x2000 的指令是 0x1000 并且它是一个两字节指令,那么在获取和解码期间程序计数器将位于地址 0x1002,在执行期间,地址 0x1002 将根据该指令集的规则存储在某处,并且程序计数器将采用值 0x2000 来调用此子例程。当我们到达 ret 指令并开始执行它时,我们开始执行 ret,程序计数器包含 0x200A 但 ret 将指令的地址放在调用之后,即在调用执行期间存储的值,所以在在这条指令的结尾,程序计数器将包含值 0x1002,下一次取指将来自该地址。
因此,在执行前的最后一条指令中,pc 指向的内容
通常是不分支或跳转的指令的下一条指令或
称呼。 0x200A。但是在执行期间程序计数器已更改,因此
“下一条”指令是我们到达这里的呼叫之后的指令。
更多
c064: 0a 24 jz $+22 ;abs 0xc07a
c066: 4e 5e rla.b r14
在获取 pc 之前是 0xC064。获取和解码后,PC 为 0xC066。指令说如果 zerp 跳转到 0xc07a。因此,如果未设置零标志,则 pc 将停留在 0xC066,这是它开始下一条指令的地方,但如果 z 是
设置然后 pc 被修改为 0xc07a ,这是下一条指令
执行将。所以在 0xc064 之前 0xc066 或 0xc07a 之后取决于。
一条指令的后面是下一条指令的前面。
无条件跳转
c074: c2 4d 21 00 mov.b r13, &0x0021
c078: ee 3f jmp $-34 ;abs 0xc056
在获取0xc07a之前,执行之前0xc07A之后执行0xc056
对于那条指令,pc 至少保存了三个值(如果获取一个字节
一次然后它保持 0xc078、0xc079、0xc07a 并以 0xc056 结束)期间
一条指令。
是的,它可以并且确实保存多个值,但不能同时保存一个值,在指令的各个阶段一次一个值。