Your code assumes that DS is set to 0. You cannot allow this. The first part of your code should explicitly set DS to 0 if you are using org 0x7c00 .
You should seriously consider defining your stack by installing SS: SP. You do not know where the existing one is, or it is large enough to process what you intend to do.
Just before calling your bootloader, the BIOS will set the DL register with the boot device number. You should not set DL to 0 in code when executing disk queries from a boot disk. You must use the value that exists in DL when invoking the bootloader.
You must use the CLD instruction to clear the direction flag, since you are using an LODSB instruction that is waiting to be moved forward in memory. There is no guarantee that the direction flag will be set correctly, so you must explicitly point it in the direction you need with CLD (forward) or STD (back).
I have more information about the problems above in my StackOverflow answer with General Bootloader Tips .
Since you are not using BPB , I highly recommend removing jmp start as the first instruction of your bootloader. Instead, move the data after the code, but before the signature of the boot sector ( 0xAA55 ). The reason for this is that some BIOSes will try to find the BPB based on the JMP instruction that appears as the first loader instruction and, if found, overwrites parts of your loader in memory, potentially causing undefined behavior.
Your bootloader uses this instruction to start the second stage loaded from the second sector:
jmp 0x0:0x1000
The problem is that when you read the sector configuring ES: BX as follows:
read_sector: mov ax, 0x0 mov es, ax xor bx, bx
This sets ES: BX to 0x0000: 0x0000, which is clearly not where your JMP expects the code to be. You need to install ES: BX in the memory location that you want INT 13 / AH = 02h to read the sector (s) of the disk.
INT 13h / AH = 02h requires the cylinder / head / sector number to be set correctly. Sectors start numbering at 1, but Cylinders and Heads are based on zero. The second sector of the disk is in Cylinder 0, Head 0, Sector 2. Your code sets Cylinder to 1 instead of 0. This code is incorrect, since you really have to set it to 0:
mov ch, 01
In the second step, you created print as a function, since it ends with a RET statement. jmp print should be changed to call print .
With all the changes recommended above, including those of my general loader tips, your code could be modified like this:
boot.asm
[bits 16] [org 0x7c00] ; Use the boot drive number passed to us by BIOS in register DL start: xor ax,ax ; We want a segment of 0 for DS for this question mov ds,ax ; Set AX to appropriate segment value for your situation mov es,ax ; In this case we'll default to ES=DS mov bx,0x8000 ; Stack segment can be any usable memory mov ss,bx ; This places it with the top of the stack @ 0x80000. mov sp,ax ; Set SP=0 so the bottom of stack will be @ 0x8FFFF cld ; Set the direction flag to be positive direction mov si, wolf_wel_msg call wolf_print mov si, wolf_kernel_load call wolf_print pushf stc mov ah,00 int 13h read_sector: mov ax, 0x0 mov es, ax ; ES = 0 mov bx, 0x1000 ; BX = 0x1000. ES:BX=0x0:0x1000 ; ES:BX = starting address to read sector(s) into mov ah, 02 ; Int 13h/AH=2 = Read Sectors From Drive mov al, 01 ; Sectors to read = 1 mov ch, 00 ; CH=Cylinder. Second sector of disk ; is at Cylinder 0 not 1 mov cl, 02 ; Sector to read = 2 mov dh, 00 ; Head to read = 0 ; DL hasn't been destroyed by our bootloader code and still ; contains boot drive
hello.asm
[org 0x1000] jmp start data: msg db 'Hello',0 start: mov si, msg call print ; print is a function, use CALL instead of JMP cli hlt print: lodsb or al, al jz exit mov ah,0x0e int 10h jmp print exit: ret
Since you are apparently using Windows based on the information provided in your DD command, you may have another problem. I donβt know which DD you are using, but of=\\.\d: does not write to the beginning of the disk (USB drive), it will write to the partition where D: is located, and not at the beginning of the disk itself.
I recommend using the latest DD from Chrysocome . To date, the latest 0.6beta3 . I recommend this version because it allows you to correctly access the disk (or USB drive) relative to the beginning of the disk, and not relative to the beginning of a specific partition. This can lead to serious problems requiring proper storage of the 1st and 2nd sectors. In the latest version, I will use these commands with administrator privileges to write to a USB drive:
dd if=f:\boot.bin od=d: bs=512 count=1 dd if=f:\hello.bin od=d: bs=512 seek=1 count=1
This assumes your USB drive is located on drive D: as suggested in your question. A WARNING. Improper use of the drive may result in loss and corruption of data on another device.
If these commands work correctly, the output should look something like this:
dd if=boot.bin od=d: bs=512 count=1 rawwrite dd for windows version 0.6beta3. Written by John Newbigin < jn@it.swin.edu.au > This program is covered by terms of the GPL Version 2. Device d: is a link to \\?\Device\HarddiskVolume5 \\?\Device\HarddiskVolume5 is a partition on \Device\Harddisk1 512 100% 1+0 records in 1+0 records out dd if=hello.bin od=d: bs=512 seek=1 count=1 rawwrite dd for windows version 0.6beta3. Written by John Newbigin < jn@it.swin.edu.au > This program is covered by terms of the GPL Version 2. Device d: is a link to \\?\Device\HarddiskVolume5 \\?\Device\HarddiskVolume5 is a partition on \Device\Harddisk1 28 5% 0+1 records in 0+1 records out
After you issue these commands, Windows can automatically detect that the disk is no longer formatted. Do not allow Windows to format the drive. If you allow to format the disk, it will re-format it and format it. In doing so, it will destroy the boot sector that you wrote. When prompted, simply cancel the format dialog that may appear.
Be sure to disconnect / remove the USB drive correctly before removing it from your system. Incorrect unmounting will cause the data to be incorrectly / completely written to disk.
If you want to create a disk image for Bochs, QEMU, DOSbox, etc., you can create a 720k floppy disk with these commands on the command line:
dd if=/dev/zero of=disk.img bs=1024 count=720 dd if=f:\boot.bin of=disk.img bs=512 count=1 conv=notrunc dd if=f:\hello.bin of=disk.img bs=512 seek=1 count=1 conv=notrunc
The disk.img image disk.img must be used by Bochs, QEMU, DOSbox, etc. or recorded on a 720k floppy disk for use on a real computer.
/dev/zero looks like a typical Unix / Linux device. The DD command for Windows, I suggested that you use the concepts /dev/zero as a special input device that only generates zeros. Windows does not have a device /dev/zero , but DD sees this as a special internal device and mimics it.
When starting from Bochs 2.6.8 on MS Windows, this is what I saw:

On my Lenovo L520 laptop (non-EFI BIOS) with a 16GB USB drive, this is what I saw:
