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
Must be run as root.
This is equivalent to pressing the power button and not a safe way to power off your PC. Make sure you close all open applications and execute sync
to flush all file system buffers before executing this program, to at least minimize the risk of file corruption.
Test run
$ 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:
Followed by darkness.
How it works
int $0x80
invokes a software interrupt. It works on both x86 and x64, but has been deprecated for over a decade now and should not be used in production code. x64 code should use syscall
instead. x86 should use sysenter
, but it is too cumbersome for code golf.
The resulting action from the syscall depends on registers EAX - EDX, ESI, and EDI. The Linux Syscall Reference shows all syscalls that are available via int $0x80
.
When EAX holds 0x58 (88), reboot is called, which can also be used to power off, put to sleep, or hibernate the computer, as well as switching kernels and disabling or enabling the Ctrl - Alt - Del key combo.
At the start of the program – and by compiling with as
or gcc -nostdlib
, we can make sure that we're actually at the start of the program – most registers are set to 0. This includes EAX, so we can use mov $0x58, %al
to set the lower 8 bits of EAX to 0x58, thus setting EAX itself to 0x58. This saves two bytes over manually zeroing the register with xor %eax, %eax
and one more over the straighforward mov $0x58, %eax
which encodes 0x58 in 32 bits.
The first two arguments to reboot are magic numbers, presumably to prevent accidental reboots, and are read from registers EBX and ECX. Unless these numbers are equal to certain constants, reboot refuses to perform any action.
The first magic number must equal 0xfee1dead (feel dead), probably referring to the power off / death of the PC.
The second magic number can be equal to four different constants, although the latter three did not work in ancient versions of Linux. All of them seem to refer to the subsequent power on / birth of the PC.
0x28121969 represents Linus Torvalds's birthday (December 28, 1969).
0x05121996 represents Patricia Torvalds's birthday (December 5, 1996).
0x16041998 represents Daniela Torvalds's birthday (April 16, 1998).
0x20112000 represents Celeste Torvalds's birthday (November 20, 2000).
Patricia, Daniela, and Celeste Torvalds are Linus Torvalds's three daughters.
The EDX register selects the type of "reboot" we want. 0x4321fedc is RB_POWER_OFF, shutting the PC down and powering it off.
Finally, the value of the ESI register is ignored for RB_POWER_OFF; the value of the EDI register is ignored entirely by reboot.
Alternate version, x64-only, 19 bytes
On x64, we can use a proper syscall for the same byte count.
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
The only differences lie in the instruction (syscall
vs int $0x80
), the value of __NR_REBOOT (0xa9 vs 0x58), and the involved registers.
`whatever`;
Bash/Perl/PHP/Ruby/etc. stupiglots. \$\endgroup\$shatdown: past tense of the verb shutdown
\$\endgroup\$