1

What exactly does ". = 0x7c00" in a linker script do?

More specifically, when I place . = 0x7c00 at the beginning of a linker script, why doesn't the resulting output file begin with 0x7c00 = 31,744 zeros?

I understand that when a PC boots, the BIOS places the 512 byte MBR at memory address 0x7c00. However, I am confused as to how exactly the linker's location counter affects how the output file is laid out.

(For context, I'm trying to thoroughly understand the sample code from the "x86 bare metal" project. https://github.com/cirosantilli/x86-bare-metal-examples. I've included the entire linker script below for context.)

SECTIONS
{
    /*
    We could also pass the -Ttext 0x7C00 to as instead of doing this.

    If your program does not have any memory accesses, you can omit this.
    */
    . = 0x7c00;
    .text :
    {
        __start = .;

        /*
        We are going to stuff everything
        into a text segment for now, including data.
        Who cares? Other segments only exist to appease C compilers.
         */
        *(.text)

        /*
        Magic bytes. 0x1FE == 510.

        We could add this on each Gas file separately with `.word`,
        but this is the perfect place to DRY that out.
        */
        . = 0x1FE;
        SHORT(0xAA55)

        *(.stage2)

        __stage2_nsectors = ABSOLUTE((. - __start) / 512);

        . = ALIGN(512);
        __end = .;
        __end_align_4k = ALIGN(4k);
    }
}
Zack
  • 6,232
  • 8
  • 38
  • 68
  • But beware of stuff like this: https://stackoverflow.com/questions/53584666/why-does-gnu-ld-include-a-section-that-does-not-appear-in-the-linker-script I'm still trying to make the C baremetal hello world work :-( I hate linker scripts :-) – Ciro Santilli OurBigBook.com Dec 02 '18 at 23:09

1 Answers1

1

It looks like the ". = 0x7c00" is not meaning a length but an absolute address. It reads to me as 'set the current value of the special variable "." to be the hex value 0x7c00 and then it plans to use that address as an offset later in the script like with the . = ALIGN(512) it is also why it saves that address off as __start so it can then do math on the resulting image. If you manipulate . during the script so it points to the last chunk of memory added to the image then you can use it to determine the total size:

__stage2_nsectors = ABSOLUTE((. - __start) / 512);

in English would be

The difference between the starting place and wherever I ended divided by sector size.

Kelly S. French
  • 12,198
  • 10
  • 63
  • 93