Saturday, November 22, 2014

Assembly Tutorial 3: Disk IO

For this tutorial we are going to keep things as short and simple as possible.  I will cover how to load information from a disk into memory using CHS addressing, and how to jump to that part of memory to run code.

CHS Addressing
First I will start with explaining what CHS addressing it.  CHS stands for Cylinder, Head, and Sector.  When referring to a traditional hard disk which is typically made of several discs that are stacked with read heads on each surface.

The cylinder is an imaginary cylinder that extends through all the discs, so basically all the data that can be read without moving the read heads.  The first cylinder is numbered 0.

The head is the read head, also starting at number 0.  Now the sector is the smallest storage unit that is addressable by the hard drive.  This actually starts at 1.

Loading the Data from the Disk
In assembly we can use BIOS interrupt 0x13 to load data from the disk.  Unlike our print functions this actually takes a lot more parameters.

We need to put 0x02 in AH to tell the BIOS that we want to use the Disk Read function.

In DL we will put the drive to load from.

In BX we will put the address in memory to load to.

The number of sectors to load goes in register AL.

We need to address where to start from in CH with the Cylinder, DH with the Head, and CL with the Sector.  With our program we will put 0 in CH, 0 in DH, and 2 in CL.

We will also put 9 in AL to specify that we will load 9 sectors.
We will also set BX to 0x9000.

For most computers the BIOS loads DL with the boot drive at start so we will store that at the label BOOT_DRIVE at the top of our program and push it back to DL when we go to load from the disk.

At this point we can jump to the data we just loaded at 0x9000 by calling JMP 0x9000.

Building the Program
For the data we are going to have at this location we will put our hello world program, except instead of using the org directive to set our start at 0x7c00 we will set it to 0x9000 so the compiler knows we are loading it at this location.  We also need to make sure the file is 9 sectors long so we will do similar to the bootloader and put a times macro except we will make it 4608-($-$$) db 0 since there are 512 bytes in a sector.

At this point we can compile our two files using NASM and then merge them using a binary copy.  This is done with the copy command:
copy /b "Bootloader.com" + "Hello World.com" "Hello World.bin"

The output file can then be run in QEMU.

Please refer to the code in the repository for an exact implementation.
https://github.com/musicman89/Assembly-Tutorial


No comments:

Post a Comment