mov $0x58, %al # 2 bytes: b0 58
mov $0xfee1dead, %ebx # 5 bytes: bb ad de e1 fe
mov $0x28121969, %ecx # 5 bytes: b9 69 19 12 28
mov $0x4321fedc, %edx # 5 bytes: ba dc fe 21 43
int $0x80 # 2 bytes: cd 80
ルートとして実行する必要があります。
これは電源ボタンを押すのと同じで、PCの電源を安全に切ることはできません。sync
少なくともファイル破損のリスクを最小限に抑えるために、このプログラムを実行する前に、開いているすべてのアプリケーションを閉じて実行し、すべてのファイルシステムバッファをフラッシュしてください。
テスト走行
$ as -o poweroff.o poweroff.s
$ ld -o poweroff poweroff.o
ld: warning: cannot find entry symbol _start; defaulting to 0000000000400078
$ sudo sh -c 'sync && ./poweroff'
root's password:
暗闇が続きます。
使い方
int $0x80
ソフトウェア割り込みを呼び出します。x86とx64の両方で動作しますが、10年以上にわたって非推奨になっており、本番コードでは使用しないでください。syscall
代わりにx64コードを使用する必要があります。x86はを使用する必要がありますがsysenter
、コードゴルフには面倒です。
syscallの結果のアクションは、レジスタEAX-EDX、ESI、およびEDIに依存します。Linuxでは、システムコールリファレンスを介して利用可能なすべてのシステムコールを示していますint $0x80
。
EAXが0x58(88)を保持すると、再起動が呼び出されます。これは、コンピューターの電源オフ、スリープ状態、休止状態、およびカーネルの切り替えとCtrl-Alt-Del キーコンボの無効化または有効化にも使用できます。
プログラムの開始時に- as
またはgcc -nostdlib
でコンパイルすることにより、実際にプログラムの開始時にいることを確認できます-ほとんどのレジスタは0に設定されます。これにはEAXが含まれるため、EAX mov $0x58, %al
の下位8ビットを0x58に設定して、EAX自体を0x58に設定できます。これにより、32ビットでxor %eax, %eax
0x58 mov $0x58, %eax
をエンコードするstraightforwardでレジスタを手動でゼロ化するよりも2バイト節約できます。
再起動の最初の2つの引数は、おそらく偶発的な再起動を防ぐためのマジック番号であり、レジスタEBXおよびECXから読み取られます。これらの数値が特定の定数に等しくない限り、再起動はアクションの実行を拒否します。
最初のマジック番号は0xfee1dead(feel dead)と等しくなければなりません。これは、おそらくPCの電源オフ/死を指します。
2番目の魔法の数は4つの異なる定数に等しくなりますが、後者の3つは古代バージョンのLinuxでは機能しませんでした。それらはすべて、PCのその後の電源オン/誕生を参照しているようです。
0x28121969は、Linus Torvaldsの誕生日(1969年12月28日)を表します。
0x05121996は、パトリシアトーバルズの誕生日(1996年12月5日)を表します。
0x16041998は、ダニエラトーバルズの誕生日(1998年4月16日)を表します。
0x20112000は、セレステトーバルズの誕生日(2000年11月20日)を表します。
パトリシア、ダニエラ、セレステ・トーバルズは、リーナス・トーバルズの3人の娘です。
EDXレジスタは、必要な「リブート」のタイプを選択します。0x4321fedcはRB_POWER_OFFで、PCをシャットダウンして電源を切ります。
最後に、ESIレジスタの値はRB_POWER_OFFに対して無視されます。EDIレジスタの値は再起動によって完全に無視されます。
代替バージョン、x64のみ、19バイト
x64では、同じバイトカウントに対して適切なsyscallを使用できます。
mov $0xa9, %al # 2 bytes: b0 a9
mov $0xfee1dead, %edi # 5 bytes: bf ad de e1 fe
mov $0x28121969, %esi # 5 bytes: be 69 19 12 28
mov $0x4321fedc, %edx # 5 bytes: ba dc fe 21 43
syscall # 2 bytes: 0f 05
唯一の違いは、命令(syscall
vs int $0x80
)、__NR_REBOOTの値(0xa9 vs 0x58)、および関連するレジスタにあります。