Moin!
jmp [es:b32]
[Bits 32]
b32:
mov ax,dataseg
Das mov ax,dataseg wird zu irgendwas assembliert, das mit den Bytes 0x66, 0xB8, ... beginnt. Der Sprung jmp [es:b32] ist ein indirekter Sprung, das heißt er liest den Speicher an Adresse b32 aus, anstatt nach b32 zu springen. Dort steht die eben genannte Instruktion, die als Adresse interpretiert wird, wodurch die CPU bei 0xB866 landet. (x86 ist Little Endian, deswegen sind die vertauscht.)
Bei einem far-jump kannst du kein Segmentregister angeben. Entweder du kodierst die Adresse hart, vermutlich sowas wie jmp 0x08:(0x7c00 + b32), falls der Assembler das schluckt Oder du machst das über den Stack:
push es
push b32 + 0x7c00
retf
Das 0x7c00 musst du vermutlich addieren, weil du annimmst, dass der Bootloader an Offset 0 (in Segment 0x7c0), geladen wird (statt 0x7c00 in Segment 0). (Das erkenne ich daran, dass du die ORG-Instruktion weggelassen hast, wodurch ORG 0 impliziert ist.) Übrigens heißt das auch, dass du beispielsweise die Variable bootdrive bei "load:" nicht korrekt ausliest, nachdem du ds auf 0 gesetzt hast. Vermutlich wird dadurch auch der restliche Code nicht funktionieren. Ich kann natürlich eine ewige Ausführung über Speicheradressierung im Real Mode schreiben, falls du das benötigst, aber ich würde vorschlagen du schlägst erstmal im NASM-Handbuch die ORG-Instruktion nach, und machst dir dann Gedanken, ob 1. du, 2. der Assembler, 3. die CPU alle dieselbe Vorstellung von dem Inhalt der Segmentregister haben, und ob diese korrekt ist.