我正在为基于x86的PC编写一个小型引导加载程序。问题是在执行这些指令后CPU仍以某种方式处于活动状态:
sti
hlt
sti 应该禁用下一条指令的中断
hlt 应该完全停止处理器
由于它们一起使用,我认为它们只会“冻结”计算机。但是当我组装它并将其作为软盘映像安装在VirtualBox中时,我的CPU会跳到100%。
我做错了什么?
答案 0 :(得分:13)
我想补充一条关于'cli'的评论,因为我过去曾经被这几次咬过。 'cli'指令不会阻止所有中断 - 它只会阻止可屏蔽的中断。可以想象,由于不可屏蔽中断(NMI),系统仍然可以被唤醒。
由于其中一条评论表明计算机已准备好关闭,我预计系统中没有其他线程/进程/任务可以运行(否则NMI可能会导致重新安排)。对于您描述的场景,NMI不太可能;但是,根据您对出错的偏执程度,您可能希望添加一个循环来防范这种可能性。
sysSuspend:
cli
hlt
jmp sysSuspend
答案 1 :(得分:11)
我认为你对这两个命令都有点困惑。
sti
命令启用中断,cli
命令禁用它们。
暂停状态类似于空闲循环,因此它不会挂起处理器。
以下是一些可能对您有所帮助的链接: 有关STI / CLI命令的信息:http://en.wikipedia.org/wiki/STI_%28x86_instruction%29
有关x86指令的信息:http://en.wikipedia.org/wiki/X86_instruction_listings
从这里可以找到可能有用的hlt
命令链接。
如果您暂停处理器,如果禁用中断,如何再次唤醒它?
答案 2 :(得分:5)
这个问题可以重新表述为更正确的问题:如何完全暂停控制流程? 实际上,此任务可以分为两个子任务:
暂停当前(同步)控制流程。
简单的繁忙循环(100%CPU使用率,大功耗,高热效应)。
基于停止的循环(省电模式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.