如何完全暂停处理器?

Nat*_*man 7 x86 assembly

我正在为基于x86的PC编写一个小型引导加载程序.问题是在执行这些指令后CPU仍以某种方式处于活动状态:

sti
hlt
Run Code Online (Sandbox Code Playgroud)

sti应该禁用下一条指令的中断
hlt应该完全停止处理器

由于它们一起使用,我认为它们只会"冻结"计算机.但是当我组装它并将其作为软盘映像安装在VirtualBox中时,我的CPU会跳到100%.

我究竟做错了什么?

Spa*_*rky 13

我想补充一条关于'cli'的评论,因为我过去曾经被这几次咬过.'cli'指令不会阻止所有中断 - 它只会阻止可屏蔽的中断.可以想象,由于不可屏蔽中断(NMI),系统仍然可以被唤醒.

由于其中一条评论表明计算机已准备好关闭,我预计系统中没有其他线程/进程/任务可以运行(否则NMI可能会导致重新安排).对于您描述的场景,NMI不太可能; 但是,根据您对出错的偏执程度,您可能希望添加一个循环来防范这种可能性.

sysSuspend:
    cli
    hlt
    jmp sysSuspend
Run Code Online (Sandbox Code Playgroud)

  • 值得注意的是:NMI 中断无论如何都不会发生,它表示一些严重的硬件问题,例如内存奇偶校验错误,并且通常会导致“HLT”。所以,正如 Sparky 所说,循环只是偏执,但它是无害的。 (3认同)

Jam*_*ack 12

我觉得你对这两个命令都有点困惑.

sti命令启用中断,cli命令禁用它们.

暂停状态类似于空闲循环,因此它不会暂停处理器.

以下是一些可能对您有所帮助的链接:有关STI/CLI命令的信息:http://en.wikipedia.org/wiki/STI_%28x86_instruction%29

有关x86指令的信息:http://en.wikipedia.org/wiki/X86_instruction_listings 这里有一个指向hlt可能有用的命令的链接.

如果您暂停处理器,如果禁用中断,如何再次唤醒它?

  • 您应该使用ACPI而不是CLI + HLT关闭. (6认同)
  • 这就是重点 - 计算机已准备好在此时关闭. (3认同)
  • 完善.我用CLI替换了STI指令,它现在运行得很好! (2认同)

Zar*_*trA 6

这个问题可以重新表述为更正确的问题:如何完全暂停控制流?实际上,此任务可以分为两个子任务:

  1. 暂停当前​​(同步)控制流。

    • 简单的繁忙循环(100%CPU使用率,大功耗,高热效应)。

    • 基于暂停的循环(省电模式C1,大多数CPU逻辑不通电)。

  2. 防止控制流的异步切换。

    • IDT中的存根中断处理程序。

    • 全局中断控制器(PIC或IO APIC)上的中断屏蔽。

    • 在本地中断控制器(Local APIC)上屏蔽中断。

    • 屏蔽CPU核心逻辑上的中断。

无论如何,您必须了解并准备好NMI处理,因为没有机制可以使您禁用它们。

理想的解决方案:

    mov  EDX, NMI_INT_HANDLER_STUB; // address of installed handler
    mov  ECX, 0x02                ; // id of the NMI handler in IDT 
    call InstallHandlerInIDT      ; 
    cli                           ; // mask all maskable interrupts on CPU core
SUSPEND:
    hlt                           ; // turn CPU into HALT state (power saving mode C1)
    jmp SUSPEND                   ; // try again if NMI had happened

NMI_INT_HANDLER_STUB:
    iretd                         ; // Complete handling immediatelly and return back.
Run Code Online (Sandbox Code Playgroud)