1

I'm not sure if this question is going to make any sense, but I've messing around with writing basic assembly functions to use when I write C code (the C code is being output as 16 bit assembly, which is being output as a 16 bit raw binary). This is all part of my quest to become better at understanding/writing C and assembly, as well as my quest to understand how operating systems function at a conceptual level.

To make sure that my functions are working properly, I've been loading the raw binaries in real mode using the bios bootsector signature.

When I load the binary on virtualbox as a .flp, whether through an IDE controller or a floppy controller, the output on screen is completely as expected. There are two words with a space in between.

When, however, I go to load the same code on real machines using a USB stick, two letters in the first word are missing. The second word is written exactly as expected.

Is there any reason why there would be this kind of a discrepancy? I loaded the same code on three different real machines (not virtual box), and the same two letters in the first word were missing. I tried different USB sticks; I also loaded the raw image onto the USB with two different machines just to make sure.

I used the dd utility to write the .flp image I used on virtualbox (again, virtualbox has no problems with the output). I also used the dd utility to write the .flp image to the USB stick. I also wrote the .bin straight to the USB stick, and that did not make a difference.

I know there isn't anything wrong with the code itself, because it outputs perfectly on virtualbox. It just has those two letters oddly missing in the first word when booted onto real machines. Again, there are two words that are supposed to be output onto the screen.

The two missing characters are not weird characters that might not be universally supported; they're both lowercase letters.

Thanks for any help!

Final edit: This problem was being caused by the BIOS doing something nefarious to the binary program from bytes 2-48 in the program. From Michael's link in the comments, this appears to have something to do with the way that the BIOS deals with USB sticks on boot (which explains why it wasn't an issue when I was booting off of a floppy in virtual box). When I moved the program down by 48 bytes, the problem disappeared.

So my code looked something like (in as86 assembly syntax):

ORG 0x7c00
jmp main
.word 0x0000

ORG 0x7c30
main:
    (calls putchar function 9 times)

putchar:
    (function that prints function argument using int 0x10)

ORG 0x7DFE
.word 0xAA55

As I put in the comment, I'm curious to know why the BIOS would overwrite anything either in the first 512 bytes of the USB stick or in the 512 bytes of memory beginning at 0x7c00. I don't know which it is, whether it's overwriting on the USB stick before transferring the contents to memory, or whether it's overwriting the memory. I could find out by loading the program up once and then doing a hexdump on the binary in the USB after the boot-up load, but I haven't done that yet. At any rate, the overwriting at those locations just seems odd given that it's only by BIOS convention that the first 512 bytes are used (with the signature at the end), and it's only by BIOS convention that the CPU points to 0x7c00 following the load into memory. So I guess my point is that the BIOS certainly knows there are going to be instructions and data in those locations. So why wouldn't the BIOS do whatever it needs to do at some other location either on the USB stick or in the memory (depending on whether it's overwriting on the stick or rather in memory)?

Learning
  • 35
  • 6
  • 2
    Maybe this is the issue? https://stackoverflow.com/a/47320115/3857942 – Michael Petch Feb 02 '20 at 02:45
  • 2
    The other possibility is that you don't set up the segment registers properly. It would help if we can see your code. If you use an ORG of 0x7c00 in your assembly code then you will want to set ES and DS to 0 before you access memory in your bootloader. Add these as the first instructions of your bootloader: `xor ax, ax` `mov ds, ax` `mov es, ax` – Michael Petch Feb 02 '20 at 02:46
  • 1
    *I know there isn't anything wrong with the code itself, because it outputs perfectly on virtualbox* Oh if only things were that simple! Despite standards for how firmware should jump to a legacy BIOS MBR bootloader, not all systems do it the same way. And of course if you make assumptions about which drive you booted from, you might just have code that "happens to work" even on VBox. – Peter Cordes Feb 02 '20 at 05:28
  • Without seeing your code, it is impossible to tell. – fuz Feb 02 '20 at 12:59
  • Thanks to everyone for the help. The issue turned out to be the issue referenced by Michael where the BIOS was overwriting program data. I pushed the start of the program down by 48 memory addresses (0x30) and now it works just fine even off of a USB stick on a real machine! I do have another question, however, if someone would be willing to answer it. Why would the BIOS overwrite anything either in the first 512 bytes of the USB stick or in the 512 bytes of memory beginning at 0x7c00? That seems silly to do if, by BIOS conventions, the bootloader program is going to be at those locations. – Learning Feb 02 '20 at 15:46
  • 2
    My other answer sort of addresses that. The BIOS is writing drive geometry (like number of cylinders/heads/sectors) into what it thinks is the BIOS Parameter Block. On a regular floppy disk the size of the media is of a fixed size and written to the floppy disk when it is formatted. When writing a floppy image to USB, the USB drive may have a different number of heads, cylinders, and sectors per track. Having the BIOS write info to the BPB allows properly written bootloaders to use the BPB geometry to do proper calculations when reading new sectors into memory. – Michael Petch Feb 02 '20 at 16:03
  • 2
    The unfortunate down side is for anyone who doesn't have space for a BPB on their media - things can just get overwritten. Some BIOSes are a bit smarter in that they will attempt to determine if a proper BPB is present before overwriting the beginning of the bootloader memory with drive geometry. It seems machines with BIOSes that blindly write new drive geometry to memory without any form of sanity check are becoming more common. The issue you are observing has been asked by others on SO, the OSDev wiki/forum, and Reddit (r/osdev). – Michael Petch Feb 02 '20 at 16:08
  • 1
    The BIOS doesn't update your disk at all. The new drive geometry written to the BPB is done in memory only. The BIOS reads the boot sector from your disk; it then writes the drive geometry info to the area it thinks is the BPB in memory inside the bootloader it read; and then transfers control to your bootloader. The disk is never altered, just the bootloader in memory. – Michael Petch Feb 02 '20 at 16:13
  • Wrote this before I saw the other comments. Thanks for the helpful responses! – Learning Feb 02 '20 at 16:13
  • 1
    Most *properly* written bootloaders for unpartitioned floppy media place a BPB in the Volume Boot Record (on floppy media the VBR is also the MBR) as part of the file system requirements (FAT12/FAT16 etc). When you format floppy media with DOS (or DOS compatible tools) to make a bootable disk the geometry of the disk is written when formatting. Most good bootloaders use the data in the BPB (cylinders/head/sectors) to read more sectors from memory to continue the boot process - that requires proper drive geometry info (heads, cylinders, sectors per track) – Michael Petch Feb 02 '20 at 16:18
  • 1
    There are some badly written bootloaders out there with a BPB in them that isn't used by the bootloader itself. Unfortunately on USB media with different drive geometry characteristics those bootloaders can fail when reading more sectors into memory to continue the boot process. – Michael Petch Feb 02 '20 at 16:20
  • 1
    On a side note. If you have a BIOS that supports booting with USB Hard Drive Emulation HDD (usually changeable in the BIOS configuration) then a BPB is usually not required, but for some BIOSes a proper partition table is needed or the disk may not be seen as bootable at all. – Michael Petch Feb 02 '20 at 16:25
  • I cannot tell you what is wrong without seeing the exact code you tried. “code looked something like this” won't cut it. – fuz Feb 02 '20 at 22:21

0 Answers0