Table of Content

Experiment and Programming Environment

We shall elect the following as our experiment

The instructor will use:

On the x86 Debian Linux system, install required application packages by command,

apt-get install -y nasm qemu qemu-system hexedit

The above command must run as root on the Linux system. In the Debian system, you first switch to root by command

su

If you have installed and set up the sudo package. You can also use sudo to run the above apt-get command to install the required packages, i.e.,

sudo apt-get install -y nasm qemu qemu-system hexedit

CPU Emulator

QEMU is a CPU emulator. To view the specifications of the x86 system it emulates, we use view one of its manual page:

man qemu-system-i386

BIOS

The Basic Input/Output System (BIOS) contains the Bootstrap code that is the first code the CPU executes when we power on the system. The Bootstrap code is responsible for loading the OS. This begins to load the code in the boot sector typically located at the very first sector of a booting device, such as, a hard disk drive. A system may have multiple boot sectors. We term the first boot sector BIOS loads the Master Boot Sector (Master Boot Record or MBR) that in turns loads and executes code in other boot sectors or the operating system kernel. When you install and set up an operating system, the system installer writes the MBR code to the Master Boot Sector.

We can examine the code in the MBR using the following commands

cat /proc/diskstats
dd if=/dev/sda of=mbr.bin bs=512 count=1 
hexedit mbr.bin
ndisasm -b16 -o7c00h mbr.bin > mbr.asm
vi mbr.asm

For more see https://thestarman.pcministry.com/asm/mbr/GRUB.htm.

Experimenting Boot Sector Code

We can write our own boot sector code. Although you can write the code to the disk’s boot sector, we run it in the emulated x86 system using QEMU. The following examples are from Nick Bundell.

Compiling and Running Boot Sector Code

For the programs given here, the procedure to compile and run the code are as follows, provided that the program to run is in file example.asm:

  1. Compile example.asm. Open a terminal window, run
    nasm example.asm -f bin -o example.bin
    
  2. Run example.asm on the x86 system emulated by the QEMU emulator. In the terminal window, run
    qemu-system-i386 -drive format=raw,file=example.bin \
     -display curses \
     -monitor telnet:127.0.0.1:54321,server,nowait
    
  3. Open the QEMU monitor. Open another terminal window run
    telnet 127.0.0.1 54321 
    

    To quit the QEMU emulator, issue quit command as in

    (qemu) quit
    

Example 0 Infinite Loop

Following the steps in the above, we do the following:

  1. Create boot0.asm. On the Linux system, create the boot0.asm file using either nano, vi, or other editors if you have installed.
    ; boot0.asm
    ; a do-nothing infinite loop
    loop:
     jmp  loop
    times 510-($-$$) db 0
    dw 0xaa55
    
  2. Compile boot0.asm. Open a terminal window, run
    nasm boot0.asm -f bin -o boot0.bin
    
  3. Run boot0.asm on the x86 system emulated by the QEMU emulator. In the terminal window, run
    qemu-system-i386 -drive format=raw,file=boot0.bin \
     -curses \
     -monitor telnet:127.0.0.1:54321,server,nowait
    
  4. Open the QEMU monitor. Open another terminal window run
    telnet 127.0.0.1 54321 
    

    To quit the QEMU emulator, issue quit command as in

    (qemu) quit
    

Example 2 Printing a Message

Similarly, you can run and observe the following code.

; boot1.asm
; print Hello on console
mov ah, 0x0e
mov al, 'H'
int 0x10
mov al, 'e'
int 0x10
mov al, 'l'
int 0x10
mov al, 'l'
int 0x10
mov al, 'o'
int 0x10
jmp $

times 510-($-$$) db 0
dw 0xaa55