Assembly 如何完全挂起处理器?

Assembly 如何完全挂起处理器?,assembly,x86,Assembly,X86,我正在为基于x86的PC编写一个小型引导加载程序。问题是CPU在执行以下指令后仍然处于活动状态: sti hlt sti应禁用下一条指令的中断 hlt应该完全停止处理器 因为它们是一起使用的,我想它们只是“冻结”电脑。但当我把它组装起来并作为软盘映像安装在VirtualBox中时,我的CPU会跳到100% 我做错了什么?我想您对这两个命令都有点困惑 sti命令启用中断,而cli命令禁用中断 暂停状态类似于空闲循环,因此不会暂停处理器 以下是一些可能对您有所帮助的链接: 有关STI/CLI命令的

我正在为基于x86的PC编写一个小型引导加载程序。问题是CPU在执行以下指令后仍然处于活动状态:

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

因为它们是一起使用的,我想它们只是“冻结”电脑。但当我把它组装起来并作为软盘映像安装在VirtualBox中时,我的CPU会跳到100%


我做错了什么?

我想您对这两个命令都有点困惑

sti
命令启用中断,而
cli
命令禁用中断

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

以下是一些可能对您有所帮助的链接: 有关STI/CLI命令的信息:

有关x86指令的信息: 这里有一个链接,指向可能会有所帮助的
hlt
命令


如果挂起处理器,如果禁用中断,如何再次唤醒它?

我想添加一条关于“cli”的评论,因为我在过去几次被它咬过。“cli”指令不会阻止所有中断——它只阻止可屏蔽的中断。可以想象,由于不可屏蔽中断(NMI),系统仍可能被唤醒

由于其中一条评论指出计算机已准备好关闭,我希望系统中没有其他线程/进程/任务准备好运行(否则NMI可能会导致重新调度)。对于您描述的场景,NMI不太可能出现;然而,根据你对事情出错的偏执程度,你可能希望添加一个循环来防止这种可能性

sysSuspend:
    cli
    hlt
    jmp sysSuspend

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

  • 暂停当前(同步)控制流

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

    • 基于Halt的环路(节能模式C1,大部分CPU逻辑未通电)

  • 防止控制流的异步切换

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

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

    • 在本地中断控制器(本地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.
    

    这可能是一个vbox错误:“是否有中断到达?是否有中断到达?是否有…”不是将禁用中断的cli指令吗?是的。我认为op可能有点混乱。这就是问题所在——电脑准备在那个时候关机。太好了。我用CLI指令替换了STI指令,现在它工作得很好!您应该使用ACPI而不是CLI+HLT关闭。这是完全停止PC的真正方法。并且功耗非常低(不像简单的循环)。值得注意的是:NMI中断无论如何都不允许发生,它表示一些严重的硬件问题,如内存奇偶校验错误,通常会导致
    HLT
    。所以,正如Sparky所说,循环只是偏执,但它是无害的。有趣的方法,但是。。是否真的需要在IDT中存根所有处理程序?
    CLI
    不应该这样做吗?另外,您忘记粘贴
    InstallHandlerInIDT
    函数;)您似乎误解了代码和解释。代码所做的是为NMI中断(IDT中的插槽0x2)安装空NMI_INT_HANDLER_存根处理程序,因为cli/sti机制禁用除NMI之外的所有中断。此步骤保证NMIs将无法从挂起状态撤回控制流。使用CLI指令可以有效地禁用剩余的中断。哦,我明白了。因此,存根仅用于插槽2,感谢您的解释。但是实际写入IDT的代码仍然缺失,对吗?我假设它由
    InstallHandlerInIDT
    函数表示