Der Code von osdev.org ist nicht dafür gedacht in den Kernel gelinkt zu werden. Insbesondere ist es ein Problem, dass dein Kernel nach 0x100000 geladen ist, was zur Folge hat, dass dieser Code im Real Mode nicht mehr addressierbar ist. Die Fehlermeldungen von ld gehen in die selbe Richtung und versuchen dir zu sagen, dass du über 16-Bit-Adressierung nicht auf die 32-Bit-Adressen, die das ELF-Format erzeugt, zugreifen kannst.
Du hast 3 Möglichkeiten:
1. Du erzeugst mit NASM eine flache Binary (-f bin) und fügst die über
INCBIN in eine weitere .asm-Datei ein. Dann kopierst du diese Daten (zur Laufzeit) an eine Adresse unter 1 MB und springst dorthin. Dazu brauchst du natürlich labels vor und hinter dem INCBIN.
2. Wie 1. nur du linkst die .bin-Datei einfach mit. Dann schauste da mal mit objdump in den Kernel rein, welche Symbole für Anfang und Ende der Daten erzeugt werden (Tipp: die sind ähnlich wie der Dateiname), damit du dann die Binary unter 1 MB kopieren kannst.
3. Du passt den Code für relative Addressierung an. Anstatt [savcr0] schreibst du dann [savcr0 - idt_real], statt [idt_real] nur [idt_real - idt_real] oder gleich [ 0] und jmp 0:GoRMode - idt_real statt jmp 0:GoRMode (falls der Assembler das nimmt ...). Dann musst du den gesamten Code an den Anfang eines Segments kopieren (weil idt_real am Anfang der Quellcode-Datei steht, und wir von jeder Adresse die Adresse von idt_real abziehen.)
Das alles funktioniert natürlich erst nachdem du den osdev.org-Code soweit angepasst hast, dass er auch mehr tut als nur in den Real Mode zu springen und dann im Nirvana zu verschweinden. Außerdem musst du aufpassen, dass du die Segmente richtig beachtest. Der Code erwartet ans Segment 0 geladen zu werden. Für Methode 3 solltest du das ändern, sonst ist die IVT weg. Für Methoden 1 und 2 solltest du dem Code gegegebenfalls noch mit .org ein Offset verpassen, das dann zusammen mit dem Segment auf die Adresse abgestimmt ist, an die die Binary kopiert wird.