Rebooting With JMP Instruction

By Susam Pal on 02 Mar 2003

While learning about x86 microprocessors, I realised that it is possible to reboot a computer running MS-DOS or Windows 98 by jumping to the memory address FFFF:0000. Here is an example DEBUG.EXE session from MS-DOS 6.22:

C:\>DEBUG
G =FFFF:0000

In the above example, we start the DOS debugger and then enter the G (go) command to execute the program at FFFF:0000. Just doing this simple operation should reboot the system immediately.

When the computer boots, the x86 microprocessor starts in real mode and executes the instruction at FFFF:0000. This is an address in the BIOS ROM that contains a far jump instruction to go to another address, typically F000:E05B.

C:\>DEBUG
-U FFFF:0000 4
FFFF:0000 EA5BE000F0    JMP     F000:E05B

The address F000:E05B contains the BIOS start-up program which performs a power-on self-test (POST), initialises the peripheral devices, loads the boot sector code, and executes it. These operations complete the booting sequence.

The important point worth noting here is that the very first instruction the microprocessor executes after booting is the instruction at FFFF:0000. We can use this fact to create a tiny executable program that can be used to reboot the computer. Of course, we can always perform a soft reboot using the key sequence ctrl+alt+del. However, just for fun, let us create a program to reboot the computer with a JMP FFFF:0000 instruction.

Reboot Program

Here is a complete DEBUG.EXE session that shows how we could write a simple reboot program:

C:\>DEBUG
-A
1165:0100 JMP FFFF:0000
1165:0105
-N REBOOT.COM
-R CX
CX 0000
:5
-W
Writing 00005 bytes
-Q

C:\>

Note that the N (name) command specifies the name of the file where we write the binary machine code to. Also, note that the W (write) command expects the registers BX and CX to contain the number of bytes to be written to the file. When the DOS debugger starts, it already initialises BX to 0 automatically, so we only set the register CX to 5 with the R CX command above.

Now we can execute this 5-byte program like this:

C:>REBOOT

Debugger Scripting

In the previous section, we saw how we can start DEBUG.EXE and type the debugger commands and the assembly language instruction to jump to FFFF:0000. We can also keep these debugger inputs in a separate text file and feed that to the debugger. Here is how the content of such a text file would look:

A
JMP FFFF:0000

N REBOOT.COM
R CX
5
W
Q

If the above input is saved in a file, say, REBOOT.TXT, then we can run the DOS command DEBUG < REBOOT.TXT to assemble the program and create the binary executable file. The following DOS session example shows how this command behaves:

C:\>DEBUG < REBOOT.TXT
-A
1165:0100 JMP FFFF:0000
1165:0105
-N REBOOT.COM
-R CX
CX 0000
:5
-W
Writing 00005 bytes
-Q

C:>

Disassembly

Here is a quick demonstration of how we can disassemble the executable code:

C:\>DEBUG REBOOT.COM
-U 100 104
117C:0100 EA0000FFFF    JMP     FFFF:0000

While we did not really need to disassemble this tiny program, the above example shows how we can use the debugger command U (unassemble) to translate machine code to assembly language mnemonics.

Comments | #assembly | #programming | #dos | #technology