1

I'm trying to make a simple bootloader, but running into issues with ld (I think).

When I compile my assembly file (below) with nasm -f bin, it works and I get a nice 512 byte file. For that one I include org 0x7c00 at the top and everything works as expected.

However, now I'm trying to do something a bit more complicated and link in a C kernel (unclear if I'm on the right path there, but I'm sure I'll learn that soon). Anyway, when I compile it with nasm -f elf -o loader_elf bootloader.asm and link it with i386-elf-ld loader_elf -o loader_exe -Ttext 0x7C00, I get a file that is 4196 bytes (with a 1152 byte elf file).

What do I need to do for either the elf file or ld to get an executable with a proper file size?

Thanks for your help!

Here's the file in question:

bits 16 ; 16-bit Real Mode
;org 0x7c00 ; BIOS boot origin... only used for bin, not elf

global _start

Message db "Starting YADBL", 0x0 

jmp _start ;Jump to start main() entry-point 

;Print characters to the screen 
Println:
    lodsb ;Load string 
    or al, al
    jz complete
    mov ah, 0x0e    
    int 0x10 ;BIOS Interrupt 0x10 - Used to print characters on the screen via Video Memory 
    jmp Println ;Loop       
complete:
    call PrintNwL

;Prints empty new lines like '\n' in C/C++  
PrintNwL: 
    mov al, 0   ; null terminator '\0'
    stosb       ; Store string 

    ;Adds a newline break '\n'
    mov ah, 0x0E
    mov al, 0x0D
    int 0x10
    mov al, 0x0A 
    int 0x10
    ret

;Reboot the Machine 
AToHalt:     
    call GetPressedKey 
    ; Inputted key is in al
    cmp al, 'A'
    jne rbt
    ; We got an A!!!
;    mov si, Halting
;    call Println
    cli
    hlt

rbt:
    ret  ; we're returning, not rebooting

    ;Sends us to the end of the memory
    ;causing reboot 
    ;db 0x0ea 
    ;dw 0x0000 
    ;dw 0xffff 
    jmp 0xffff:0000h ; also restarts

;Gets the pressed key 
GetPressedKey:
    mov ah, 0
    int 0x16  ;BIOS Keyboard Service 
    ret 

;Bootloader entry-code 
_start:
   cli ;Clear interrupts 
   ;Setup stack segments 
   mov ax,cs              
   mov ds,ax   
   mov es,ax               
   mov ss,ax                
   sti ;Enable interrupts 

   ;Print the first characters  
   mov si, Message 
   call Println 

   call AToHalt

   times 510 - ($-$$) db 0 ;Fill the rest of the bootloader with zeros 
   dw 0xAA55 ;Boot signature
  • 1
    You may be able to get the linker to create an ELF file that's less than 512 bytes, but what would be the point? BIOSes can't load ELF files. Have the linker create a binary file instead. – Ross Ridge Jul 02 '18 at 04:40
  • 1
    You could add `--oformat binary` to your linker command. But you are going to have real problems when you start adding in _C_ objects with data, bss, rodata sections. Most people for simplicity create their bootloader separate from their _C_ kernel – Michael Petch Jul 02 '18 at 05:01
  • 2
    You really shouldn't link your kernel into your bootloader. Instead, make your kernel a separate file you load from your bootloader. – fuz Jul 02 '18 at 07:17
  • You can write your 512 byte MBR (bootloader) in NASM. That code will have to read your kernel into memory at a fixed address (starting at 0x0000:0x8000 for example) using something like [Int 13h/AH = 02h](http://www.ctyme.com/intr/rb-0607.htm). You then have to switch into protected mode and then do a far jump to 0x8000 with your 32-bit code selector. Your kernel would then be built separately and placed on the disk (putting it after the bootloader is easiest). – Michael Petch Jul 02 '18 at 13:21
  • 1
    You also have `Message db "Starting YADBL", 0x0 ` before code. When the file is generated this data will be interpreted as code by the processor. Place your data after the last line of usable code and before the boot signature, – Michael Petch Jul 02 '18 at 13:43
  • I have to bind them and them compile them to binary so I can set the offset of the Kernel, right? How can I load the Kernel without the underlying file system? –  Jul 02 '18 at 14:28
  • Using `int 13h/ah=2h` doesn't require a file system. You can place the kernel at a specific point on the disk (right after the bootloader is easiest to get started). The trick is having an appropriate kernel where the entry point is at the very beginning of the file (when you build your kernel you can also output directly as a binary as well). There are examples of this around. I'll see if I can dig up an SO answer with some code – Michael Petch Jul 02 '18 at 15:55
  • 1
    Here is a previous SO answer that has a complete same of what you can do: https://stackoverflow.com/a/33619597/3857942 in the section `Code After Making All Recommended Changes` – Michael Petch Jul 02 '18 at 16:21

0 Answers0