3

My code works perfectly in virtualbox but not when booted on a real PC (from a USB pen drive which BIOS detects as a USB Hard Drive.)

In virtualbox; the code reads sector 2&3 of the disk to memory, prints the first 128 bytes (as a debug step) then executes the code stored in those sectors.

On my real PC, it successfully prints the correct bytes to screen (so obviously is reading the disk correctly, and writing it to the expected place in memory) but then stops execution at that point rather than jumping.

Why would it be different, and what could I be doing wrong?

ORG 0x7C00;

; Load Sector 2&3 from disk to 0x1000

mov bx , 0x1000             
mov ah , 0x02   
mov al , 0x02   
mov ch , 0x00   
mov dh , 0x00   
mov cl , 0x02   
int 0x13;


;Print 0x1000 + 128 bytes

mov ah, 0x0e        
mov bx ,0x1000;
loop2:          

mov al, [bx]        
cmp bx, 0x1000+128  

je end2
int 0x10        
add bx , 1;     
jmp loop2;

end2:

; Run our code


call 0x1000

jmp $;

TIMES 510 - ($ - $$) DB 0
DW 0xAA55
JeffUK
  • 4,107
  • 2
  • 20
  • 34
  • Have you tried it on different VM's/emulators? – Kendall Frey Mar 25 '13 at 15:23
  • My guess would be that the VM is running in x86 and your PC is x64? just a shot in the dark. – Viezevingertjes Mar 25 '13 at 15:28
  • @MrMichael How exactly would that prevent it from working? Last time I checked, x86_64 CPUs ran i386 bootloaders and OSes just fine. – us2012 Mar 25 '13 at 15:35
  • @us2012 like i said, a shot in the dark, a VM is very forgiving anyway if it comes down to these things, a PC however is not. – Viezevingertjes Mar 25 '13 at 15:38
  • Maybe you need to set the `DS` (data segment) register explicitly? i.e., `mov ds,0` – Brett Hale Mar 25 '13 at 15:40
  • "stops execution at that point rather than jumping" how do you know this? Try making the first instructions at 1000h print some debug info too, then you will know if it has jumped correctly. – Ville Krumlinde Mar 25 '13 at 15:59
  • Hi ville, that's exactly what I did.. in fact I even had the above code in both sectors on the disk. On the VM it printed a string twice, on the PC it printed the string once. Looks like it was one of the segment registers. Thanks for all your suggestions – JeffUK Mar 25 '13 at 20:12
  • @JeffUK out of curiosity: can you please tell me why is the current interest in boot-loaders? I looked at other x86 assembly questions and several of them from last few days are on boot loaders. Is that homework? CS course? Thanks! – Sten Petrov Mar 29 '13 at 19:35

1 Answers1

7

There are lots of problems with this code that you might find on real hardware:

  1. The state of most of the registers when you enter your bootloader is undefined - but the registers need to be valid when you call into interrupt routines. Make sure you set up your segment registers immediately on starting the bootsector. For example, if ES != CS, your jump to the second stage will land in the wrong place.

  2. Ensure you have a valid stack before calling into interrupt routines.

  3. Do not rely on interrupt routines being available. Many hardware vendors recognise build their hardware to work for Windows and Linux (since that's what 99.999% of their customers want), and don't bother implementing interrupt routines they know Windows and Linux won't call.

  4. Before doing disk-accesses, try doing something simpler, like printing a string out to the video display. Next, write a way of printing a register to the screen. Only then will you be in a position where you can start writing a bootloader in a way that you can debug.

SecurityMatt
  • 6,593
  • 1
  • 22
  • 28
  • Looks like you got it in 1! I've explicitly set all the segmentation registers to 0x00 and it's now working perfectly. Thank you! – JeffUK Mar 25 '13 at 19:17