2 assembly interrupt cpu-architecture
子例程由程序指令调用以执行调用程序所需的功能。而中断是由输入操作或硬件错误等事件启动的。但处理器如何区分它们呢?
为了补充其他好的答案,我将更多地讨论函数调用与中断的逻辑相似性,以及它们的不同之处。
\n从逻辑角度来看,子例程或函数调用会挂起当前正在执行的调用方,并将控制权转移给 sub/func。\xc2\xa0 当该 sub/func 完成时,它将控制权返回给调用方,并在调用后恢复。
\n这是从逻辑角度来看 \xe2\x80\x94 然而,就硬件而言,没有暂停或恢复或从调用者到被调用者的控制权转移 \xe2\x80\x94 只是机器的连续执行流碰巧包含各种分支指令的代码指令,例如call(jal例如在 MIPS 上)和ret(jr)
从调用者到被调用者的控制权转移发生在非常受控的情况下 \xe2\x80\x94 这很大程度上取决于软件协议、ABI 和 ABI 中指定的调用约定。\xc2\xa0 调用者和被调用者,通过软件约定有事先商定如何传递参数、传回返回值,以及哪些寄存器可供被调用者自由破坏,哪些寄存器如果使用,则必须在返回时保留/恢复。\xc2\xa0 将控制权从调用者转移到被调用者发生在调用站点和返回站点,它们在程序控制下 \xe2\x80\x94 它们作为程序执行指令的结果同步发生。
\n当中断发生时,它可能发生在任何两条指令 \xe2\x80\x94 之间,因此对于其中一条来说,没有“调用约定”来管理从用户代码(被中断的内容)到异常的传输handler.\xc2\xa0 对于外部中断,异常处理程序不完全理解被中断的代码(被中断的代码不会尝试对操作系统进行同步调用)。\xc2\xa0 在这种情况下,所有处理器状态(例如寄存器)都必须在中断代码中被假定为忙/正在使用,该代码基本上已通过将控制权转移到异常处理程序而被强制挂起。
\n外部中断不会将值返回到被中断的代码\xe2\x80\x94,它们会更改操作系统状态(设备状态),这可能会使其他一些进程从阻塞状态变为可运行状态。
\n由于外部中断可能发生在任意两条指令之间(与软件可以看到暂停/恢复点的调用不同),为了使线程可恢复,(与函数调用相比)需要保留更多的处理器状态,以防万一被中断的线程稍后应该读取该状态。
\n尽管现代硬件在任何时间点都有许多正在运行的指令,但它必须保留中断发生在两个(动态)相邻指令之间的错觉。\xc2\xa0 在某种程度上,这是为了它可以指示程序中断程序内的计数器/指令指针,用于恢复它。
\n由于外部中断,操作系统的状态会发生变化。\xc2\xa0 由于这些变化,操作系统在从中断返回时可能会选择恢复与中断线程不同的线程(甚至在另一个进程中) ,使被中断的线程处于挂起状态以供稍后恢复。\xc2\xa0 通过这种方式,可能会发生线程的调度和交错,这与函数调用和函数返回调用者有本质上的不同(从逻辑上讲)。\xc2\xa0 (一些用户级系统具有协程和纤程,它们表现出控制权的转移,而不是从调用者到被调用者并返回。)
\n总之,函数调用是在程序的控制下完成的,仅在受控点上完成,并通过软件调用约定和某些用户模式调用和返回指令来促进。\xc2\xa0 但是,要明确的是,调用和返回是可以完成的没有这些专用的调用和返回指令(它们可以毫无困难地通过替代指令序列进行模拟)。 \xc2\xa0 而外部中断是由向处理器发出信号的外部设备触发的,可能会发生在中断代码中的任何两条指令之间,部分原因是它们涉及特权更改,需要特权指令才能从中断和暂停中恢复,这很难或不可能用其他常规指令进行模拟。
\n