4

I am learning WIN32 ASM right now and I was wondering if there is something like an "idle" infinite loop that doesn't consume any resources at all. Basically I need a running process to experiment with that goes like this:

loop:
  ; alternative to sleep...
  jmp loop

Is there something that may idle the process?

Ben
  • 3,380
  • 2
  • 44
  • 98
  • 2
    How about rep; nop;? `sleep()`, `sched_yield()` etc. are system calls that ask OS to execute something else. You can do those calls in assembler. But those are not really some instructions to CPU to do nothing, but are higher level stuff. –  Feb 01 '13 at 22:06
  • By "idle the process" do you mean yield the CPU to another process? – David Schwartz Feb 01 '13 at 22:10
  • 1
    TerminateProcess() is a good way to stop executing instructions. Writing infinite loops is not, nor is there an obvious use in doing so. The HLT instruction is only usable by privileged code. – Hans Passant Feb 01 '13 at 22:12
  • With an idle "Windows" process I mean that the process has started (through the EntryPoint) but it just stays idle in the infinite loop. Without anything between the loop the CPU raises because it waits for input?! Sleep would be perfect to solve this but I don't want to depend on the Windows API. – Ben Feb 01 '13 at 22:13
  • Depending on how the type of input and how you are waiting for it, the O/S will almost certainly put the process to sleep until there's input to the process. – Nik Bougalis Feb 01 '13 at 22:27
  • 3
    Hate to ask the obvious question but ... doesn't sleep do exactly what you seem to want from your comments on the answers? You want the core to do other stuff or be completely idle for a bit and then you want control back. That's what `Sleep` does. Why are you looking for an alternative? What's the issue? – David Schwartz Feb 01 '13 at 22:27
  • 1
    This is not a good use for assembly language. You use assembly language when you think you can do a better job than the compiler, usually trying to make something go faster. There is no need for speed when your goal is to do nothing. – amdn Feb 01 '13 at 22:32
  • There is no issue. I would just like to know if there is an alternative which would be also independent from an OS. – Ben Feb 01 '13 at 22:32
  • 3
    @BenjaminWeiss: Then the answer is no. You want the OS to schedule another thread to run on the CPU if one is ready-to-run or to put the core to sleep temporarily *only* if there is no other work the OS could have that core do. That clearly requires invoking the OS since only the OS scheduler knows what other work that core might be able to do at any particular time and only the OS can arrange an interrupt to wake the core out of sleep. And this is specifically and precisely what `Sleep` does. – David Schwartz Feb 01 '13 at 22:34
  • Alright. That's all I wanted to know, thank you. I understand that sleep reschedule between threads/processes. I didn't know that sleep is such an OS dependent call. – Ben Feb 01 '13 at 22:37

5 Answers5

6

You can't have it both ways. You can either consume the CPU or you can let it do something else. You can conserve power and avoid depriving other cores of resources with rep; nop; (also known as pause), as Vlad Lazarenko suggested. But if you loop without yielding the core to another process, at least that virtual core cannot do anything else.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • I tried that, but it still eats 25% of my entire CPU. (25% because I have a QuadCore?!) – Ben Feb 01 '13 at 22:19
  • 3
    @BenjaminWeiss: Do you want the core to do something else other than run your code? Or not? There's no third alternative. If that core is running your code, it can't do anything else. Thus one of your four cores is used, 25%. – David Schwartz Feb 01 '13 at 22:23
  • I want the process to consume almost 0% of the CPU. The WINAPI Call Sleep pauses the process (maybe even suspend the current running thread). I would like to have an alternative. – Ben Feb 01 '13 at 22:30
  • 1
    @BenjaminWeiss: I don't follow. Sleep does *precisely* what you want. An alternative would be inferior or, at best, no worse. Why do you want an alternative? – David Schwartz Feb 01 '13 at 22:31
3

Note: You should never use empty loops to make the application idle. It will load your processor to 100%

There are several ways to make the application idle, when there is no GUI activity in Win32 environment. The main (documented in MSDN) is to use "GetMessage" function in the main loop in order to extract the messages from the message queue. When the message queue is empty, this function will idle, consuming very low processor time, waiting for message to arrive in the message queue.

Below is an example, using FASM macro library:

msg_loop:
      invoke  GetMessage, msg, NULL, 0, 0
      cmp     eax, 1
      jb      end_loop
      jne     msg_loop
      invoke  TranslateMessage, msg
      invoke  DispatchMessage, msg
      jmp     msg_loop

Another approach is used when you want to catch the moment when the application goes to idle state and make some low priority, one-time processing (for example enabling/disabling the buttons on the toolbar, according to the state of the application).

In this case, a combination of PeekMessage and WaitMessage have to be used. PeekMessage function returns immediately, even when the message queue is empty. This way, you can detect this situation and provide some idle tasks to be done, then you have to call WaitMessage in order to idle the process waiting for incoming messages.

Here is an simplified example from my code (using FreshLib macros):

; Main message loop
Run:
        invoke  PeekMessageA, msg, 0, 0, 0, PM_REMOVE
        test    eax,eax
        jz      .empty

        cmp     [msg.message], WM_QUIT
        je      .terminate

        invoke  TranslateMessage, msg
        invoke  DispatchMessageA, msg
        jmp     Run

.empty:
        call    OnIdle
        invoke  WaitMessage
        jmp     Run

.terminate:
        FinalizeAll
        stdcall TerminateAll, 0
johnfound
  • 6,857
  • 4
  • 31
  • 60
2

What do you mean by "consume resources"?

If you just want a command that does nothing? If so nop will do that, and you can loop as much as you want even: rep; nop. However, the CPU will actually be busy doing work: executing the "no operation" instruction.

If you want an instruction that will cause the CPU itself to stop, then you are sorta-kinda out of luck: although there are ways to do that, you cannot do it from userspace.

Nik Bougalis
  • 10,495
  • 1
  • 21
  • 37
  • Consume resources I actually mean the lowest cost of CPU percentage. – Ben Feb 01 '13 at 22:20
  • 2
    @BenjaminWeiss: So you want the core to be able to do other things? Then you'll have to make a call to the OS to tell it to schedule another thread on that CPU. Call [SwitchToThread](http://msdn.microsoft.com/en-us/library/ms686352%28VS.85%29.aspx). Note that usage will still be at least 25% -- If the core can do something else, it will and thus be in use. If the core can't do anything else, it will run your code as fast as it can, and thus be in use. – David Schwartz Feb 01 '13 at 22:25
  • This would require a call to the OS which I don't want to. Isn't there something else like sleep? – Ben Feb 01 '13 at 22:28
  • 3
    Why do you not want a call to the O/S? Your application is already system specific, anyways - there's no magical "universal binary" that works on anything. Unless you plan on running your code on bare metal (e.g. a BIOS ROM extension, or somesuch) – Nik Bougalis Feb 01 '13 at 22:29
  • 3
    @BenjaminWeiss: You want the core to do something else other than run your code, right? That means the OS has to schedule another thread to use that core. That's clearly impossible without invoking the OS. – David Schwartz Feb 01 '13 at 22:29
2

With ring 0 access level (like kernel driver), you could use the x86 HLT opcode, but you need to have a system programming skill to really understand how to use it. Using HLT this way requires interrupts to be enabled (not masked) and the guarantee of an interrupt occurring (e.g. system timer), because the return from the interrupt will execute the next instruction after the HLT.

Without ring 0 access you'll never find any x86 opcode to enter an "idle" mode... You only could find some instructions which consume less power (no memory access, no cache access, no FPU access, low ALU usage...).

Jason Pyeron
  • 2,388
  • 1
  • 22
  • 31
1

Yes, there are some architectures support intrinsic idle state AKA halt.

For example, in x86 hlt, opcode 0xf4. Probably can be called only on privileged mode.

CPU Switches from User mode to Kernel Mode : What exactly does it do? How does it makes this transition?

How to completely suspend the processor?

a Linux's userspace example I found here:

.section .rodata
greeting:
.string "Hello World\n"
.text
_start:
mov $12,%edx /* write(1, "Hello World\n", 12) */
mov $greeting,%ecx
mov $1,%ebx
mov $4,%eax /* write is syscall 4 */
int $0x80
xorl %ebx, %ebx /* Set exit status and exit */
mov $0xfc,%eax
int $0x80
hlt /* Just in case... */
Community
  • 1
  • 1
0x90
  • 39,472
  • 36
  • 165
  • 245