3

私は現在 WIN32 ASM を学んでおり、リソースをまったく消費しない「アイドル」無限ループのようなものがあるかどうか疑問に思っていました。基本的に、次のような実験を行う実行中のプロセスが必要です。

loop:
  ; alternative to sleep...
  jmp loop

プロセスをアイドル状態にする可能性のあるものはありますか?

4

5 に答える 5

6

両方の方法を持つことはできません。CPU を消費することも、別のことをさせることもできます。Vlad Lazarenko が提案したように、rep; nop;(としても知られている)を使用すると、電力を節約し、他のコアのリソースを奪うことを回避できます。pauseしかし、コアを別のプロセスに渡さずにループすると、少なくともその仮想コアは他に何もできなくなります。

于 2013-02-01T22:08:42.267 に答える
3

注:アプリケーションをアイドル状態にするために空のループを使用しないでください。プロセッサを100%ロードします

Win32 環境で GUI アクティビティがない場合、アプリケーションをアイドル状態にする方法はいくつかあります。メイン (MSDN に記載) は、メッセージ キューからメッセージを抽出するために、メイン ループで "GetMessage" 関数を使用することです。メッセージ キューが空の場合、この関数はアイドル状態になり、メッセージがメッセージ キューに到着するのを待って、プロセッサ時間をほとんど消費しません。

以下は、FASM マクロ ライブラリを使用した例です。

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

アプリケーションがアイドル状態になる瞬間をキャッチし、優先度の低い 1 回限りの処理を行う場合 (たとえば、アプリケーションの状態に応じてツールバーのボタンを有効/無効にするなど) には、別のアプローチが使用されます。

この場合、PeekMessage と WaitMessage の組み合わせを使用する必要があります。PeekMessage 関数は、メッセージ キューが空の場合でも、すぐに戻ります。このようにして、この状況を検出し、いくつかのアイドル タスクを実行することができます。次に、WaitMessage を呼び出して、受信メッセージを待機しているプロセスをアイドル状態にする必要があります。

これは私のコードからの単純化された例です (FreshLib マクロを使用):

; 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
于 2013-02-01T23:46:18.953 に答える
2

「リソースを消費する」とはどういう意味ですか?

何もしないコマンドが必要な場合は?そうすればnop、好きなだけループすることもできます: rep; nop. ただし、CPU は実際には作業で忙しくなります。つまり、「操作なし」命令を実行します。

CPU自体を停止させる命令が必要な場合は、ちょっと運が悪いです.それを行う方法はありますが、ユーザー空間から行うことはできません.

于 2013-02-01T22:11:28.893 に答える
1

はい、組み込みのアイドル状態 AKA をサポートするアーキテクチャがいくつかありますhalt

たとえば、 x86hltでは opcode 0xf4. おそらく、特権モードでのみ呼び出すことができます。

CPU がユーザー モードからカーネル モードに切り替わります: 正確には何をしますか? この移行はどのように行われますか?

プロセッサを完全にサスペンドする方法は?

ここで見つけたLinuxのユーザー空間の例:

.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... */
于 2013-02-01T22:08:16.740 に答える