Question

In my efforts to understand how to use the GNU binutils to build a simple boot loader using gas I have come across the question, how do you tell the linker where to put your data, in a file that uses .org to advance the location counter while keeping the file size at 512 bytes. I can't seem to find a way to do this.

The assembly program that tries to do this is:

# Author: Matthew Hoggan
# Date Created: Tuesday, Mar 6, 2012

.code16                      # Tell assembler to work in 16 bit mode
.section .data
msg:                         # Message to be printed to the screen
  .asciz "hello, world"

.section .text
.globl _start                # Help linker find start of program
_start:
  xor  %ax,  %ax             # Zero out ax register (ah used to specify bios function to Video Services) 
  movw %ax,  %ds             # Since ax is 0x00 0x00 use it to set data segment to 0
  mov  $msg, %si             # Use source index as pointer to string

loop:
  movb %ds:(%si), %al        # Pass data to BIOS function in low nibble of ax
  inc  %si                   # Advance the pointer
  or   %al, %al              # If byte stored in al is equal to zero then...
  jz   _hang                 # Zero signifies end of string
  call print_char            # Print current char in al
  jmp loop                   # Repeat

#
# Function that uses bios function calls
# to print char to screen
#
print_char:
  movb $0x0e, %ah             # Function to print a character to the screen
  movb $0x07, %bl             # color/style to use for the character
  int  $0x10                  # Video Service Request to Bios
  ret

#
# Function used as infinite loop
#
_hang:
  jmp  _hang

.org 510
.byte 0x55, 0xAA

.end

UPDATE Using the following commands I get the following error:

mehoggan@mehoggan-laptop:~/Code/svn_scripts/assembly/bootloader/gas$ ld --oformat binary -o string string.o 
string.o: In function `_start':
(.text+0x5): relocation truncated to fit: R_X86_64_16 against `.data'
Was it helpful?

Solution

For this kind of work you should write your own linker script. Just pass it to the linker with the -T option.

My script for an almost identical problem was:

SECTIONS
{
    . = 0x1000;
    bootsec :
    {
        *(.text)
        *(.data)
        *(.rodata)
        *(.bss)
        endbootsec = .;
        . = 0x1FE;
        SHORT(0xAA55)
    }
    endbootsecw = endbootsec / 2;
    image = 0x1200;
}

With that trick you don't event need to put the 0x55 0xAA in the assembler!

The 0x1000 at the beginning: Actually all the jumps are relative, so that is not used, but it is needed later for the jump into protected mode...

endbootsecw, endbootsec and image are symbols used elsewhere in the code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top