从Does the program counter always have to change (upon a clock tick)?开始,我已经知道PC不需要在每个时钟进行更改;因为特定指令可能需要多于一个时钟滴答才能执行。
我想进一步提出这个问题。假设我们有以下简单的C代码:
// gcc -g min.c -o min.exe # generate executable
// gcc -S min.c -o min.s # generate assembler listing from source
// objdump -S min.exe > min.sdump # generate assembler listing from executable
int main() {
int a;
a = 15;
return a;
}
通过比较汇编程序列表(objdump -S
并不总是非常准确地散布源代码行),我得到这样的结论:
min.s: min.sdump:
--------------------- -------------------------
main: 08048394 <main>:
pushl %ebp 8048394: 55 push %ebp
movl %esp, %ebp 8048395: 89 e5 mov %esp,%ebp
subl $16, %esp 8048397: 83 ec 10 sub $0x10,%esp
movl $15, -4(%ebp) 804839a: c7 45 fc 0f 00 00 00 movl $0xf,-0x4(%ebp)
movl -4(%ebp), %eax 80483a1: 8b 45 fc mov -0x4(%ebp),%eax
leave 80483a4: c9 leave
ret 80483a5: c3 ret
.size main, .-main 80483a6: 90 nop
我知道这很可能是错误的 - 但让我们假设单字节指令需要一个时钟滴答,其他指令需要两个。然后,我可以将“指令标记”作为“前一个”命令完成后的时钟上升沿;如下面的时序图所示(对应于反汇编列表;可以找到图像的Latex / Tikz代码here):
所以用原来的问题来解释:
... PC(程序计数器)是否总是必须更改(每次新指令时)? 我在想,如果一条指令设置了PC(或者更确切地说是下一台PC),那么下一个执行地址与它当前的地址相同,就没有办法退出该循环(当然除非有一些外部中断)?
答案 0 :(得分:1)
你所描述的是一个无限循环 - 例如通过跳到自身PC基本上“保持不变”并且永不退出 - 除了一些外部事件(如关闭计算机或外部引发中断......) 。 PC是否在技术上/间歇性地改变取决于特定处理器如何实现所使用的指令......
答案 1 :(得分:1)
所以这个小程序可以满足你的要求:
int main(){
loop: goto loop;
}
它编译成这样的东西:
.L3:
jmp .L3
效果是,当从外面看时,PC将保持不变。在内部,硅将在一步中执行类似的操作:
PC = argument of JMP
PC将被设置,但总是与当前值相同。
修改
目前尚不清楚你对“锁定”究竟是什么意思。 每个无限循环将占用CPU资源,并且如果禁用中断将不会中断。无论PC是否发生变化,这都无关紧要。上面的循环只是可能的最小紧密循环。
但是:在实际系统上有 ARE 中断 - 在每个值得这两个字母的操作系统上,调度程序将被定时器中断唤醒并将CPU提供给下一个处理。即使在通常没有“操作系统”的微控制器上,也会在每个非平凡的情况下使用内部和外部中断。事实上 - 上面的紧密循环在微控制器上并不罕见 - 主要工作完成后,CPU进入紧密循环并等待下一个中断。中断会以某种方式打破循环。
请注意,在实际操作系统上,仅仅用户空间程序无法直接控制中断,原因如下:否则任何愚蠢的程序都可能会使用一个汇编程序命令关闭系统。 / p>